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 using System.Collections;
15 using System.Security.Cryptography;
18 namespace Mono.Security {
21 // a. ITU ASN.1 standards (free download)
22 // http://www.itu.int/ITU-T/studygroups/com17/languages/
31 // RFC3280, section 4.2.1.5
32 // CAs conforming to this profile MUST always encode certificate
33 // validity dates through the year 2049 as UTCTime; certificate validity
34 // dates in 2050 or later MUST be encoded as GeneralizedTime.
35 static public ASN1 FromDateTime (DateTime dt)
39 return new ASN1 (0x17, Encoding.ASCII.GetBytes (dt.ToString ("yyMMddHHmmss") + "Z"));
43 return new ASN1 (0x18, Encoding.ASCII.GetBytes (dt.ToString ("yyyyMMddHHmmss") + "Z"));
47 static public ASN1 FromInt32 (Int32 value)
49 byte[] integer = BitConverterLE.GetBytes (value);
51 while (integer [x] == 0x00)
53 ASN1 asn1 = new ASN1 (0x02);
55 byte[] smallerInt = new byte [x + 1];
56 int index = smallerInt.Length - 1;
57 for (int i = 0; i < smallerInt.Length; i++) {
58 smallerInt [index] = integer [i];
61 asn1.Value = smallerInt;
66 static public ASN1 FromOID (string oid)
68 return new ASN1 (CryptoConfig.EncodeOID (oid));
71 static public ASN1 FromUnsignedBigInteger (byte[] integer)
73 if (integer [0] == 0x00) {
74 // this first byte is added so we're sure it's an unsigned integer
75 // however we can't feed it into RSAParameters or DSAParameters
76 int length = integer.Length + 1;
77 byte[] uinteger = new byte [length];
78 Array.Copy (integer, 0, uinteger, 1, length);
81 return new ASN1 (0x02, integer);
84 static public int ToInt32 (ASN1 asn1)
87 throw new NotSupportedException ("Only integer can be converted");
89 for (int i=0; i < asn1.Value.Length; i++)
90 x = (x << 8) + asn1.Value [i];
94 // Convert a binary encoded OID to human readable string representation of
95 // an OID (IETF style). Based on DUMPASN1.C from Peter Gutmann.
96 static public string ToOID (ASN1 asn1)
98 byte[] aOID = asn1.Value;
99 StringBuilder sb = new StringBuilder ();
100 // Pick apart the OID
101 byte x = (byte) (aOID[0] / 40);
102 byte y = (byte) (aOID[0] % 40);
104 // Handle special case for large y if x = 2
105 y += (byte) ((x - 2) * 40);
108 sb.Append (x.ToString ());
110 sb.Append (y.ToString ());
112 for (x = 1; x < aOID.Length; x++) {
113 val = ((val << 7) | ((byte) (aOID [x] & 0x7F)));
114 if ( !((aOID [x] & 0x80) == 0x80)) {
116 sb.Append (val.ToString ());
120 return sb.ToString ();
123 static public DateTime ToDateTime (ASN1 time)
125 string t = Encoding.ASCII.GetString (time.Value);
126 // to support both UTCTime and GeneralizedTime (and not so common format)
130 mask = "yyMMddHHmmZ"; // illegal I think ... must check
133 // RFC3280: 4.1.2.5.1 UTCTime
134 int year = Convert.ToInt16 (t.Substring (0, 2));
135 // Where YY is greater than or equal to 50, the
136 // year SHALL be interpreted as 19YY; and
137 // Where YY is less than 50, the year SHALL be
138 // interpreted as 20YY.
143 mask = "yyyyMMddHHmmssZ";
146 mask = "yyyyMMddHHmmssZ"; // GeneralizedTime
149 return DateTime.ParseExact (t, mask, null);