You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1032 lines
35 KiB

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)); }
}
}
}