2 // ASN1Convert.cs: Abstract Syntax Notation 1 convertion routines
5 // Sebastien Pouliot <sebastien@ximian.com>
6 // Jesper Pedersen <jep@itplus.dk>
8 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
9 // (C) 2004 Novell (http://www.novell.com)
10 // (C) 2004 IT+ A/S (http://www.itplus.dk)
14 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System
.Collections
;
38 using System
.Globalization
;
39 using System
.Security
.Cryptography
;
42 namespace Mono
.Security
{
45 // a. ITU ASN.1 standards (free download)
46 // http://www.itu.int/ITU-T/studygroups/com17/languages/
53 sealed class ASN1Convert
{
55 private ASN1Convert ()
59 // RFC3280, section 4.2.1.5
60 // CAs conforming to this profile MUST always encode certificate
61 // validity dates through the year 2049 as UTCTime; certificate validity
62 // dates in 2050 or later MUST be encoded as GeneralizedTime.
63 static public ASN1
FromDateTime (DateTime dt
)
67 return new ASN1 (0x17, Encoding
.ASCII
.GetBytes (
68 dt
.ToUniversalTime ().ToString ("yyMMddHHmmss",
69 CultureInfo
.InvariantCulture
) + "Z"));
73 return new ASN1 (0x18, Encoding
.ASCII
.GetBytes (
74 dt
.ToUniversalTime ().ToString ("yyyyMMddHHmmss",
75 CultureInfo
.InvariantCulture
) + "Z"));
79 static public ASN1
FromInt32 (Int32
value)
81 byte[] integer
= BitConverterLE
.GetBytes (value);
82 Array
.Reverse (integer
);
84 while ((x
< integer
.Length
) && (integer
[x
] == 0x00))
86 ASN1 asn1
= new ASN1 (0x02);
92 asn1
.Value
= new byte [0];
95 byte[] smallerInt
= new byte [4 - x
];
96 Buffer
.BlockCopy (integer
, x
, smallerInt
, 0, smallerInt
.Length
);
97 asn1
.Value
= smallerInt
;
103 static public ASN1
FromOid (string oid
)
106 throw new ArgumentNullException ("oid");
108 return new ASN1 (CryptoConfig
.EncodeOID (oid
));
111 static public ASN1
FromUnsignedBigInteger (byte[] big
)
114 throw new ArgumentNullException ("big");
116 if (big
[0] != 0x00) {
117 // this first byte is added so we're sure this is an unsigned integer
118 // however we can't feed it into RSAParameters or DSAParameters
119 int length
= big
.Length
+ 1;
120 byte[] uinteger
= new byte [length
];
121 Buffer
.BlockCopy (big
, 0, uinteger
, 1, length
- 1);
124 return new ASN1 (0x02, big
);
127 static public int ToInt32 (ASN1 asn1
)
130 throw new ArgumentNullException ("asn1");
131 if (asn1
.Tag
!= 0x02)
132 throw new FormatException ("Only integer can be converted");
135 for (int i
=0; i
< asn1
.Value
.Length
; i
++)
136 x
= (x
<< 8) + asn1
.Value
[i
];
140 // Convert a binary encoded OID to human readable string representation of
141 // an OID (IETF style). Based on DUMPASN1.C from Peter Gutmann.
142 static public string ToOid (ASN1 asn1
)
145 throw new ArgumentNullException ("asn1");
147 byte[] aOID
= asn1
.Value
;
148 StringBuilder sb
= new StringBuilder ();
149 // Pick apart the OID
150 byte x
= (byte) (aOID
[0] / 40);
151 byte y
= (byte) (aOID
[0] % 40);
153 // Handle special case for large y if x = 2
154 y
+= (byte) ((x
- 2) * 40);
157 sb
.Append (x
.ToString (CultureInfo
.InvariantCulture
));
159 sb
.Append (y
.ToString (CultureInfo
.InvariantCulture
));
161 for (x
= 1; x
< aOID
.Length
; x
++) {
162 val
= ((val
<< 7) | ((byte) (aOID
[x
] & 0x7F)));
163 if ( !((aOID
[x
] & 0x80) == 0x80)) {
165 sb
.Append (val
.ToString (CultureInfo
.InvariantCulture
));
169 return sb
.ToString ();
172 static public DateTime
ToDateTime (ASN1 time
)
175 throw new ArgumentNullException ("time");
177 string t
= Encoding
.ASCII
.GetString (time
.Value
);
178 // to support both UTCTime and GeneralizedTime (and not so common format)
182 mask
= "yyMMddHHmmZ"; // illegal I think ... must check
185 // RFC3280: 4.1.2.5.1 UTCTime
186 int year
= Convert
.ToInt16 (t
.Substring (0, 2), CultureInfo
.InvariantCulture
);
187 // Where YY is greater than or equal to 50, the
188 // year SHALL be interpreted as 19YY; and
189 // Where YY is less than 50, the year SHALL be
190 // interpreted as 20YY.
195 mask
= "yyyyMMddHHmmssZ";
198 mask
= "yyyyMMddHHmmssZ"; // GeneralizedTime
201 return DateTime
.ParseExact (t
, mask
, null);