public X509ContentType GetCertContentType(byte[] rawData) { ContentType contentType; unsafe { fixed (byte* pRawData = rawData) { CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pRawData); if (!Interop.crypt32.CryptQueryObject( CertQueryObjectType.CERT_QUERY_OBJECT_BLOB, &certBlob, ExpectedContentTypeFlags.CERT_QUERY_CONTENT_FLAG_ALL, ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL, 0, IntPtr.Zero, out contentType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } } return MapContentType(contentType); }
public unsafe void FindByThumbprint(byte[] thumbPrint) { fixed (byte* pThumbPrint = thumbPrint) { CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(thumbPrint.Length, pThumbPrint); FindCore(CertFindType.CERT_FIND_HASH, &blob); } }
private static StorePal FromBlobOrFile(byte[] rawData, string fileName, string password, X509KeyStorageFlags keyStorageFlags) { bool fromFile = fileName != null; unsafe { fixed (byte* pRawData = rawData) { fixed (char* pFileName = fileName) { CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(fromFile ? 0 : rawData.Length, pRawData); bool persistKeySet = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet)); PfxCertStoreFlags certStoreFlags = MapKeyStorageFlags(keyStorageFlags); void* pvObject = fromFile ? (void*)pFileName : (void*)&blob; ContentType contentType; SafeCertStoreHandle certStore; if (!Interop.crypt32.CryptQueryObject( fromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB, pvObject, StoreExpectedContentFlags, ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL, 0, IntPtr.Zero, out contentType, IntPtr.Zero, out certStore, IntPtr.Zero, IntPtr.Zero )) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } if (contentType == ContentType.CERT_QUERY_CONTENT_PFX) { certStore.Dispose(); if (fromFile) { rawData = File.ReadAllBytes(fileName); } fixed (byte* pRawData2 = rawData) { CRYPTOAPI_BLOB blob2 = new CRYPTOAPI_BLOB(rawData.Length, pRawData2); certStore = Interop.crypt32.PFXImportCertStore(ref blob2, password, certStoreFlags); if (certStore == null || certStore.IsInvalid) throw Marshal.GetLastWin32Error().ToCryptographicException(); } if (!persistKeySet) { // // If the user did not want us to persist private keys, then we should loop through all // the certificates in the collection and set our custom CERT_DELETE_KEYSET_PROP_ID property // so the key container will be deleted when the cert contexts will go away. // SafeCertContextHandle pCertContext = null; while (Interop.crypt32.CertEnumCertificatesInStore(certStore, ref pCertContext)) { CRYPTOAPI_BLOB nullBlob = new CRYPTOAPI_BLOB(0, null); if (!Interop.crypt32.CertSetCertificateContextProperty(pCertContext, CertContextPropId.CERT_DELETE_KEYSET_PROP_ID, CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, &nullBlob)) throw Marshal.GetLastWin32Error().ToCryptographicException(); } } } return new StorePal(certStore); } } } }
public byte[] Export(X509ContentType contentType, string password) { switch (contentType) { case X509ContentType.Cert: { SafeCertContextHandle pCertContext = null; if (!Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext)) return null; try { unsafe { byte[] rawData = new byte[pCertContext.CertContext->cbCertEncoded]; Marshal.Copy((IntPtr)(pCertContext.CertContext->pbCertEncoded), rawData, 0, rawData.Length); GC.KeepAlive(pCertContext); return rawData; } } finally { pCertContext.Dispose(); } } case X509ContentType.SerializedCert: { SafeCertContextHandle pCertContext = null; if (!Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext)) return null; try { int cbEncoded = 0; if (!Interop.crypt32.CertSerializeCertificateStoreElement(pCertContext, 0, null, ref cbEncoded)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; byte[] pbEncoded = new byte[cbEncoded]; if (!Interop.crypt32.CertSerializeCertificateStoreElement(pCertContext, 0, pbEncoded, ref cbEncoded)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; return pbEncoded; } finally { pCertContext.Dispose(); } } case X509ContentType.Pkcs12: { unsafe { CRYPTOAPI_BLOB dataBlob = new CRYPTOAPI_BLOB(0, (byte*)null); if (!Interop.crypt32.PFXExportCertStore(_certStore, ref dataBlob, password, PFXExportFlags.EXPORT_PRIVATE_KEYS | PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; byte[] pbEncoded = new byte[dataBlob.cbData]; fixed (byte* ppbEncoded = pbEncoded) { dataBlob.pbData = ppbEncoded; if (!Interop.crypt32.PFXExportCertStore(_certStore, ref dataBlob, password, PFXExportFlags.EXPORT_PRIVATE_KEYS | PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; } return pbEncoded; } } case X509ContentType.SerializedStore: return SaveToMemoryStore(CertStoreSaveAs.CERT_STORE_SAVE_AS_STORE); case X509ContentType.Pkcs7: return SaveToMemoryStore(CertStoreSaveAs.CERT_STORE_SAVE_AS_PKCS7); default: throw new CryptographicException(SR.Cryptography_X509_InvalidContentType); } }
private byte[] SaveToMemoryStore(CertStoreSaveAs dwSaveAs) { unsafe { CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(0, null); if (!Interop.crypt32.CertSaveStore(_certStore, CertEncodingType.All, dwSaveAs, CertStoreSaveTo.CERT_STORE_SAVE_TO_MEMORY, ref blob, 0)) throw Marshal.GetLastWin32Error().ToCryptographicException(); byte[] exportedData = new byte[blob.cbData]; fixed (byte* pExportedData = exportedData) { blob.pbData = pExportedData; if (!Interop.crypt32.CertSaveStore(_certStore, CertEncodingType.All, dwSaveAs, CertStoreSaveTo.CERT_STORE_SAVE_TO_MEMORY, ref blob, 0)) throw Marshal.GetLastWin32Error().ToCryptographicException(); } return exportedData; } }
private static ICertificatePal FromBlobOrFile(byte[] rawData, string fileName, string password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(rawData != null || fileName != null); bool loadFromFile = (fileName != null); PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags); bool persistKeySet = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet)); CertEncodingType msgAndCertEncodingType; ContentType contentType; FormatType formatType; SafeCertStoreHandle hCertStore = null; SafeCryptMsgHandle hCryptMsg = null; SafeCertContextHandle pCertContext = null; try { unsafe { fixed (byte* pRawData = rawData) { fixed (char* pFileName = fileName) { CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(loadFromFile ? 0 : rawData.Length, pRawData); CertQueryObjectType objectType = loadFromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB; void* pvObject = loadFromFile ? (void*)pFileName : (void*)&certBlob; bool success = Interop.crypt32.CryptQueryObject( objectType, pvObject, X509ExpectedContentTypeFlags, X509ExpectedFormatTypeFlags, 0, out msgAndCertEncodingType, out contentType, out formatType, out hCertStore, out hCryptMsg, out pCertContext ); if (!success) { int hr = Marshal.GetHRForLastWin32Error(); throw hr.ToCryptographicException(); } } } if (contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) { pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg); } else if (contentType == ContentType.CERT_QUERY_CONTENT_PFX) { if (loadFromFile) rawData = File.ReadAllBytes(fileName); pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); } CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer: !persistKeySet); pCertContext = null; return pal; } } finally { if (hCertStore != null) hCertStore.Dispose(); if (hCryptMsg != null) hCryptMsg.Dispose(); if (pCertContext != null) pCertContext.Dispose(); } }
private static SafeCertContextHandle FilterPFXStore(byte[] rawData, string password, PfxCertStoreFlags pfxCertStoreFlags) { SafeCertStoreHandle hStore; unsafe { fixed (byte* pbRawData = rawData) { CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pbRawData); hStore = Interop.crypt32.PFXImportCertStore(ref certBlob, password, pfxCertStoreFlags); if (hStore.IsInvalid) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; } } try { // Find the first cert with private key. If none, then simply take the very first cert. Along the way, delete the keycontainers // of any cert we don't accept. SafeCertContextHandle pCertContext = SafeCertContextHandle.InvalidHandle; SafeCertContextHandle pEnumContext = null; while (Interop.crypt32.CertEnumCertificatesInStore(hStore, ref pEnumContext)) { if (pEnumContext.ContainsPrivateKey) { if ((!pCertContext.IsInvalid) && pCertContext.ContainsPrivateKey) { // We already found our chosen one. Free up this one's key and move on. SafeCertContextHandleWithKeyContainerDeletion.DeleteKeyContainer(pEnumContext); } else { // Found our first cert that has a private key. Set him up as our chosen one but keep iterating // as we need to free up the keys of any remaining certs. pCertContext.Dispose(); pCertContext = pEnumContext.Duplicate(); } } else { if (pCertContext.IsInvalid) pCertContext = pEnumContext.Duplicate(); // Doesn't have a private key but hang on to it anyway in case we don't find any certs with a private key. } } if (pCertContext.IsInvalid) { // For compat, setting "hr" to ERROR_INVALID_PARAMETER even though ERROR_INVALID_PARAMETER is not actually an HRESULT. throw ErrorCode.ERROR_INVALID_PARAMETER.ToCryptographicException(); } return pCertContext; } finally { hStore.Dispose(); } }
public byte[] EncodeX509SubjectKeyIdentifierExtension(byte[] subjectKeyIdentifier) { unsafe { fixed (byte* pSubkectKeyIdentifier = subjectKeyIdentifier) { CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(subjectKeyIdentifier.Length, pSubkectKeyIdentifier); return Interop.crypt32.EncodeObject(Oids.SubjectKeyIdentifier, &blob); } } }
public static extern bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref CRYPTOAPI_BLOB pvSaveToPara, int dwFlags);
public static extern bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, [Out] out CRYPTOAPI_BLOB pvData, [In, Out] ref int pcbData);
public static extern int CertNameToStr(CertEncodingType dwCertEncodingType, [In] ref CRYPTOAPI_BLOB pName, CertNameStrTypeAndFlags dwStrType, StringBuilder psz, int csz);
public static extern bool PFXExportCertStore(SafeCertStoreHandle hStore, [In, Out] ref CRYPTOAPI_BLOB pPFX, String szPassword, PFXExportFlags dwFlags);
public static extern SafeCertStoreHandle PFXImportCertStore([In] ref CRYPTOAPI_BLOB pPFX, String szPassword, PfxCertStoreFlags dwFlags);