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