Do not expose the classes when they are compiled inside corlib as helpers.
[mono.git] / mcs / class / corlib / Mono.Security / ASN1Convert.cs
1 //
2 // ASN1Convert.cs: Abstract Syntax Notation 1 convertion routines
3 //
4 // Author:
5 //      Sebastien Pouliot (spouliot@motus.com)
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 //
9
10 using System;
11 using System.Collections;
12 using System.Security.Cryptography;
13 using System.Text;
14
15 namespace Mono.Security {
16
17         // References:
18         // a.   ITU ASN.1 standards (free download)
19         //      http://www.itu.int/ITU-T/studygroups/com17/languages/
20
21 #if INSIDE_CORLIB
22         internal
23 #else
24         public
25 #endif
26         class ASN1Convert {
27
28                 // RFC3280, section 4.2.1.5
29                 // CAs conforming to this profile MUST always encode certificate
30                 // validity dates through the year 2049 as UTCTime; certificate validity
31                 // dates in 2050 or later MUST be encoded as GeneralizedTime.
32                 static public ASN1 FromDateTime (DateTime dt) 
33                 {
34                         if (dt.Year < 2050) {
35                                 // UTCTIME
36                                 return new ASN1 (0x17, Encoding.ASCII.GetBytes (dt.ToString ("yyMMddHHmmss") + "Z"));
37                         }
38                         else {
39                                 // GENERALIZEDTIME
40                                 return new ASN1 (0x18, Encoding.ASCII.GetBytes (dt.ToString ("yyyyMMddHHmmss") + "Z"));
41                         }
42                 }
43
44                 static public ASN1 FromInt32 (Int32 value) 
45                 {
46                         byte[] integer = BitConverter.GetBytes (value);
47                         int x = 3;
48                         while (integer [x] == 0x00)
49                                 x--;
50                         ASN1 asn1 = new ASN1 (0x02);
51                         if (x == 3)
52                                 asn1.Value = integer;
53                         else {
54                                 byte[] smallerInt = new byte [x + 1];
55                                 Array.Copy (integer, 0, smallerInt, 0, smallerInt.Length);
56                                 asn1.Value = smallerInt;
57                         }
58                         return asn1;
59                 }
60
61                 static public ASN1 FromOID (string oid) 
62                 {
63                         return new ASN1 (CryptoConfig.EncodeOID (oid));
64                 }
65
66                 static public ASN1 FromUnsignedBigInteger (byte[] integer) 
67                 {
68                         if (integer [0] == 0x00) {
69                                 // this first byte is added so we're sure it's an unsigned integer
70                                 // however we can't feed it into RSAParameters or DSAParameters
71                                 int length = integer.Length + 1;
72                                 byte[] uinteger = new byte [length];
73                                 Array.Copy (integer, 0, uinteger, 1, length);
74                                 integer = uinteger;
75                         }
76                         return new ASN1 (0x02, integer);
77                 }
78
79                 static public int ToInt32 (ASN1 asn1) 
80                 {
81                         if (asn1.Tag != 0x02)
82                                 throw new NotSupportedException ("Only integer can be converted");
83                         int x = 0;
84                         for (int i=0; i < asn1.Value.Length; i++)
85                                 x = (x << 8) + asn1.Value [i];
86                         return x;
87                 }
88
89                 // Convert a binary encoded OID to human readable string representation of 
90                 // an OID (IETF style). Based on DUMPASN1.C from Peter Gutmann.
91                 static public string ToOID (ASN1 asn1) 
92                 {
93                         byte[] aOID = asn1.Value;
94                         StringBuilder sb = new StringBuilder ();
95                         // Pick apart the OID
96                         byte x = (byte) (aOID[0] / 40);
97                         byte y = (byte) (aOID[0] % 40);
98                         if (x > 2) {
99                                 // Handle special case for large y if x = 2
100                                 y += (byte) ((x - 2) * 40);
101                                 x = 2;
102                         }
103                         sb.Append (x.ToString ());
104                         sb.Append (".");
105                         sb.Append (y.ToString ());
106                         ulong val = 0;
107                         for (x = 1; x < aOID.Length; x++) {
108                                 val = ((val << 7) | ((byte) (aOID [x] & 0x7F)));
109                                 if ( !((aOID [x] & 0x80) == 0x80)) {
110                                         sb.Append (".");
111                                         sb.Append (val.ToString ());
112                                         val = 0;
113                                 }
114                         }
115                         return sb.ToString ();
116                 }
117
118                 static public DateTime ToDateTime (ASN1 time) 
119                 {
120                         string t = Encoding.ASCII.GetString (time.Value);
121                         // to support both UTCTime and GeneralizedTime (and not so common format)
122                         string mask = null;
123                         switch (t.Length) {
124                                 case 11:
125                                         mask = "yyMMddHHmmZ"; // illegal I think ... must check
126                                         break;
127                                 case 13: 
128                                         // RFC3280: 4.1.2.5.1  UTCTime
129                                         int year = Convert.ToInt16 (t.Substring (0, 2));
130                                         // Where YY is greater than or equal to 50, the 
131                                         // year SHALL be interpreted as 19YY; and 
132                                         // Where YY is less than 50, the year SHALL be 
133                                         // interpreted as 20YY.
134                                         if (year >= 50)
135                                                 t = "19" + t;
136                                         else
137                                                 t = "20" + t;
138                                         mask = "yyyyMMddHHmmssZ";
139                                         break;
140                                 case 15:
141                                         mask = "yyyyMMddHHmmssZ"; // GeneralizedTime
142                                         break;
143                         }
144                         return DateTime.ParseExact (t, mask, null);
145                 }
146         }
147 }