/// <summary> /// Computes the hash value of the specified byte array using the specified hash algorithm, and signs the resulting hash value. /// </summary> /// <param name="certificate">An <see cref="X509Certificate2"/> object of the signer certificate.</param> /// <param name="message">Message to be signed.</param> /// <param name="hashAlgorithm">The name of the hash algorithm to use in the signature.</param> /// <returns>The signature for the specified data.</returns> public static Byte[] SignMessage(X509Certificate2 certificate, Byte[] message, Oid hashAlgorithm) { IntPtr phCryptProv = IntPtr.Zero; UInt32 pdwKeySpec = 0; Boolean pfCallerFreeProv = false; if (!Crypt32.CryptAcquireCertificatePrivateKey(certificate.Handle, 0x00010000, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerFreeProv)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } Oid2 hashalgorithm = new Oid2( hashAlgorithm.FriendlyName.ToLower() .Replace("rsa", null) .Replace("ecdsa", null), OidGroupEnum.HashAlgorithm, true); String hashAlg; // true -> CNG, false -> legacy if (pdwKeySpec == UInt32.MaxValue) { Byte[] hashBytes = calculateHash(message, hashalgorithm, false, out hashAlg); try { UInt32 pcbResult; Int32 hresult = nCrypt.NCryptSignHash(phCryptProv, IntPtr.Zero, hashBytes, (UInt32)hashBytes.Length, null, 0, out pcbResult, 0); if (hresult != 0) { throw new CryptographicException(hresult); } Byte[] pbSignature = new byte[pcbResult]; hresult = nCrypt.NCryptSignHash(phCryptProv, IntPtr.Zero, hashBytes, (UInt32)hashBytes.Length, pbSignature, (UInt32)pbSignature.Length, out pcbResult, 0); if (hresult != 0) { throw new CryptographicException(hresult); } return(pbSignature); } finally { if (pfCallerFreeProv) { nCrypt.NCryptFreeObject(phCryptProv); } } } if (pfCallerFreeProv) { AdvAPI.CryptReleaseContext(phCryptProv, 0); } calculateHash(message, hashalgorithm, false, out hashAlg); RSACryptoServiceProvider key = (RSACryptoServiceProvider)certificate.PrivateKey; return(key.SignData(message, hashAlg)); }
/// <summary> /// Deletes private key material associated with a X.509 certificate from file system or hardware storage. /// </summary> /// <param name="cert">An instance of X.509 certificate.</param> /// <returns> /// <strong>True</strong> if associated private key was found and successfully deleted, otherwise <strong>False</strong>. /// </returns> public static Boolean DeletePrivateKey(this X509Certificate2 cert) { if (!Crypt32.CryptAcquireCertificatePrivateKey( cert.Handle, Wincrypt.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, IntPtr.Zero, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out UInt32 pdwKeySpec, out Boolean _)) { return(false); } return(pdwKeySpec == UInt32.MaxValue ? deleteCngKey(phCryptProvOrNCryptKey) : deleteLegacyKey(cert.PrivateKey)); }
public static PrivateKey ExtractKey(X509Certificate2 cert) { if (!cert.HasPrivateKey) { throw new ArgumentException("Certificate does not contain a private key.", nameof(cert)); } NCryptKeyOrCryptProviderSafeHandle handle; KeySpec keySpec; bool callerFree; var flags = PlatformSupport.HasCngSupport ? AcquirePrivateKeyFlags.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG : 0u; if (!Crypt32.CryptAcquireCertificatePrivateKey(cert.Handle, flags, IntPtr.Zero, out handle, out keySpec, out callerFree)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } handle.SetCallerFree(callerFree); return(new PrivateKey(handle, keySpec == KeySpec.NCRYPT ? KeyProviders.CNG : KeyProviders.CAPI, keySpec)); }
/// <summary> /// Computes the hash value of the specified byte array using the specified hash algorithm, and signs the resulting hash value. /// </summary> /// <param name="certificate">An <see cref="X509Certificate2"/> object of the signer certificate.</param> /// <param name="message">Message to be signed.</param> /// <param name="hashAlgorithm">The name of the hash algorithm to use in the signature. For example, 'SHA256'</param> /// <returns>The signature for the specified data.</returns> public static Byte[] SignMessage(X509Certificate2 certificate, Byte[] message, Oid hashAlgorithm) { SafeNCryptKeyHandle phCryptProv = new SafeNCryptKeyHandle(); UInt32 pdwKeySpec = 0; Boolean pfCallerFreeProv = false; if (!Crypt32.CryptAcquireCertificatePrivateKey(certificate.Handle, Wincrypt.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, IntPtr.Zero, out phCryptProv, out pdwKeySpec, out pfCallerFreeProv)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } // true -> CNG, false -> legacy if (pdwKeySpec == UInt32.MaxValue) { Byte[] hashBytes = calculateHash(message, hashAlgorithm.FriendlyName, false); try { Int32 hresult = NCrypt.NCryptSignHash(phCryptProv, IntPtr.Zero, hashBytes, hashBytes.Length, null, 0, out Int32 pcbResult, 0); if (hresult != 0) { throw new CryptographicException(hresult); } Byte[] pbSignature = new Byte[pcbResult]; hresult = NCrypt.NCryptSignHash(phCryptProv, IntPtr.Zero, hashBytes, hashBytes.Length, pbSignature, pbSignature.Length, out pcbResult, 0); if (hresult != 0) { throw new CryptographicException(hresult); } return(pbSignature); } finally { if (pfCallerFreeProv) { NCrypt.NCryptFreeObject(phCryptProv.DangerousGetHandle()); } } } if (pfCallerFreeProv) { AdvAPI.CryptReleaseContext(phCryptProv.DangerousGetHandle(), 0); } calculateHash(message, hashAlgorithm.FriendlyName, false); RSACryptoServiceProvider key = (RSACryptoServiceProvider)certificate.PrivateKey; return(key.SignData(message, hashAlgorithm.Value)); }
void acquirePrivateKey() { if (disposed) { throw new ObjectDisposedException(nameof(SignerCertificate)); } // the key is already acquired, so skip key retrieval if (checkPrivateKeyIsLoaded()) { return; } // the key is not acquired, so attempt to get it UInt32 pdwKeySpec = 0; Boolean pfCallerFreeProv = false; SafeNCryptKeyHandle phCryptProvOrNCryptKey = new SafeNCryptKeyHandle(); if (!Crypt32.CryptAcquireCertificatePrivateKey( SignerCertificate.Handle, Wincrypt.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, IntPtr.Zero, ref phCryptProvOrNCryptKey, ref pdwKeySpec, ref pfCallerFreeProv)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (pdwKeySpec == UInt32.MaxValue) { phPrivKey = phCryptProvOrNCryptKey; isCng = true; } else { // translate legacy CSP key to CNG key handle getCngHandleFromLegacy(phCryptProvOrNCryptKey); } }
void acquirePrivateKeyFromCert() { // the key is not acquired, so attempt to get it if (!Crypt32.CryptAcquireCertificatePrivateKey( SignerCertificate.Handle, Wincrypt.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, IntPtr.Zero, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out UInt32 pdwKeySpec, out Boolean _)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (pdwKeySpec == UInt32.MaxValue) { phPrivKey = phCryptProvOrNCryptKey; isCng = true; } else { // translate legacy CSP key to CNG key handle getCngHandleFromLegacy(phCryptProvOrNCryptKey); } }