internal static X509Certificate2 CopyWithPersistedCapiKey(X509Certificate2 publicCert, CspKeyContainerInfo keyContainerInfo) { if (string.IsNullOrEmpty(keyContainerInfo.KeyContainerName)) { return(null); } X509Certificate2 publicPrivate = new X509Certificate2(publicCert.RawData); var keyProvInfo = new X509Native.CRYPT_KEY_PROV_INFO(); keyProvInfo.pwszContainerName = keyContainerInfo.KeyContainerName; keyProvInfo.pwszProvName = keyContainerInfo.ProviderName; keyProvInfo.dwProvType = keyContainerInfo.ProviderType; keyProvInfo.dwKeySpec = (int)keyContainerInfo.KeyNumber; keyProvInfo.dwFlags = keyContainerInfo.MachineKeyStore ? X509Native.CRYPT_MACHINE_KEYSET : 0; using (SafeCertContextHandle certificateContext = X509Native.GetCertificateContext(publicPrivate)) { if (!X509Native.SetCertificateKeyProvInfo(certificateContext, ref keyProvInfo)) { int hr = Marshal.GetLastWin32Error(); publicPrivate.Dispose(); throw new CryptographicException(hr); } } return(publicPrivate); }
internal static X509Certificate2 CopyWithPersistedCngKey(X509Certificate2 publicCert, CngKey cngKey) { if (string.IsNullOrEmpty(cngKey.KeyName)) { return(null); } X509Certificate2 publicPrivate = new X509Certificate2(publicCert.RawData); CngProvider provider = cngKey.Provider; string keyName = cngKey.KeyName; bool machineKey = cngKey.IsMachineKey; // CAPI RSA_SIGN keys won't open correctly under CNG without the key number being specified, so // check to see if we can figure out what key number it needs to re-open. int keySpec = GuessKeySpec(provider, keyName, machineKey, cngKey.AlgorithmGroup); var keyProvInfo = new X509Native.CRYPT_KEY_PROV_INFO(); keyProvInfo.pwszContainerName = cngKey.KeyName; keyProvInfo.pwszProvName = cngKey.Provider.Provider; keyProvInfo.dwFlags = machineKey ? X509Native.CRYPT_MACHINE_KEYSET : 0; keyProvInfo.dwKeySpec = keySpec; using (SafeCertContextHandle certificateContext = X509Native.GetCertificateContext(publicPrivate)) { if (!X509Native.SetCertificateKeyProvInfo(certificateContext, ref keyProvInfo)) { int hr = Marshal.GetLastWin32Error(); publicPrivate.Dispose(); throw new CryptographicException(hr); } } return(publicPrivate); }