namespace com.hitrust.Security.Certificates { using Security; using Cryptography; using System; using System.Collections.Specialized; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; public class Certificate : ICloneable { internal CertificateInfo m_CertInfo; private CertificateChain m_Chain; internal CertificateContext m_Context; private IntPtr m_Handle; private CertificateStore m_Store; public Certificate(Certificate certificate) { this.m_Chain = null; if (certificate == null) { throw new ArgumentNullException(); } this.InitCertificate(certificate.Handle, true, null); } public Certificate(IntPtr handle) : this(handle, false) {} internal Certificate(IntPtr handle, CertificateStore store) { this.m_Chain = null; this.InitCertificate(handle, false, store); } public Certificate(IntPtr handle, bool duplicate) { this.m_Chain = null; this.InitCertificate(handle, duplicate, null); } public void AssociateWithPrivateKey(string pvkFile, string password) { this.AssociateWithPrivateKey(pvkFile, password, false); } public void AssociateWithPrivateKey(string pvkFile, string password, bool exportable) { try { if (!File.Exists(pvkFile)) { throw new FileNotFoundException("The PVK file could not be found."); } } catch (FileNotFoundException exception) { throw exception; } catch (Exception exception2) { throw new FileNotFoundException("The PVK file could not be found.", exception2); } byte[] buffer = new byte[0x18]; FileStream stream = File.Open(pvkFile, FileMode.Open, FileAccess.Read, FileShare.Read); stream.Read(buffer, 0, buffer.Length); if (BitConverter.ToUInt32(buffer, 0) != 0xb0b5f11e) { throw new CertificateException("The specified file is not a valid PVK file."); } int num = BitConverter.ToInt32(buffer, 8); int num2 = BitConverter.ToInt32(buffer, 12); int num3 = BitConverter.ToInt32(buffer, 0x10); int num4 = BitConverter.ToInt32(buffer, 20); byte[] buffer2 = new byte[num3]; byte[] buffer3 = new byte[num4]; stream.Read(buffer2, 0, buffer2.Length); stream.Read(buffer3, 0, buffer3.Length); if (num2 != 0) { if (password == null) { throw new ArgumentNullException(); } byte[] bytes = Encoding.ASCII.GetBytes(password); byte[] destinationArray = new byte[buffer2.Length + password.Length]; Array.Copy(buffer2, 0, destinationArray, 0, buffer2.Length); Array.Copy(bytes, 0, destinationArray, buffer2.Length, bytes.Length); byte[] sourceArray = this.TryDecrypt(buffer3, 8, buffer3.Length - 8, destinationArray, 0x10); if (sourceArray == null) { sourceArray = this.TryDecrypt(buffer3, 8, buffer3.Length - 8, destinationArray, 5); if (sourceArray == null) { throw new CertificateException("The PVK file could not be decrypted. [wrong password?]"); } } Array.Copy(sourceArray, 0, buffer3, 8, sourceArray.Length); Array.Clear(sourceArray, 0, sourceArray.Length); Array.Clear(bytes, 0, bytes.Length); Array.Clear(destinationArray, 0, destinationArray.Length); } int phKey = 0; int dwFlags = 0; if (exportable) { dwFlags = 1; } int phProv = 0; if (((SspiProvider.CryptAcquireContext(ref phProv, "{48959A69-B181-4cdd-B135-7565701307C5}", null, 1, 8) == 0) && (Marshal.GetLastWin32Error() == -2146893809)) && (SspiProvider.CryptAcquireContext(ref phProv, "{48959A69-B181-4cdd-B135-7565701307C5}", null, 1, 0) == 0)) { throw new CertificateException("Cannot acquire crypto service provider."); } if (SspiProvider.CryptImportKey(phProv, buffer3, buffer3.Length, 0, dwFlags, ref phKey) == 0) { throw new CertificateException("Could not import the private key from the PVK file."); } CRYPT_KEY_PROV_INFO pvData = new CRYPT_KEY_PROV_INFO { pwszContainerName = "{48959A69-B181-4cdd-B135-7565701307C5}", pwszProvName = null, dwProvType = 1, dwFlags = 0, cProvParam = 0, rgProvParam = IntPtr.Zero, dwKeySpec = num }; if (SspiProvider.CertSetCertificateContextProperty(this.Handle, 2, 0, ref pvData) == 0) { throw new CertificateException("Could not associate the private key with the certificate."); } SspiProvider.CryptDestroyKey(phKey); SspiProvider.CryptReleaseContext(phProv, 0); Array.Clear(buffer3, 0, buffer3.Length); } private string BytesToString(byte[] buffer) { string str = ""; for (int i = 0; i < buffer.Length; i++) { str = str + buffer[i].ToString("X2"); } return str; } public object Clone() { return new Certificate(SspiProvider.CertDuplicateCertificateContext(this.Handle)); } internal byte[] ConvertIntToByteArray(int dwInput) { int index = 0; byte[] buffer2 = new byte[8]; if (dwInput == 0) { return new byte[1]; } int num = dwInput; while (num > 0) { buffer2[index] = (byte)(num & 0xff); num = num >> 8; index++; } byte[] buffer = new byte[index]; if (BitConverter.IsLittleEndian) { for (int j = 0; j < index; j++) { buffer[j] = buffer2[(index - j) - 1]; } return buffer; } for (int i = 0; i < index; i++) { buffer[i] = buffer2[i]; } return buffer; } private CertificateStore CreateCertStore(bool withParents) { CertificateStore store = new CertificateStore(); if (withParents) { Certificate[] certificates = this.GetCertificateChain().GetCertificates(); for (int i = 0; i < certificates.Length; i++) { store.AddCertificate(certificates[i]); } return store; } store.AddCertificate(this); return store; } public static Certificate CreateFromBase64String(string rawString) { if (rawString == null) { throw new ArgumentNullException("rawString"); } return CreateFromCerFile(Convert.FromBase64String(rawString)); } public static Certificate CreateFromCerFile(string file) { return CertificateStore.CreateFromCerFile(file).FindCertificate(); } public static Certificate CreateFromCerFile(byte[] file) { if (file == null) { throw new ArgumentNullException(); } return CreateFromCerFile(file, 0, file.Length); } public static Certificate CreateFromCerFile(byte[] file, int offset, int size) { if (file == null) { throw new ArgumentNullException(); } if ((offset < 0) || ((offset + size) > file.Length)) { throw new ArgumentOutOfRangeException(); } IntPtr destination = Marshal.AllocHGlobal(size); Marshal.Copy(file, offset, destination, size); IntPtr handle = SspiProvider.CertCreateCertificateContext(0x10001, destination, size); Marshal.FreeHGlobal(destination); if (handle == IntPtr.Zero) { throw new CertificateException("Unable to load the specified certificate."); } return new Certificate(handle); } public static Certificate CreateFromPemFile(byte[] file) { if (file == null) { throw new ArgumentNullException(); } string cert = Encoding.ASCII.GetString(file); string certString = GetCertString(cert, "CERTIFICATE"); if (certString == null) { certString = GetCertString(cert, "X509 CERTIFICATE"); if (certString == null) { throw new CertificateException("The specified PEM file does not contain a certificate."); } } return CreateFromCerFile(Convert.FromBase64String(certString)); } public static Certificate CreateFromPemFile(string filename) { return CreateFromPemFile(CertificateStore.GetFileContents(filename)); } public static Certificate CreateFromPfxFile(string file, string password) { return CertificateStore.CreateFromPfxFile(file, password).FindCertificate(); } public static Certificate CreateFromPfxFile(byte[] file, string password) { return CertificateStore.CreateFromPfxFile(file, password).FindCertificate(); } public static Certificate CreateFromPfxFile(string file, string password, bool exportable) { return CertificateStore.CreateFromPfxFile(file, password, exportable).FindCertificate(); } public static Certificate CreateFromPfxFile(byte[] file, string password, bool exportable) { return CertificateStore.CreateFromPfxFile(file, password, exportable).FindCertificate(); } public static Certificate CreateFromPfxFile(byte[] file, string password, bool exportable, KeysetLocation location) { return CertificateStore.CreateFromPfxFile(file, password, exportable, location).FindCertificate(); } public static Certificate CreateFromPfxFile(string file, string password, bool exportable, KeysetLocation location) { return CertificateStore.CreateFromPfxFile(file, password, exportable, location).FindCertificate(); } public static Certificate CreateFromX509Certificate(X509Certificate certificate) { if (certificate == null) { throw new ArgumentNullException(); } return CreateFromCerFile(certificate.GetRawCertData()); } public static object DecodeExtension(Extension extension, int oid, Type returnType) { return DecodeExtension(extension, new IntPtr(oid), returnType); } protected static object DecodeExtension(Extension extension, IntPtr oid, Type returnType) { object obj2; if ((extension.EncodedValue == null) || (returnType == null)) { throw new ArgumentNullException(); } int pcbStructInfo = 0; if (SspiProvider.CryptDecodeObject(0x10001, oid, extension.EncodedValue, extension.EncodedValue.Length, 0, IntPtr.Zero, ref pcbStructInfo) == 0) { throw new CertificateException("Could not decode the extension."); } IntPtr pvStructInfo = Marshal.AllocHGlobal(pcbStructInfo); try { if (SspiProvider.CryptDecodeObject(0x10001, oid, extension.EncodedValue, extension.EncodedValue.Length, 0, pvStructInfo, ref pcbStructInfo) == 0) { throw new CertificateException("Could not decode the extension."); } obj2 = Activator.CreateInstance(returnType, new object[] {pvStructInfo, pcbStructInfo}); } catch (CertificateException exception) { throw exception; } catch (Exception exception2) { throw new CertificateException("Unable to instantiate the specified object type.", exception2); } finally { Marshal.FreeHGlobal(pvStructInfo); } return obj2; } public static object DecodeExtension(Extension extension, string oid, Type returnType) { object obj2; if (oid == null) { throw new ArgumentNullException("oid"); } IntPtr ptr = Marshal.StringToHGlobalAnsi(oid); try { obj2 = DecodeExtension(extension, ptr, returnType); } finally { Marshal.FreeHGlobal(ptr); } return obj2; } public virtual bool Equals(Certificate other) { if (other == null) { return false; } return (SspiProvider.CertCompareCertificate(0x10001, this.m_Context.pCertInfo, other.m_Context.pCertInfo) != 0); } public override bool Equals(object other) { bool flag; try { flag = this.Equals((Certificate)other); } catch { try { flag = this.Equals((X509Certificate)other); } catch { flag = false; } } return flag; } public virtual bool Equals(X509Certificate other) { if (other == null) { return false; } return (other.GetCertHashString() == this.GetCertHashString()); } public void ExportPrivateKey(string pvkFile, string password) { byte[] buffer2; if (!this.HasPrivateKey()) { throw new CertificateException("The certificate does not have an associated private key."); } int dwFlags = 0; int phCryptProv = 0; int pdwKeySpec = 0; int pfCallerFreeProv = 0; int phUserKey = 0; int pdwDataLen = 0; if (!Environment.UserInteractive) { dwFlags = 0x40; } if (SspiProvider.CryptAcquireCertificatePrivateKey(this.Handle, dwFlags, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerFreeProv) == 0) { throw new CertificateException("Could not acquire private key."); } if (SspiProvider.CryptGetUserKey(phCryptProv, pdwKeySpec, ref phUserKey) == 0) { throw new CertificateException("Could not retrieve a handle of the private key."); } if ((SspiProvider.CryptExportKey(phUserKey, 0, 7, 0, IntPtr.Zero, ref pdwDataLen) == 0) && (Marshal.GetLastWin32Error() != 0xea)) { throw new CertificateException("Could not export the private key."); } byte[] pbData = new byte[pdwDataLen]; if (SspiProvider.CryptExportKey(phUserKey, 0, 7, 0, pbData, ref pdwDataLen) == 0) { throw new CertificateException("Could not export the private key."); } if (pfCallerFreeProv != 0) { SspiProvider.CryptReleaseContext(phCryptProv, 0); } uint num7 = 0xb0b5f11e; int num8 = 0; int num9 = (password == null) ? 0 : 1; if (num9 == 0) { buffer2 = new byte[0]; } else { buffer2 = new byte[0x10]; new RNGCryptoServiceProvider().GetBytes(buffer2); byte[] bytes = Encoding.ASCII.GetBytes(password); SHA1 sha = SHA1.Create(); sha.TransformBlock(buffer2, 0, buffer2.Length, buffer2, 0); sha.TransformFinalBlock(bytes, 0, bytes.Length); bytes = new byte[0x10]; Array.Copy(sha.Hash, 0, bytes, 0, bytes.Length); ICryptoTransform transform = RC4.Create().CreateEncryptor(bytes, null); transform.TransformBlock(pbData, 8, pbData.Length - 8, pbData, 8); transform.Dispose(); sha.Clear(); } int length = buffer2.Length; FileStream stream = null; try { stream = File.Open(pvkFile, FileMode.Create, FileAccess.Write, FileShare.Read); stream.Write(BitConverter.GetBytes(num7), 0, 4); stream.Write(BitConverter.GetBytes(num8), 0, 4); stream.Write(BitConverter.GetBytes(pdwKeySpec), 0, 4); stream.Write(BitConverter.GetBytes(num9), 0, 4); stream.Write(BitConverter.GetBytes(length), 0, 4); stream.Write(BitConverter.GetBytes(pdwDataLen), 0, 4); if (buffer2.Length > 0) { stream.Write(buffer2, 0, buffer2.Length); } stream.Write(pbData, 0, pbData.Length); } catch (IOException exception) { throw exception; } catch (Exception exception2) { throw new IOException("An error occurs while writing the file.", exception2); } finally { if (stream != null) { stream.Close(); } } } ~Certificate() { if (this.Handle != IntPtr.Zero) { SspiProvider.CertFreeCertificateContext(this.Handle); this.m_Handle = IntPtr.Zero; } } public Extension FindExtension(string oid) { if (oid == null) { throw new ArgumentNullException(); } IntPtr ptr = SspiProvider.CertFindExtension(oid, this.m_CertInfo.cExtension, this.m_CertInfo.rgExtension); if (ptr == IntPtr.Zero) { return null; } CERT_EXTENSION cert_extension = (CERT_EXTENSION)Marshal.PtrToStructure(ptr, typeof(CERT_EXTENSION)); Extension extension = new Extension(Marshal.PtrToStringAnsi(cert_extension.pszObjId), cert_extension.fCritical != 0, new byte[cert_extension.ValuecbData]); Marshal.Copy(cert_extension.ValuepbData, extension.EncodedValue, 0, cert_extension.ValuecbData); return extension; } public byte[] GetCertHash() { return this.GetCertHash(HashType.SHA1); } public byte[] GetCertHash(HashType type) { byte[] buffer; IntPtr pvData = Marshal.AllocHGlobal(0x100); try { int pcbData = 0x100; if (((SspiProvider.CertGetCertificateContextProperty(this.Handle, (int)type, pvData, ref pcbData) == 0) || (pcbData <= 0)) || (pcbData > 0x100)) { throw new CertificateException("An error occurs while retrieving the hash of the certificate."); } buffer = new byte[pcbData]; Marshal.Copy(pvData, buffer, 0, pcbData); } catch (Exception exception) { throw exception; } finally { Marshal.FreeHGlobal(pvData); } return buffer; } public string GetCertHashString() { return this.GetCertHashString(HashType.SHA1); } public string GetCertHashString(HashType type) { return this.BytesToString(this.GetCertHash(type)); } private byte[] GetCertificateBuffer() { byte[] destination = new byte[this.m_Context.cbCertEncoded]; Marshal.Copy(this.m_Context.pbCertEncoded, destination, 0, this.m_Context.cbCertEncoded); return destination; } public CertificateChain GetCertificateChain() { if (this.m_Chain == null) { this.m_Chain = new CertificateChain(this, this.Store); } return this.m_Chain; } internal CertificateInfo GetCertificateInfo() { return this.m_CertInfo; } private static string GetCertString(string cert, string delimiter) { int index = cert.IndexOf("-----BEGIN " + delimiter + "-----"); if (index < 0) { return null; } int num2 = cert.IndexOf("-----END " + delimiter + "-----", index); if (num2 < 0) { return null; } int num3 = delimiter.Length + 0x10; int length = num2 - (index + num3); return cert.Substring(index + num3, length); } public DistinguishedName GetDistinguishedName() { return new DistinguishedName(this.m_CertInfo.SubjectpbData, this.m_CertInfo.SubjectcbData); } public DateTime GetEffectiveDate() { return DateTime.FromFileTime(this.m_CertInfo.NotBefore); } public StringCollection GetEnhancedKeyUsage() { StringCollection strings2; StringCollection strings = new StringCollection(); int pcbUsage = 0; SspiProvider.CertGetEnhancedKeyUsage(this.Handle, 0, IntPtr.Zero, ref pcbUsage); if (pcbUsage <= 0) { return strings; } IntPtr pUsage = Marshal.AllocHGlobal(pcbUsage); try { if (SspiProvider.CertGetEnhancedKeyUsage(this.Handle, 0, pUsage, ref pcbUsage) == 0) { throw new CertificateException("Could not obtain the enhanced key usage."); } TrustListUsage usage = (TrustListUsage)Marshal.PtrToStructure(pUsage, typeof(TrustListUsage)); for (int i = 0; i < usage.cUsageIdentifier; i++) { IntPtr ptr = Marshal.ReadIntPtr(usage.rgpszUsageIdentifier, i * IntPtr.Size); try { strings.Add(Marshal.PtrToStringAnsi(ptr)); } catch {} } strings2 = strings; } finally { Marshal.FreeHGlobal(pUsage); } return strings2; } public DateTime GetExpirationDate() { return DateTime.FromFileTime(this.m_CertInfo.NotAfter); } public Extension[] GetExtensions() { Extension[] extensionArray = new Extension[this.m_CertInfo.cExtension]; int num = 8 + (IntPtr.Size * 2); IntPtr rgExtension = this.m_CertInfo.rgExtension; Type structureType = typeof(CERT_EXTENSION); for (int i = 0; i < this.m_CertInfo.cExtension; i++) { CERT_EXTENSION cert_extension = (CERT_EXTENSION)Marshal.PtrToStructure(rgExtension, structureType); extensionArray[i] = new Extension(Marshal.PtrToStringAnsi(cert_extension.pszObjId), cert_extension.fCritical != 0, new byte[cert_extension.ValuecbData]); Marshal.Copy(cert_extension.ValuepbData, extensionArray[i].EncodedValue, 0, cert_extension.ValuecbData); rgExtension = new IntPtr(rgExtension.ToInt64() + num); } return extensionArray; } public string GetFormat() { return "X509"; } public override int GetHashCode() { byte[] certHash = this.GetCertHash(); byte[] destinationArray = new byte[4]; if (certHash.Length < destinationArray.Length) { Array.Copy(certHash, 0, destinationArray, 0, certHash.Length); } else { Array.Copy(certHash, 0, destinationArray, 0, destinationArray.Length); } return BitConverter.ToInt32(destinationArray, 0); } public int GetIntendedKeyUsage() { IntPtr pbKeyUsage = Marshal.AllocHGlobal(4); SspiProvider.CertGetIntendedKeyUsage(0x10001, this.m_Context.pCertInfo, pbKeyUsage, 4); byte[] destination = new byte[4]; Marshal.Copy(pbKeyUsage, destination, 0, 4); Marshal.FreeHGlobal(pbKeyUsage); return BitConverter.ToInt32(destination, 0); } public string GetIssuerName() { int cb = SspiProvider.CertGetNameString(this.Handle, 4, 0x10001, IntPtr.Zero, IntPtr.Zero, 0); if (cb <= 0) { throw new CertificateException("An error occurs while requesting the issuer name."); } IntPtr pszNameString = Marshal.AllocHGlobal(cb); SspiProvider.CertGetNameString(this.Handle, 4, 0x10001, IntPtr.Zero, pszNameString, cb); string str = Marshal.PtrToStringAnsi(pszNameString); Marshal.FreeHGlobal(pszNameString); return str; } public string GetKeyAlgorithm() { return Marshal.PtrToStringAnsi(this.m_CertInfo.SignatureAlgorithmpszObjId); } public byte[] GetKeyAlgorithmParameters() { byte[] destination = new byte[this.m_CertInfo.SignatureAlgorithmParameterscbData]; if (destination.Length > 0) { Marshal.Copy(this.m_CertInfo.SignatureAlgorithmParameterspbData, destination, 0, destination.Length); } return destination; } public string GetKeyAlgorithmParametersString() { return this.BytesToString(this.GetKeyAlgorithmParameters()); } public byte[] GetKeyIdentifier() { int pcbData = 0; SspiProvider.CertGetCertificateContextProperty(this.Handle, 20, (byte[])null, ref pcbData); byte[] pvData = new byte[pcbData]; SspiProvider.CertGetCertificateContextProperty(this.Handle, 20, pvData, ref pcbData); return pvData; } public string GetName() { int pcbStructInfo = 0; SspiProvider.CryptDecodeObject(0x10001, new IntPtr(20), this.m_CertInfo.SubjectpbData, this.m_CertInfo.SubjectcbData, 0, IntPtr.Zero, ref pcbStructInfo); if (pcbStructInfo <= 0) { throw new CertificateException("Unable to decode the name of the certificate."); } IntPtr zero = IntPtr.Zero; string str = null; try { zero = Marshal.AllocHGlobal(pcbStructInfo); if (SspiProvider.CryptDecodeObject(0x10001, new IntPtr(20), this.m_CertInfo.SubjectpbData, this.m_CertInfo.SubjectcbData, 0, zero, ref pcbStructInfo) == 0) { throw new CertificateException("Unable to decode the name of the certificate."); } IntPtr ptr = SspiProvider.CertFindRDNAttr("2.5.4.3", zero); if (ptr == IntPtr.Zero) { ptr = SspiProvider.CertFindRDNAttr("1.2.840.113549.1.9.2", zero); } if (ptr == IntPtr.Zero) { ptr = SspiProvider.CertFindRDNAttr("2.5.4.10", zero); } if (ptr != IntPtr.Zero) { RdnAttribute attribute = (RdnAttribute)Marshal.PtrToStructure(ptr, typeof(RdnAttribute)); str = Marshal.PtrToStringUni(attribute.pbData, attribute.cbData / 2); } } catch (CertificateException exception) { throw exception; } catch (Exception exception2) { throw new CertificateException("Could not get certificate attributes.", exception2); } finally { if (zero != IntPtr.Zero) { Marshal.FreeHGlobal(zero); } } if (str == null) { throw new CertificateException("Certificate does not have a name attribute."); } return str; } public byte[] GetPublicKey() { byte[] destination = new byte[this.m_CertInfo.SubjectPublicKeyInfoPublicKeycbData]; Marshal.Copy(this.m_CertInfo.SubjectPublicKeyInfoPublicKeypbData, destination, 0, destination.Length); return destination; } public int GetPublicKeyLength() { return SspiProvider.CertGetPublicKeyLength(0x10001, new IntPtr(this.m_Context.pCertInfo.ToInt64() + 0x38L)); } public string GetPublicKeyString() { return this.BytesToString(this.GetPublicKey()); } public byte[] GetRawCertData() { byte[] destination = new byte[this.m_Context.cbCertEncoded]; Marshal.Copy(this.m_Context.pbCertEncoded, destination, 0, destination.Length); return destination; } public string GetRawCertDataString() { return this.BytesToString(this.GetRawCertData()); } public byte[] GetSerialNumber() { byte[] destination = new byte[this.m_CertInfo.SerialNumbercbData]; if (destination.Length > 0) { Marshal.Copy(this.m_CertInfo.SerialNumberpbData, destination, 0, destination.Length); } return destination; } public string GetSerialNumberString() { return this.BytesToString(this.GetSerialNumber()); } public static string[] GetValidUsages(Certificate[] certificates) { string[] strArray2; if (certificates == null) { throw new ArgumentNullException(); } IntPtr zero = IntPtr.Zero; IntPtr ptr = Marshal.AllocHGlobal((int)(certificates.Length * IntPtr.Size)); try { for (int i = 0; i < certificates.Length; i++) { if (certificates[i] == null) { throw new ArgumentException(); } Marshal.WriteIntPtr(ptr, i * IntPtr.Size, certificates[i].Handle); } int cNumOIDs = 0; int pcbOIDs = 0; if (SspiProvider.CertGetValidUsages(certificates.Length, ptr, ref cNumOIDs, zero, ref pcbOIDs) == 0) { throw new CertificateException("Unable to get the valid usages."); } if (cNumOIDs == -1) { return null; } zero = Marshal.AllocHGlobal(pcbOIDs); if (SspiProvider.CertGetValidUsages(certificates.Length, ptr, ref cNumOIDs, zero, ref pcbOIDs) == 0) { throw new CertificateException("Unable to get the valid usages."); } string[] strArray = new string[cNumOIDs]; for (int j = 0; j < cNumOIDs; j++) { strArray[j] = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(zero, j * IntPtr.Size)); } strArray2 = strArray; } finally { Marshal.FreeHGlobal(ptr); if (zero != IntPtr.Zero) { Marshal.FreeHGlobal(zero); } } return strArray2; } public bool HasPrivateKey() { int phCryptProv = 0; int pdwKeySpec = 0; int pfCallerFreeProv = 0; bool flag = false; if (SspiProvider.CryptAcquireCertificatePrivateKey(this.Handle, 0x44, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerFreeProv) != 0) { flag = true; } if (pfCallerFreeProv != 0) { SspiProvider.CryptReleaseContext(phCryptProv, 0); } return flag; } private void InitCertificate(IntPtr handle, bool duplicate, CertificateStore store) { if (handle == IntPtr.Zero) { throw new ArgumentException("Invalid certificate handle!"); } if (duplicate) { this.m_Handle = SspiProvider.CertDuplicateCertificateContext(handle); } else { this.m_Handle = handle; } this.m_Context = (CertificateContext)Marshal.PtrToStructure(handle, typeof(CertificateContext)); this.m_CertInfo = (CertificateInfo)Marshal.PtrToStructure(this.m_Context.pCertInfo, typeof(CertificateInfo)); if (store == null) { this.m_Store = null; } else { this.m_Store = store; } } private void SaveToFile(byte[] buffer, string filename) { if (filename == null) { throw new ArgumentNullException(); } try { FileStream stream = File.Open(filename, FileMode.CreateNew, FileAccess.Write, FileShare.None); stream.Write(buffer, 0, buffer.Length); stream.Close(); } catch (Exception exception) { throw new IOException("Could not write data to file.", exception); } } public string ToBase64String() { byte[] inArray = this.ToCerBuffer(); return Convert.ToBase64String(inArray, 0, inArray.Length); } public byte[] ToCerBuffer() { return this.GetCertificateBuffer(); } public void ToCerFile(string filename) { this.SaveToFile(this.GetCertificateBuffer(), filename); } public byte[] ToPemBuffer() { return Encoding.ASCII.GetBytes("-----BEGIN CERTIFICATE-----\r\n" + this.ToBase64String() + "\r\n-----END CERTIFICATE-----\r\n"); } public byte[] ToPfxBuffer(string password, bool withPrivateKeys, bool withParents) { return this.CreateCertStore(withParents).ToPfxBuffer(password, withPrivateKeys); } public void ToPfxFile(string filename, string password, bool withPrivateKeys, bool withParents) { this.CreateCertStore(withParents).ToPfxFile(filename, password, withPrivateKeys); } public override string ToString() { return base.GetType().FullName; } public string ToString(bool verbose) { if (verbose) { return ("CERTIFICATE:\r\n Format: X509\r\n Name: " + this.GetName() + "\r\n Issuing CA: " + this.GetIssuerName() + "\r\n Key Algorithm: " + this.GetKeyAlgorithm() + "\r\n Serial Number: " + this.GetSerialNumberString() + "\r\n Key Alogrithm Parameters: " + this.GetKeyAlgorithmParametersString() + "\r\n Public Key: " + this.GetPublicKeyString()); } return this.ToString(); } public X509Certificate ToX509() { return new X509Certificate(SspiProvider.CertDuplicateCertificateContext(this.Handle)); } private byte[] TryDecrypt(byte[] buffer, int offset, int length, byte[] password, int keyLen) { byte[] destinationArray = new byte[0x10]; Array.Copy(SHA1.Create().ComputeHash(password, 0, password.Length), 0, destinationArray, 0, keyLen); byte[] buffer3 = RC4.Create().CreateDecryptor(destinationArray, null).TransformFinalBlock(buffer, offset, length); if (((buffer3[0] == 0x52) && (buffer3[1] == 0x53)) && ((buffer3[2] == 0x41) && (buffer3[3] == 50))) { return buffer3; } return null; } public bool VerifyRevocation(byte[] crl) { if (crl == null) { throw new ArgumentNullException(); } IntPtr pCrlContext = SspiProvider.CertCreateCRLContext(0x10001, crl, crl.Length); IntPtr zero = IntPtr.Zero; if (SspiProvider.CertFindCertificateInCRL(this.Handle, pCrlContext, 0, IntPtr.Zero, ref zero) == 0) { throw new CertificateException("Unable to search the specified CRL for the certificate."); } return (zero == IntPtr.Zero); } public IntPtr Handle { get { return this.m_Handle; } } public bool IsCurrent { get { return (SspiProvider.CertVerifyTimeValidity(IntPtr.Zero, this.m_Context.pCertInfo) == 0); } } public RSACryptoServiceProvider PrivateKey { get { int dwFlags = 0; int phCryptProv = 0; int pdwKeySpec = 0; int pfCallerFreeProv = 0; if (!Environment.UserInteractive) { dwFlags = 0x40; } if (SspiProvider.CryptAcquireCertificatePrivateKey(this.Handle, dwFlags, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerFreeProv) == 0) { throw new CertificateException("Could not acquire private key."); } if (pfCallerFreeProv != 0) { SspiProvider.CryptReleaseContext(phCryptProv, 0); } if (Environment.UserInteractive) { dwFlags = 0; } else { dwFlags = 0x40; } int pcbData = 0; if ((SspiProvider.CryptFindCertificateKeyProvInfo(this.Handle, dwFlags, IntPtr.Zero) == 0) || (SspiProvider.CertGetCertificateContextProperty(this.Handle, 2, (byte[])null, ref pcbData) == 0)) { throw new CertificateException("Could not query the associated private key."); } IntPtr pvData = Marshal.AllocHGlobal(pcbData); RSACryptoServiceProvider provider = null; try { SspiProvider.CertGetCertificateContextProperty(this.Handle, 2, pvData, ref pcbData); CRYPT_KEY_PROV_INFO crypt_key_prov_info = (CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(pvData, typeof(CRYPT_KEY_PROV_INFO)); CspParameters parameters = new CspParameters { KeyContainerName = crypt_key_prov_info.pwszContainerName, ProviderName = null, ProviderType = crypt_key_prov_info.dwProvType, KeyNumber = crypt_key_prov_info.dwKeySpec }; if ((crypt_key_prov_info.dwFlags & 0x20) != 0) { parameters.Flags = CspProviderFlags.UseMachineKeyStore; } provider = new RSACryptoServiceProvider(parameters); } catch (CertificateException exception) { throw exception; } catch (Exception exception2) { throw new CertificateException("An error occurs while accessing the certificate's private key.", exception2); } finally { Marshal.FreeHGlobal(pvData); } return provider; } } public RSACryptoServiceProvider PublicKey { get { IntPtr zero = IntPtr.Zero; int phProv = 0; int phKey = 0; RSACryptoServiceProvider provider = null; try { int dwFlags = 0; if ((!Environment.UserInteractive && (Environment.OSVersion.Platform == PlatformID.Win32NT)) && (Environment.OSVersion.Version.Major >= 5)) { dwFlags = 0x40; } if ((SspiProvider.CryptAcquireContext(ref phProv, IntPtr.Zero, null, 1, dwFlags) == 0) && (SspiProvider.CryptAcquireContext(ref phProv, IntPtr.Zero, null, 1, dwFlags | 8) == 0)) { throw new CertificateException("Could not acquire crypto context."); } CERT_PUBLIC_KEY_INFO pInfo = new CERT_PUBLIC_KEY_INFO(this.m_CertInfo); int pdwDataLen = 0; if (SspiProvider.CryptImportPublicKeyInfoEx(phProv, 0x10001, ref pInfo, 0, 0, IntPtr.Zero, ref phKey) == 0) { throw new CertificateException("Could not obtain the handle of the public key."); } if (SspiProvider.CryptExportKey(phKey, 0, 6, 0, IntPtr.Zero, ref pdwDataLen) == 0) { throw new CertificateException("Could not get the size of the key."); } zero = Marshal.AllocHGlobal(pdwDataLen); if (SspiProvider.CryptExportKey(phKey, 0, 6, 0, zero, ref pdwDataLen) == 0) { throw new CertificateException("Could not export the key."); } PUBLIC_KEY_BLOB public_key_blob = (PUBLIC_KEY_BLOB)Marshal.PtrToStructure(zero, typeof(PUBLIC_KEY_BLOB)); if (public_key_blob.magic != 0x31415352) { throw new CertificateException("This is not an RSA certificate."); } RSAParameters parameters = new RSAParameters { Exponent = this.ConvertIntToByteArray(public_key_blob.pubexp) }; IntPtr source = new IntPtr(zero.ToInt64() + Marshal.SizeOf(typeof(PUBLIC_KEY_BLOB))); parameters.Modulus = new byte[public_key_blob.bitlen / 8]; Marshal.Copy(source, parameters.Modulus, 0, parameters.Modulus.Length); Array.Reverse(parameters.Modulus); provider = new RSACryptoServiceProvider(new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore }); provider.ImportParameters(parameters); } finally { if (phKey != 0) { SspiProvider.CryptDestroyKey(phKey); } if (phProv != 0) { SspiProvider.CryptReleaseContext(phProv, 0); } if (zero != IntPtr.Zero) { Marshal.FreeHGlobal(zero); } } return provider; } } internal CertificateStore Store { get { return this.m_Store; } set { if (this.m_Store != value) { this.m_Chain = null; } this.m_Store = value; } } public bool SupportsDataEncryption { get { return (this.HasPrivateKey() && ((this.GetIntendedKeyUsage() & 0x10) != 0)); } } public bool SupportsDigitalSignature { get { return (this.HasPrivateKey() && ((this.GetIntendedKeyUsage() & 0x80) != 0)); } } } }