2 // X509Certificate20.cs: Partial class to handle new 2.0-only stuff
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2006,2008 Novell, Inc (http://www.novell.com)
9 // Copyright 2013 Xamarin Inc.
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Runtime.InteropServices;
33 using System.Security.Permissions;
37 using Mono.Security.X509;
39 using System.Runtime.Serialization;
41 namespace System.Security.Cryptography.X509Certificates {
44 [MonoTODO ("X509ContentType.SerializedCert isn't supported (anywhere in the class)")]
45 public partial class X509Certificate : IDeserializationCallback, ISerializable {
46 private string issuer_name;
47 private string subject_name;
50 public X509Certificate ()
52 // this allows an empty certificate to exists
55 public X509Certificate (byte[] rawData, string password)
57 Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
60 [MonoTODO ("SecureString support is incomplete")]
61 public X509Certificate (byte[] rawData, SecureString password)
63 Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
66 public X509Certificate (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
68 Import (rawData, password, keyStorageFlags);
71 [MonoTODO ("SecureString support is incomplete")]
72 public X509Certificate (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
74 Import (rawData, password, keyStorageFlags);
77 public X509Certificate (string fileName)
79 Import (fileName, (string)null, X509KeyStorageFlags.DefaultKeySet);
82 public X509Certificate (string fileName, string password)
84 Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
87 [MonoTODO ("SecureString support is incomplete")]
88 public X509Certificate (string fileName, SecureString password)
90 Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
93 public X509Certificate (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
95 Import (fileName, password, keyStorageFlags);
98 [MonoTODO ("SecureString support is incomplete")]
99 public X509Certificate (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
101 Import (fileName, password, keyStorageFlags);
104 public X509Certificate (SerializationInfo info, StreamingContext context)
106 byte[] raw = (byte[]) info.GetValue ("RawData", typeof (byte[]));
107 Import (raw, (string)null, X509KeyStorageFlags.DefaultKeySet);
111 public string Issuer {
114 throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
116 if (issuer_name == null)
117 issuer_name = X501.ToString (x509.GetIssuerName (), true, ", ", true);
122 public string Subject {
125 throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
127 if (subject_name == null)
128 subject_name = X501.ToString (x509.GetSubjectName (), true, ", ", true);
134 public IntPtr Handle {
135 get { return IntPtr.Zero; }
140 public override bool Equals (object obj)
142 X509Certificate x = (obj as X509Certificate);
144 return this.Equals (x);
148 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported")]
150 public virtual byte[] Export (X509ContentType contentType)
152 return Export (contentType, (byte[])null);
155 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported")]
157 public virtual byte[] Export (X509ContentType contentType, string password)
159 byte[] pwd = (password == null) ? null : Encoding.UTF8.GetBytes (password);
160 return Export (contentType, pwd);
163 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported. SecureString support is incomplete.")]
164 public virtual byte[] Export (X509ContentType contentType, SecureString password)
166 byte[] pwd = (password == null) ? null : password.GetBuffer ();
167 return Export (contentType, pwd);
170 internal byte[] Export (X509ContentType contentType, byte[] password)
173 throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
176 switch (contentType) {
177 case X509ContentType.Cert:
179 case X509ContentType.Pfx: // this includes Pkcs12
181 throw new NotSupportedException ();
182 case X509ContentType.SerializedCert:
184 throw new NotSupportedException ();
186 string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
187 throw new CryptographicException (msg);
192 if (password != null)
193 Array.Clear (password, 0, password.Length);
198 public virtual void Import (byte[] rawData)
200 Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
203 private Mono.Security.X509.X509Certificate ImportPkcs12 (byte[] rawData, string password)
205 var pfx = (password == null) ? new Mono.Security.X509.PKCS12 (rawData) : new Mono.Security.X509.PKCS12 (rawData, password);
206 if (pfx.Certificates.Count == 0) {
207 // no certificate was found
209 } else if (pfx.Keys.Count == 0) {
210 // no key were found - pick the first certificate
211 return pfx.Certificates [0];
213 // find the certificate that match the first key
214 var keypair = (pfx.Keys [0] as AsymmetricAlgorithm);
215 string pubkey = keypair.ToXmlString (false);
216 foreach (var c in pfx.Certificates) {
217 if ((c.RSA != null) && (pubkey == c.RSA.ToXmlString (false)))
219 if ((c.DSA != null) && (pubkey == c.DSA.ToXmlString (false)))
222 return pfx.Certificates [0]; // no match, pick first certificate without keys
226 [MonoTODO ("missing KeyStorageFlags support")]
228 public virtual void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
231 if (password == null) {
233 x509 = new Mono.Security.X509.X509Certificate (rawData);
235 catch (Exception e) {
237 x509 = ImportPkcs12 (rawData, null);
240 string msg = Locale.GetText ("Unable to decode certificate.");
241 // inner exception is the original (not second) exception
242 throw new CryptographicException (msg, e);
248 x509 = ImportPkcs12 (rawData, password);
251 // it's possible to supply a (unrequired/unusued) password
253 x509 = new Mono.Security.X509.X509Certificate (rawData);
258 [MonoTODO ("SecureString support is incomplete")]
259 public virtual void Import (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
261 Import (rawData, (string)null, keyStorageFlags);
265 public virtual void Import (string fileName)
267 byte[] rawData = File.ReadAllBytes (fileName);
268 Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
271 [MonoTODO ("missing KeyStorageFlags support")]
273 public virtual void Import (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
275 byte[] rawData = File.ReadAllBytes (fileName);
276 Import (rawData, password, keyStorageFlags);
279 [MonoTODO ("SecureString support is incomplete, missing KeyStorageFlags support")]
280 public virtual void Import (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
282 byte[] rawData = File.ReadAllBytes (fileName);
283 Import (rawData, (string)null, keyStorageFlags);
286 void IDeserializationCallback.OnDeserialization (object sender)
290 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
292 // will throw a NRE if info is null (just like MS implementation)
293 info.AddValue ("RawData", x509.RawData);
297 public virtual void Reset ()
303 cachedCertificateHash = null;