2006-10-08 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System / System.Security.Cryptography.X509Certificates / X509Certificate2.cs
1 //
2 // System.Security.Cryptography.X509Certificate2 class
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 #if NET_2_0 && SECURITY_DEP
31
32 using System.IO;
33 using System.Text;
34 using Mono.Security.Cryptography;
35 using MX = Mono.Security.X509;
36
37 namespace System.Security.Cryptography.X509Certificates {
38
39         public class X509Certificate2 : X509Certificate {
40
41                 private bool _archived;
42                 private X509ExtensionCollection _extensions;
43                 private string _name;
44                 private string _serial;
45                 private PublicKey _publicKey;
46                 X500DistinguishedName _issuer_name;
47
48                 private MX.X509Certificate _cert;
49
50                 // constructors
51
52                 public X509Certificate2 () : base () 
53                 {
54                         _cert = null;
55                 }
56
57                 public X509Certificate2 (byte[] rawData) : base (rawData) 
58                 {
59                         _cert = new MX.X509Certificate (base.GetRawCertData ());
60                 }
61
62                 public X509Certificate2 (byte[] rawData, string password) : base (rawData, password) 
63                 {
64                         Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
65                 }
66
67                 public X509Certificate2 (byte[] rawData, SecureString password) : base (rawData, password) 
68                 {
69                         Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
70                 }
71
72                 public X509Certificate2 (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
73                         : base (rawData, password, keyStorageFlags) 
74                 {
75                         Import (rawData, password, keyStorageFlags);
76                 }
77
78                 public X509Certificate2 (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
79                         : base (rawData, password, keyStorageFlags) 
80                 {
81                         Import (rawData, password, keyStorageFlags);
82                 }
83
84                 public X509Certificate2 (string fileName) : base (fileName) 
85                 {
86                         _cert = new MX.X509Certificate (base.GetRawCertData ());
87                 }
88
89                 public X509Certificate2 (string fileName, string password)
90                         : base (fileName, password)
91                 {
92                         Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
93                 }
94
95                 public X509Certificate2 (string fileName, SecureString password)
96                         : base (fileName, password)
97                 {
98                         Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
99                 }
100
101                 public X509Certificate2 (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
102                         : base (fileName, password, keyStorageFlags) 
103                 {
104                         Import (fileName, password, keyStorageFlags);
105                 }
106
107                 public X509Certificate2 (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
108                         : base (fileName, password, keyStorageFlags) 
109                 {
110                         Import (fileName, password, keyStorageFlags);
111                 }
112
113                 public X509Certificate2 (IntPtr handle) : base (handle) 
114                 {
115                         _cert = new MX.X509Certificate (base.GetRawCertData ());
116                 }
117
118                 public X509Certificate2 (X509Certificate certificate) 
119                         : base (certificate)
120                 {
121                         _cert = new MX.X509Certificate (base.GetRawCertData ());
122                 }
123
124                 // properties
125
126                 public bool Archived {
127                         get { return _archived; }
128                         set { _archived = value; }
129                 }
130
131                 public X509ExtensionCollection Extensions {
132                         get { return _extensions; }
133                 }
134
135                 public string FriendlyName {
136                         get { return _name; }
137                         set { _name = value; }
138                 }
139
140                 [MonoTODO ("Probably it could be more efficient")]
141                 public bool HasPrivateKey {
142                         get { return PrivateKey != null; }
143                 }
144
145                 [MonoTODO]
146                 public X500DistinguishedName IssuerName {
147                         get {
148                                 if (_issuer_name == null)
149                                         _issuer_name = new X500DistinguishedName (Issuer);
150                                 return _issuer_name;
151                         }
152                 } 
153
154                 public DateTime NotAfter {
155                         get { return _cert.ValidUntil; }
156                 }
157
158                 public DateTime NotBefore {
159                         get { return _cert.ValidFrom; }
160                 }
161
162                 public AsymmetricAlgorithm PrivateKey {
163                         get {
164                                 if (_cert.RSA != null) {
165                                         RSACryptoServiceProvider rcsp = _cert.RSA as RSACryptoServiceProvider;
166                                         if (rcsp != null)
167                                                 return rcsp.PublicOnly ? null : rcsp;
168                                         RSAManaged rsam = _cert.RSA as RSAManaged;
169                                         if (rsam != null)
170                                                 return rsam.PublicOnly ? null : rsam;
171                                         try {
172                                                 _cert.RSA.ExportParameters (true);
173                                                 return _cert.RSA;
174                                         } catch (CryptographicException) {
175                                                 return null;
176                                         }
177                                 }
178                                 else if (_cert.DSA != null) {
179                                         DSACryptoServiceProvider dcsp = _cert.DSA as DSACryptoServiceProvider;
180                                         if (dcsp != null)
181                                                 return dcsp.PublicOnly ? null : dcsp;
182                                         try {
183                                                 _cert.DSA.ExportParameters (true);
184                                                 return _cert.DSA;
185                                         } catch (CryptographicException) {
186                                                 return null;
187                                         }
188                                 }
189                                 return null;
190                         }
191                         set {
192                                 if (value is RSA)
193                                         _cert.RSA = (RSA) value;
194                                 else if (value is DSA)
195                                         _cert.DSA = (DSA) value;
196                                 else
197                                         throw new NotSupportedException ();
198                         }
199                 } 
200
201                 public PublicKey PublicKey {
202                         get { 
203                                 if (_publicKey == null) {
204                                         _publicKey = new PublicKey (_cert);
205                                 }
206                                 return _publicKey;
207                         }
208                 } 
209
210                 public byte[] RawData {
211                         get {
212                                 if (_cert == null) {
213                                         throw new CryptographicException (Locale.GetText ("No certificate data."));
214                                 }
215                                 return base.GetRawCertData ();
216                         }
217                 } 
218
219                 public string SerialNumber {
220                         get { 
221                                 if (_serial == null) {
222                                         StringBuilder sb = new StringBuilder ();
223                                         byte[] serial = _cert.SerialNumber;
224                                         for (int i=serial.Length - 1; i >= 0; i--)
225                                                 sb.Append (serial [i].ToString ("X2"));
226                                         _serial = sb.ToString ();
227                                 }
228                                 return _serial; 
229                         }
230                 } 
231
232                 public Oid SignatureAlgorithm {
233                         get { return null; }
234                 } 
235
236                 [MonoTODO]
237                 public X500DistinguishedName SubjectName {
238                         get { return null; }
239                 } 
240
241                 public string Thumbprint {
242                         get { return base.GetCertHashString (); }
243                 } 
244
245                 public int Version {
246                         get { return _cert.Version; }
247                 }
248
249                 // methods
250
251                 [MonoTODO]
252                 public string GetNameInfo (X509NameType nameType, bool forIssuer) 
253                 {
254                         return null;
255                 }
256
257                 public override void Import (byte[] rawData) 
258                 {
259                         Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
260                 }
261
262                 [MonoTODO ("missing KeyStorageFlags support")]
263                 public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
264                 {
265                         base.Import (rawData, password, keyStorageFlags);
266                         if (password == null) {
267                                 _cert = new Mono.Security.X509.X509Certificate (rawData);
268                                 // TODO - PKCS12 without password
269                         } else {
270                                 // try PKCS#12
271                                 try {
272                                         MX.PKCS12 pfx = new MX.PKCS12 (rawData, password);
273                                         if (pfx.Certificates.Count > 0) {
274                                                 _cert = pfx.Certificates [0];
275                                         } else {
276                                                 _cert = null;
277                                         }
278                                         if (pfx.Keys.Count > 0) {
279                                                 _cert.RSA = (pfx.Keys [0] as RSA);
280                                                 _cert.DSA = (pfx.Keys [0] as DSA);
281                                         }
282                                 }
283                                 catch {
284                                         // it's possible to supply a (unrequired/unusued) password
285                                         // fix bug #79028
286                                         _cert = new Mono.Security.X509.X509Certificate (rawData);
287                                 }
288                         }
289                 }
290
291                 [MonoTODO ("SecureString is incomplete")]
292                 public override void Import (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
293                 {
294                         Import (rawData, (string) null, keyStorageFlags);
295                 }
296
297                 public override void Import (string fileName) 
298                 {
299                         byte[] rawData = Load (fileName);
300                         Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
301                 }
302
303                 [MonoTODO ("missing KeyStorageFlags support")]
304                 public override void Import (string fileName, string password, X509KeyStorageFlags keyStorageFlags) 
305                 {
306                         byte[] rawData = Load (fileName);
307                         Import (rawData, password, keyStorageFlags);
308                 }
309
310                 [MonoTODO ("SecureString is incomplete")]
311                 public override void Import (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags) 
312                 {
313                         byte[] rawData = Load (fileName);
314                         Import (rawData, (string)null, keyStorageFlags);
315                 }
316
317                 private byte[] Load (string fileName)
318                 {
319                         byte[] data = null;
320                         using (FileStream fs = File.OpenRead (fileName)) {
321                                 data = new byte [fs.Length];
322                                 fs.Read (data, 0, data.Length);
323                                 fs.Close ();
324                         }
325                         return data;
326                 }
327
328                 public override void Reset () 
329                 {
330                         _serial = null;
331                         _publicKey = null;
332                         base.Reset ();
333                 }
334
335                 [MonoTODO]
336                 public override string ToString ()
337                 {
338                         return null;
339                 }
340
341                 [MonoTODO]
342                 public override string ToString (bool verbose)
343                 {
344                         return null;
345                 }
346
347                 [MonoTODO]
348                 public bool Verify ()
349                 {
350                         X509Chain chain = new X509Chain ();
351                         if (!chain.Build (this))
352                                 return false;
353                         // TODO - check chain and other stuff ???
354                         return true;
355                 }
356
357                 // static methods
358
359                 [MonoTODO]
360                 public static X509ContentType GetCertContentType (byte[] rawData)
361                 {
362                         return X509ContentType.Unknown;
363                 }
364
365                 [MonoTODO]
366                 public static X509ContentType GetCertContentType (string fileName)
367                 {
368                         return X509ContentType.Unknown;
369                 }
370         }
371 }
372
373 #endif