void getCngHandleFromLegacy(SafeHandle phCryptProvOrNCryptKey) { // attempt to translate legacy HCRYPTPROV handle to CNG key handle Int32 hresult = nCrypt.NCryptTranslateHandle( IntPtr.Zero, out SafeNCryptKeyHandle cngKey, phCryptProvOrNCryptKey.DangerousGetHandle(), IntPtr.Zero, (UInt32)X509KeySpecFlags.AT_SIGNATURE, 0); // release legacy HCRYPTPROV handle AdvAPI.CryptReleaseContext(phCryptProvOrNCryptKey.DangerousGetHandle(), 0); if (hresult == 0) { // if key is successfully translated, assign new CNG key handle to phPrivKey phPrivKey = cngKey; isCng = true; } else { // if key translation failed, then switch to legacy RSA/DSACryptoServiceProvider isCng = false; legacyKey = SignerCertificate.PrivateKey; } }
static CspCollection m_enumprovs() { Hashtable ProvTypes = get_provtypes(); StringBuilder pszProvName = new StringBuilder(); CspCollection csps = new CspCollection(); UInt32 dwIndex = 0; UInt32 pdwProvType = 0; UInt32 pcbProvName = 0; while (AdvAPI.CryptEnumProviders(dwIndex, 0, 0, ref pdwProvType, null, ref pcbProvName)) { pszProvName.Length = (Int32)pcbProvName; // retrieve CSP if (!AdvAPI.CryptEnumProviders(dwIndex++, 0, 0, ref pdwProvType, pszProvName, ref pcbProvName)) { throw new Win32Exception(Error.InvalidDataException); } String name = pszProvName.ToString(); String pType = (String)ProvTypes[pdwProvType]; IntPtr phProv = IntPtr.Zero; // retrieve CSP context if (!AdvAPI.CryptAcquireContext(ref phProv, null, name, pdwProvType, Wincrypt.CRYPT_VERIFYCONTEXT)) { throw new Win32Exception(Error.InavlidHandleException); } Int32 pdwDataLen = 0; ALG_IDCollection algs = new ALG_IDCollection(); if (AdvAPI.CryptGetProvParam(phProv, 0x16, null, ref pdwDataLen, Wincrypt.CRYPT_FIRST)) { Byte[] pbData = new Byte[Marshal.SizeOf(typeof(Wincrypt.PROV_ENUMALGS_EX))]; while (AdvAPI.CryptGetProvParam(phProv, 0x16, pbData, ref pdwDataLen, Wincrypt.CRYPT_NEXT)) { IntPtr ptr = Marshal.AllocHGlobal(pbData.Length); Marshal.Copy(pbData, 0, ptr, pbData.Length); Wincrypt.PROV_ENUMALGS_EX AlgStructure = (Wincrypt.PROV_ENUMALGS_EX)Marshal.PtrToStructure(ptr, typeof(Wincrypt.PROV_ENUMALGS_EX)); Marshal.FreeHGlobal(ptr); ALG_ID alg = get_algparams(AlgStructure); algs.Add(alg); } csps.Add(new CspLegacy(name, pType, algs)); } else { csps.Add(new CspLegacy(name, pType, algs)); } AdvAPI.CryptReleaseContext(phProv, 0); } return(csps); }
/// <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> /// 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)); }