public static void DeleteKeyContainer(SafeCertContextHandle pCertContext) { if (pCertContext.IsInvalid) { return; } int cb = 0; bool containsPrivateKey = Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cb); if (!containsPrivateKey) { return; } byte[] provInfoAsBytes = new byte[cb]; if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, provInfoAsBytes, ref cb)) { return; } unsafe { fixed(byte *pProvInfoAsBytes = provInfoAsBytes) { CRYPT_KEY_PROV_INFO *pProvInfo = (CRYPT_KEY_PROV_INFO *)pProvInfoAsBytes; string providerName = pwszToString((IntPtr)(pProvInfo->pwszProvName)); string keyContainerName = pwszToString((IntPtr)(pProvInfo->pwszContainerName)); if (pProvInfo->dwProvType == 0) { // dwProvType being 0 indicates that the key is stored in CNG. // dwProvType being non-zero indicates that the key is stored in CAPI. try { using (CngKey cngKey = CngKey.Open(keyContainerName, new CngProvider(providerName))) { cngKey.Delete(); } } catch (CryptographicException) { // While leaving the file on disk is undesirable, an inability to perform this cleanup // should not manifest itself to a user. } } else { CryptAcquireContextFlags flags = (pProvInfo->dwFlags & CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) | CryptAcquireContextFlags.CRYPT_DELETEKEYSET; IntPtr hProv; bool success = Interop.cryptoapi.CryptAcquireContext(out hProv, keyContainerName, providerName, pProvInfo->dwProvType, flags); // Called CryptAcquireContext solely for the side effect of deleting the key containers. When called with these flags, no actual // hProv is returned (so there's nothing to clean up.) Debug.Assert(hProv == IntPtr.Zero); } } } }
public static void VerifyMachineKey( CngAlgorithm algorithm, int plainBytesCount, Func <string, SymmetricAlgorithm> persistedFunc, Func <SymmetricAlgorithm> ephemeralFunc) { string keyName = Guid.NewGuid().ToString(); CngKeyCreationParameters creationParameters = new CngKeyCreationParameters { Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider, ExportPolicy = CngExportPolicies.AllowPlaintextExport, KeyCreationOptions = CngKeyCreationOptions.MachineKey, }; CngKey cngKey = CngKey.Create(algorithm, keyName, creationParameters); try { VerifyPersistedKey( keyName, plainBytesCount, persistedFunc, ephemeralFunc, CipherMode.CBC, PaddingMode.PKCS7); } finally { // Delete also Disposes the key, no using should be added here. cngKey.Delete(); } }
//[Fact] - Keeping this test for reference but we don't want to run it as an inner-loop test because // it creates a key on disk. public static void AesRoundTrip256BitsNoneECBUsingStoredKey() { CngAlgorithm algname = new CngAlgorithm("AES"); string keyName = "CoreFxTest-" + Guid.NewGuid(); CngKey _cngKey = CngKey.Create(algname, keyName); try { using (Aes alg = new AesCng(keyName)) { try { alg.Padding = PaddingMode.None; alg.Mode = CipherMode.ECB; int keySize = alg.KeySize; byte[] plainText = "15a818701f0f7c99fe4b1b4b860f131b".HexToByteArray(); byte[] cipher = alg.Encrypt(plainText); byte[] decrypted = alg.Decrypt(cipher); byte[] expectedDecrypted = "15a818701f0f7c99fe4b1b4b860f131b".HexToByteArray(); Assert.Equal <byte>(expectedDecrypted, decrypted); } catch (Exception e) { Console.WriteLine(e.Message); } } } finally { _cngKey.Delete(); } }
public static void RemoveKeyFromCng(string providerName, string containerName) { CngProvider cngProvider = new CngProvider(providerName); CngKey cngKey = CngKey.Open(containerName, cngProvider); cngKey.Delete(); }
public static void DeleteKeyContainer(SafeCertContextHandle pCertContext) { if (pCertContext.IsInvalid) { return; } int cb = 0; bool containsPrivateKey = Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, null, ref cb); if (!containsPrivateKey) { return; } byte[] provInfoAsBytes = new byte[cb]; if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, provInfoAsBytes, ref cb)) { return; } unsafe { fixed(byte *pProvInfoAsBytes = provInfoAsBytes) { CRYPT_KEY_PROV_INFO *pProvInfo = (CRYPT_KEY_PROV_INFO *)pProvInfoAsBytes; // For UWP the key was opened in a CNG-only context, so it can/should be deleted via CngKey.Delete. // In all other contexts, the key was loaded into CAPI, so deleting it via CryptAcquireContext is // the correct action. #if NETNATIVE string providerName = Marshal.PtrToStringUni((IntPtr)(pProvInfo->pwszProvName)); string keyContainerName = Marshal.PtrToStringUni((IntPtr)(pProvInfo->pwszContainerName)); try { using (CngKey cngKey = CngKey.Open(keyContainerName, new CngProvider(providerName))) { cngKey.Delete(); } } catch (CryptographicException) { // While leaving the file on disk is undesirable, an inability to perform this cleanup // should not manifest itself to a user. } #else CryptAcquireContextFlags flags = (pProvInfo->dwFlags & CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET) | CryptAcquireContextFlags.CRYPT_DELETEKEYSET; IntPtr hProv; bool success = Interop.advapi32.CryptAcquireContext(out hProv, pProvInfo->pwszContainerName, pProvInfo->pwszProvName, pProvInfo->dwProvType, flags); // Called CryptAcquireContext solely for the side effect of deleting the key containers. When called with these flags, no actual // hProv is returned (so there's nothing to clean up.) Debug.Assert(hProv == IntPtr.Zero); #endif } } }
public static void DeleteAESKey(string keyName) { if (CngKey.Exists(keyName, CngProvider.MicrosoftSoftwareKeyStorageProvider)) { Console.WriteLine("Deleting Existing Key -:" + keyName); CngKey deleteKey = CngKey.Open(keyName, CngProvider.MicrosoftSoftwareKeyStorageProvider); deleteKey.Delete(); } }
public static void AssociatePersistedKey_CNG_DSA() { const string KeyName = nameof(AssociatePersistedKey_CNG_DSA); CngKey cngKey = null; HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA256; byte[] signature; try { CngKeyCreationParameters creationParameters = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.None, Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider, KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, Parameters = { new CngProperty("Length", BitConverter.GetBytes(1024), CngPropertyOptions.None), } }; cngKey = CngKey.Create(new CngAlgorithm("DSA"), KeyName, creationParameters); using (DSACng dsaCng = new DSACng(cngKey)) { X509SignatureGenerator dsaGen = new DSAX509SignatureGenerator(dsaCng); CertificateRequest request = new CertificateRequest( new X500DistinguishedName($"CN={KeyName}"), dsaGen.PublicKey, HashAlgorithmName.SHA256); DateTimeOffset now = DateTimeOffset.UtcNow; using (X509Certificate2 cert = request.Create(request.SubjectName, dsaGen, now, now.AddDays(1), new byte[1])) using (X509Certificate2 certWithPrivateKey = cert.CopyWithPrivateKey(dsaCng)) using (DSA dsa = certWithPrivateKey.GetDSAPrivateKey()) { signature = dsa.SignData(Array.Empty <byte>(), hashAlgorithm); Assert.True(dsaCng.VerifyData(Array.Empty <byte>(), signature, hashAlgorithm)); } } // Some certs have disposed, did they delete the key? using (CngKey stillPersistedKey = CngKey.Open(KeyName, CngProvider.MicrosoftSoftwareKeyStorageProvider)) using (DSACng dsaCng = new DSACng(stillPersistedKey)) { dsaCng.SignData(Array.Empty <byte>(), hashAlgorithm); } } finally { cngKey?.Delete(); } }
public static void RemoveKeyFromCng(string providerName, string containerName) { #if NET5_0_OR_GREATER System.Diagnostics.Debug.Assert(OperatingSystem.IsWindows()); #endif CngProvider cngProvider = new CngProvider(providerName); CngKey cngKey = CngKey.Open(containerName, cngProvider); cngKey.Delete(); }
public X509Certificate2 CreateNamedKeyCertificate(CertData data) { try { CngKeyCreationParameters keyCreationParameters = new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowPlaintextArchiving | CngExportPolicies.AllowArchiving, KeyUsage = CngKeyUsages.AllUsages }; X509Certificate2 cert; X509CertificateCreationParameters configCreate = new X509CertificateCreationParameters(new X500DistinguishedName(data.DistinguishedName)) { EndTime = DateTime.Parse("01/01/2020", System.Globalization. DateTimeFormatInfo. InvariantInfo), StartTime = DateTime.Parse("01/01/2010", System.Globalization. DateTimeFormatInfo. InvariantInfo) }; using (CngKey namedKey = CngKey.Create(CngAlgorithm2.Rsa, data.Key, keyCreationParameters)) { cert = namedKey.CreateSelfSignedCertificate(configCreate); cert.FriendlyName = data.Friendlyname; Assert.True(cert.HasPrivateKey); Assert.True(cert.HasCngKey()); using (CngKey certKey = cert.GetCngPrivateKey()) { Assert.Equal(CngAlgorithm2.Rsa, certKey.Algorithm); } } return(cert); } finally { if (CngKey.Exists(data.Key)) { using (CngKey key = CngKey.Open(data.Key)) { key.Delete(); } } } }
private void btnDecrypt_Click(object sender, EventArgs e) { string sRet = ""; byte[] bytIn = Convert.FromBase64String(tbCipher.Text); tbHexData.Text = ByteArrayToString(bytIn); if (cbAlg.SelectedIndex == 0) // AES { MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length); SymmetricAlgorithm symAlg = new RijndaelManaged(); symAlg.KeySize = 32 * 8; symAlg.BlockSize = 16 * 8; symAlg.Mode = CipherMode.CBC; symAlg.Padding = PaddingMode.PKCS7; symAlg.Key = GetLegalKey(symAlg); symAlg.IV = GetLegalIV(symAlg); ICryptoTransform encrypto = symAlg.CreateDecryptor(); CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read); StreamReader sr = new StreamReader(cs); sRet = sr.ReadToEnd(); } else if (cbAlg.SelectedIndex == 1) // RSA { //声明一个RSA算法的实例,指定了密钥长度为1024位,会自动生成密钥信息。 RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(1024); rsaProvider.FromXmlString(tbKey2.Text); //将私钥导入到RSA对象 byte[] bytOut = rsaProvider.Decrypt(bytIn, false); //对数据data解密,并返回加密结果; sRet = Encoding.UTF8.GetString(bytOut); } else if (cbAlg.SelectedIndex == 2) // ECC { CngKey decKey = CngKey.Import(Convert.FromBase64String(txPrvKey.Text), CngKeyBlobFormat.EccPrivateBlob); ECDiffieHellmanCng decoder = new ECDiffieHellmanCng(decKey); decoder.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash; decoder.HashAlgorithm = CngAlgorithm.Sha256; Aes aes = new AesCryptoServiceProvider(); aes.IV = Convert.FromBase64String(this.tbKey2.Text); CngKey k = CngKey.Import(Convert.FromBase64String(this.tbKey1.Text), CngKeyBlobFormat.EccPublicBlob); aes.Key = decoder.DeriveKeyMaterial(k); MemoryStream plaintext = new MemoryStream(); using (CryptoStream cs = new CryptoStream(plaintext, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(bytIn, 0, bytIn.Length); cs.Close(); sRet = Encoding.UTF8.GetString(plaintext.ToArray()); } decKey.Delete(); } textContent.Text = sRet; }
public static void ClearRSAKey() { if (CngKey.Exists(PRIVATE_KEY)) { using (CngKey algorithmKey = CngKey.Open(PRIVATE_KEY)) { algorithmKey.Delete(); } } ; }
public static void AssociatePersistedKey_CNG_RSA() { const string KeyName = nameof(AssociatePersistedKey_CNG_RSA); CngKey cngKey = null; HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA256; byte[] signature; try { CngKeyCreationParameters creationParameters = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.None, Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider, KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, }; cngKey = CngKey.Create(CngAlgorithm.Rsa, KeyName, creationParameters); using (RSACng rsaCng = new RSACng(cngKey)) { CertificateRequest request = new CertificateRequest( $"CN={KeyName}", rsaCng, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); DateTimeOffset now = DateTimeOffset.UtcNow; using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) using (RSA rsa = cert.GetRSAPrivateKey()) { signature = rsa.SignData(Array.Empty <byte>(), hashAlgorithm, RSASignaturePadding.Pkcs1); Assert.True( rsaCng.VerifyData(Array.Empty <byte>(), signature, hashAlgorithm, RSASignaturePadding.Pkcs1)); } } // Some certs have disposed, did they delete the key? using (CngKey stillPersistedKey = CngKey.Open(KeyName, CngProvider.MicrosoftSoftwareKeyStorageProvider)) using (RSACng rsaCng = new RSACng(stillPersistedKey)) { byte[] signature2 = rsaCng.SignData(Array.Empty <byte>(), hashAlgorithm, RSASignaturePadding.Pkcs1); Assert.Equal(signature, signature2); } } finally { cngKey?.Delete(); } }
/// <summary> /// Will destroy the key with keyname within the given provider with providerName. Will throw CryptographicException if either Provider or Key don't exist /// </summary> /// <param name="providerName">Name of the provider</param> /// <param name="keyName">Name of the key to destroy</param> public void DestroyLocalRSAKey(string providerName, string keyName) { CngProvider provider = new CngProvider(providerName); if (CngKey.Exists(keyName, provider)) { using (CngKey key = CngKey.Open(keyName, provider)) { key.Delete(); } } }
public static void AssociatePersistedKey_CNG_ECDsa() { const string KeyName = nameof(AssociatePersistedKey_CNG_ECDsa); CngKey cngKey = null; HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA256; byte[] signature; try { CngKeyCreationParameters creationParameters = new CngKeyCreationParameters() { ExportPolicy = CngExportPolicies.None, Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider, KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey, }; cngKey = CngKey.Create(CngAlgorithm.ECDsaP384, KeyName, creationParameters); using (ECDsaCng ecdsaCng = new ECDsaCng(cngKey)) { CertificateRequest request = new CertificateRequest( new X500DistinguishedName($"CN={KeyName}"), ecdsaCng, HashAlgorithmName.SHA256); DateTimeOffset now = DateTimeOffset.UtcNow; using (X509Certificate2 cert = request.CreateSelfSigned(now, now.AddDays(1))) using (ECDsa ecdsa = cert.GetECDsaPrivateKey()) { signature = ecdsa.SignData(Array.Empty <byte>(), hashAlgorithm); Assert.True(ecdsaCng.VerifyData(Array.Empty <byte>(), signature, hashAlgorithm)); } } // Some certs have disposed, did they delete the key? using (CngKey stillPersistedKey = CngKey.Open(KeyName, CngProvider.MicrosoftSoftwareKeyStorageProvider)) using (ECDsaCng ecdsaCng = new ECDsaCng(stillPersistedKey)) { ecdsaCng.SignData(Array.Empty <byte>(), hashAlgorithm); } } finally { cngKey?.Delete(); } }
public static void LoadWrongKeyType() { string keyName = Guid.NewGuid().ToString(); CngKey cngKey = CngKey.Create(new CngAlgorithm("AES"), keyName); try { Assert.Throws <CryptographicException>(() => new TripleDESCng(keyName)); } finally { cngKey.Delete(); } }
static void Main(string[] args) { var keyParams = new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.None, KeyCreationOptions = CngKeyCreationOptions.MachineKey, Provider = new CngProvider("Microsoft Platform Crypto Provider"), }; CngKey key = CngKey.Create(CngAlgorithm.Rsa, $"TPM-Import-Key", keyParams); Console.WriteLine($"Is the key a machine key? {key.IsMachineKey}"); key.Delete(); // just for cleanup, not necessary for reproduction }
/// <summary> /// Will destroy the key with keyname within the given provider with providerName. Will throw CryptographicException if either Provider or Key don't exist /// </summary> /// <param name="providerName">Name of the provider</param> /// <param name="keyName">Name of the key to destroy</param> public void DestroyLocalRSAKey(string providerName, string keyName) { CngProvider provider = new CngProvider(providerName); bool keyExists = doesKeyExists(provider, keyName); if (!keyExists) { //Nothing to destroy return; } using (CngKey key = CngKey.Open(keyName, provider, CngKeyOpenOptions.MachineKey)) { key.Delete(); } }
public void GetCngPrivateKeyTest() { // The known Microsoft cert does not have a CNG private key Assert.IsNull(s_microsoftCert.GetCngPrivateKey()); const string keyName = "Microsoft.Security.Cryptography.X509Certificates.Test.X509Certificate2Tests.GetCngPrivateKeyTest.RSA1"; try { // Create a cert for a persisted CNG key CngKeyCreationParameters keyCreationParams = new CngKeyCreationParameters(); keyCreationParams.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; using (CngKey key = CngKey.Create(CngAlgorithm2.Rsa, keyName, keyCreationParams)) { X509CertificateCreationParameters creationParams = new X509CertificateCreationParameters(new X500DistinguishedName("CN=CngCert")); creationParams.CertificateCreationOptions = X509CertificateCreationOptions.None; creationParams.TakeOwnershipOfKey = false; // A CNG certificate using a named key which is linked to the cert itself should return true X509Certificate2 cngFullCert = key.CreateSelfSignedCertificate(creationParams); using (CngKey certKey = cngFullCert.GetCngPrivateKey()) { Assert.AreEqual(keyName, certKey.KeyName); } // Create a cert with just the public key - there should be no access to the private key byte[] publicCertData = cngFullCert.Export(X509ContentType.Cert); X509Certificate2 cngPublicCert = new X509Certificate2(publicCertData); Assert.IsFalse(cngPublicCert.HasPrivateKey); Assert.IsNull(cngPublicCert.GetCngPrivateKey()); key.Delete(); } } finally { // Make sure to delete the persisted key so we're clean for the next run. if (CngKey.Exists(keyName)) { using (CngKey key = CngKey.Open(keyName)) { key.Delete(); } } } }
public void HasCngKeyTestCngCertTest() { const string keyName = "Microsoft.Security.Cryptography.X509Certificates.Test.X509Certificate2Tests.HasCngKeyTest.RSA1"; try { // Create a cert for a persisted CNG key CngKeyCreationParameters keyCreationParams = new CngKeyCreationParameters(); keyCreationParams.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport; using (CngKey key = CngKey.Create(CngAlgorithm2.Rsa, keyName, keyCreationParams)) { X509CertificateCreationParameters creationParams = new X509CertificateCreationParameters(new X500DistinguishedName("CN=CngCert")); creationParams.CertificateCreationOptions = X509CertificateCreationOptions.None; creationParams.TakeOwnershipOfKey = false; // A CNG certificate using a named key which is linked to the cert itself should return true X509Certificate2 cngCert = key.CreateSelfSignedCertificate(creationParams); Assert.IsTrue(cngCert.HasCngKey()); // A CNG cert exported and then re-imported should also return true byte[] pfx = cngCert.Export(X509ContentType.Pfx, "CngCertPassword"); X509Certificate2 cngCertImport = new X509Certificate2(pfx, "CngCertPassword"); Assert.IsTrue(cngCertImport.HasCngKey()); key.Delete(); } using (CngKey key = CngKey.Create(CngAlgorithm2.Rsa)) { X509Certificate2 ephemeralCert = key.CreateSelfSignedCertificate(new X500DistinguishedName("CN=EphemeralCngCert")); Assert.IsTrue(ephemeralCert.HasCngKey()); } } finally { // Make sure to delete the persisted key so we're clean for the next run. if (CngKey.Exists(keyName)) { using (CngKey key = CngKey.Open(keyName)) { key.Delete(); } } } }
public void CreateNamedKeyCertificate() { string keyName = "NamedKey_" + Guid.NewGuid().ToString(); try { CngKeyCreationParameters keyCreationParameters = new CngKeyCreationParameters(); keyCreationParameters.ExportPolicy = CngExportPolicies.AllowExport; X509Certificate2 cert = null; byte[] pfx = null; using (CngKey namedKey = CngKey.Create(CngAlgorithm2.Rsa, keyName, keyCreationParameters)) { cert = namedKey.CreateSelfSignedCertificate(new X500DistinguishedName("CN=TestNamedRSAKey")); pfx = cert.Export(X509ContentType.Pfx, "TestPassword"); Assert.IsTrue(cert.HasPrivateKey); Assert.IsTrue(cert.HasCngKey()); using (CngKey certKey = cert.GetCngPrivateKey()) { Assert.AreEqual(CngAlgorithm2.Rsa, certKey.Algorithm); } } GC.KeepAlive(cert); X509Certificate2 rtCert = new X509Certificate2(pfx, "TestPassword"); Assert.IsTrue(rtCert.HasPrivateKey); Assert.IsTrue(rtCert.HasCngKey()); using (CngKey rtKey = rtCert.GetCngPrivateKey()) { Assert.AreEqual(CngAlgorithm2.Rsa, rtKey.Algorithm); } } finally { if (CngKey.Exists(keyName)) { using (CngKey key = CngKey.Open(keyName)) { key.Delete(); } } } }
public static void Main() { partyAKey(); partyBKey(); CngProvider luna = new CngProvider("SafeNet Key Storage Provider"); CngKey ecKey = CngKey.Open("Party-A", luna); byte [] pubKey = softKey.Export(CngKeyBlobFormat.EccPublicBlob); softKey.Delete(); publicKey = CngKey.Import(pubKey, CngKeyBlobFormat.EccPublicBlob, luna); ECDiffieHellmanCng xChg = new ECDiffieHellmanCng(ecKey); xChg.HashAlgorithm = CngAlgorithm.Sha256; xChg.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hmac; byte[] data = xChg.DeriveKeyMaterial(publicKey); Console.ReadLine(); ecKey.Delete(); }
public static void VerifyCfbPersistedUnsupportedFeedbackSize( CngAlgorithm algorithm, Func <string, SymmetricAlgorithm> persistedFunc, int notSupportedFeedbackSizeInBits) { string keyName = Guid.NewGuid().ToString(); string feedbackSizeString = notSupportedFeedbackSizeInBits.ToString(); // We try to delete the key later which will also dispose of it, so no need // to put this in a using. CngKey cngKey = CngKey.Create(algorithm, keyName); try { using (SymmetricAlgorithm alg = persistedFunc(keyName)) { alg.Mode = CipherMode.CFB; alg.FeedbackSize = notSupportedFeedbackSizeInBits; alg.Padding = PaddingMode.None; byte[] destination = new byte[alg.BlockSize / 8]; CryptographicException ce = Assert.ThrowsAny <CryptographicException>(() => alg.EncryptCfb(Array.Empty <byte>(), destination, PaddingMode.None, notSupportedFeedbackSizeInBits)); Assert.Contains(feedbackSizeString, ce.Message); ce = Assert.ThrowsAny <CryptographicException>(() => alg.DecryptCfb(Array.Empty <byte>(), destination, PaddingMode.None, notSupportedFeedbackSizeInBits)); Assert.Contains(feedbackSizeString, ce.Message); ce = Assert.ThrowsAny <CryptographicException>(() => alg.CreateDecryptor()); Assert.Contains(feedbackSizeString, ce.Message); ce = Assert.ThrowsAny <CryptographicException>(() => alg.CreateEncryptor()); Assert.Contains(feedbackSizeString, ce.Message); } } finally { cngKey.Delete(); } }
internal static void VerifyMismatchAlgorithmFails( CngAlgorithm algorithm, Func <string, SymmetricAlgorithm> createFromKey) { string keyName = Guid.NewGuid().ToString(); // We try to delete the key later which will also dispose of it, so no need // to put this in a using. CngKey cngKey = CngKey.Create(algorithm, keyName); try { CryptographicException ce = Assert.Throws <CryptographicException>(() => createFromKey(keyName)); Assert.Contains($"'{algorithm.Algorithm}'", ce.Message); } finally { cngKey.Delete(); } }
public static void GetKey_NonExportable( CngAlgorithm algorithm, Func <string, SymmetricAlgorithm> persistedFunc) { string keyName = Guid.NewGuid().ToString(); CngKey cngKey = CngKey.Create(algorithm, keyName); try { using (SymmetricAlgorithm persisted = persistedFunc(keyName)) { Assert.ThrowsAny <CryptographicException>(() => persisted.Key); } } finally { // Delete also Disposes the key, no using should be added here. cngKey.Delete(); } }
// The ephemeral key has already been validated by the AesCipherTests suite. // Therefore we can use the ephemeral key to validate the persisted key. internal static void VerifyPersistedKey( CngAlgorithm algorithm, int keySize, int plainBytesCount, Func <string, SymmetricAlgorithm> persistedFunc, Func <SymmetricAlgorithm> ephemeralFunc, CipherMode cipherMode, PaddingMode paddingMode, int feedbackSizeInBits) { string keyName = Guid.NewGuid().ToString(); CngKeyCreationParameters creationParameters = new CngKeyCreationParameters { Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider, ExportPolicy = CngExportPolicies.AllowPlaintextExport, Parameters = { new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None), } }; CngKey cngKey = CngKey.Create(algorithm, keyName, creationParameters); try { VerifyPersistedKey( keyName, plainBytesCount, persistedFunc, ephemeralFunc, cipherMode, paddingMode, feedbackSizeInBits); } finally { // Delete also Disposes the key, no using should be added here. cngKey.Delete(); } }
//[Fact] - Keeping this test for reference but we don't want to run it as an inner-loop test because // it creates a key on disk. public static void StoredKeyTripleDES() { CngAlgorithm algname = new CngAlgorithm("3DES"); string keyName = "CoreFxTest-" + Guid.NewGuid(); CngKey _cngKey = CngKey.Create(algname, keyName); try { using (TripleDES alg = new TripleDESCng(keyName)) { int keySize = alg.KeySize; Assert.Equal(192, keySize); // Since this is a stored key, it's not going to surrender the actual key bytes. Assert.ThrowsAny <CryptographicException>(() => alg.Key); } } finally { _cngKey.Delete(); } }
public static void SetKey_DetachesFromPersistedKey( CngAlgorithm algorithm, Func <string, SymmetricAlgorithm> persistedFunc) { // This test verifies that: // * [Algorithm]Cng.set_Key does not change the persisted key value // * [Algorithm]Cng.GenerateKey is "the same" as set_Key // * ICryptoTransform objects opened before the change do not react to it string keyName = Guid.NewGuid().ToString(); CngKey cngKey = CngKey.Create(algorithm, keyName); try { using (SymmetricAlgorithm replaceKey = persistedFunc(keyName)) using (SymmetricAlgorithm regenKey = persistedFunc(keyName)) using (SymmetricAlgorithm stable = persistedFunc(keyName)) { // Ensure that we get no padding violations on decrypting with a bad key replaceKey.Padding = regenKey.Padding = stable.Padding = PaddingMode.None; stable.GenerateIV(); // Generate (4 * 8) = 32 blocks of plaintext byte[] plainTextBytes = GenerateRandom(4 * stable.BlockSize); byte[] iv = stable.IV; regenKey.IV = replaceKey.IV = iv; byte[] encryptedBytes; using (ICryptoTransform encryptor = replaceKey.CreateEncryptor()) { encryptedBytes = encryptor.TransformFinalBlock(plainTextBytes, 0, plainTextBytes.Length); } using (ICryptoTransform replaceBefore = replaceKey.CreateDecryptor()) using (ICryptoTransform replaceBeforeDelayed = replaceKey.CreateDecryptor()) using (ICryptoTransform regenBefore = regenKey.CreateDecryptor()) using (ICryptoTransform regenBeforeDelayed = regenKey.CreateDecryptor()) using (ICryptoTransform stableBefore = stable.CreateDecryptor()) using (ICryptoTransform stableBeforeDelayed = stable.CreateDecryptor()) { // Before we regenerate the regen key it should validly decrypt AssertTransformsEqual(plainTextBytes, regenBefore, encryptedBytes); // Before we regenerate the replace key it should validly decrypt AssertTransformsEqual(plainTextBytes, replaceBefore, encryptedBytes); // The stable handle definitely should validly read before. AssertTransformsEqual(plainTextBytes, stableBefore, encryptedBytes); regenKey.GenerateKey(); replaceKey.Key = regenKey.Key; using (ICryptoTransform replaceAfter = replaceKey.CreateDecryptor()) using (ICryptoTransform regenAfter = regenKey.CreateDecryptor()) using (ICryptoTransform stableAfter = stable.CreateDecryptor()) { // All of the Befores, and the BeforeDelayed (which have not accessed their key material) // should still decrypt correctly. And so should stableAfter. AssertTransformsEqual(plainTextBytes, regenBefore, encryptedBytes); AssertTransformsEqual(plainTextBytes, regenBeforeDelayed, encryptedBytes); AssertTransformsEqual(plainTextBytes, replaceBefore, encryptedBytes); AssertTransformsEqual(plainTextBytes, replaceBeforeDelayed, encryptedBytes); AssertTransformsEqual(plainTextBytes, stableBefore, encryptedBytes); AssertTransformsEqual(plainTextBytes, stableBeforeDelayed, encryptedBytes); AssertTransformsEqual(plainTextBytes, stableAfter, encryptedBytes); // There's a 1 in 2^128 chance that the regenerated key matched the original generated key. byte[] badDecrypt = replaceAfter.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); Assert.NotEqual(plainTextBytes, badDecrypt); // Regen and replace should come up with the same bad value, since they have the same // key value. AssertTransformsEqual(badDecrypt, regenAfter, encryptedBytes); } } // And, finally, a newly opened handle to the key is also unaffected. using (SymmetricAlgorithm openedAfter = persistedFunc(keyName)) { openedAfter.Padding = PaddingMode.None; openedAfter.IV = iv; using (ICryptoTransform decryptor = openedAfter.CreateDecryptor()) { AssertTransformsEqual(plainTextBytes, decryptor, encryptedBytes); } } } } finally { // Delete also Disposes the key, no using should be added here. cngKey.Delete(); } }
public static void ExportDoesNotCorruptPrivateKeyMethods() { string keyName = $"clrtest.{Guid.NewGuid():D}"; X509Store cuMy = new X509Store(StoreName.My, StoreLocation.CurrentUser); cuMy.Open(OpenFlags.ReadWrite); X509Certificate2 createdCert = null; X509Certificate2 foundCert = null; X509Certificate2 foundCert2 = null; try { string commonName = nameof(ExportDoesNotCorruptPrivateKeyMethods); string subject = $"CN={commonName},OU=.NET"; using (ImportedCollection toClean = new ImportedCollection(cuMy.Certificates)) { X509Certificate2Collection coll = toClean.Collection; using (ImportedCollection matches = new ImportedCollection(coll.Find(X509FindType.FindBySubjectName, commonName, false))) { foreach (X509Certificate2 cert in matches.Collection) { cuMy.Remove(cert); } } } foreach (X509Certificate2 cert in cuMy.Certificates) { if (subject.Equals(cert.Subject)) { cuMy.Remove(cert); } cert.Dispose(); } CngKeyCreationParameters options = new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport, }; using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, keyName, options)) using (RSACng rsaCng = new RSACng(key)) { CertificateRequest certReq = new CertificateRequest( subject, rsaCng, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); DateTimeOffset now = DateTimeOffset.UtcNow.AddMinutes(-5); createdCert = certReq.CreateSelfSigned(now, now.AddDays(1)); } cuMy.Add(createdCert); using (ImportedCollection toClean = new ImportedCollection(cuMy.Certificates)) { X509Certificate2Collection matches = toClean.Collection.Find( X509FindType.FindBySubjectName, commonName, validOnly: false); Assert.Equal(1, matches.Count); foundCert = matches[0]; } Assert.False(HasEphemeralKey(foundCert)); foundCert.Export(X509ContentType.Pfx, ""); Assert.False(HasEphemeralKey(foundCert)); using (ImportedCollection toClean = new ImportedCollection(cuMy.Certificates)) { X509Certificate2Collection matches = toClean.Collection.Find( X509FindType.FindBySubjectName, commonName, validOnly: false); Assert.Equal(1, matches.Count); foundCert2 = matches[0]; } Assert.False(HasEphemeralKey(foundCert2)); } finally { if (createdCert != null) { cuMy.Remove(createdCert); createdCert.Dispose(); } cuMy.Dispose(); foundCert?.Dispose(); foundCert2?.Dispose(); try { CngKey key = CngKey.Open(keyName); key.Delete(); key.Dispose(); } catch (Exception) { } } bool HasEphemeralKey(X509Certificate2 c) { using (RSA key = c.GetRSAPrivateKey()) { // This code is not defensive against the type changing, because it // is in the source tree with the code that produces the value. // Don't blind-cast like this in library or application code. RSACng rsaCng = (RSACng)key; return(rsaCng.Key.IsEphemeral); } } }
/// <summary> /// Create a RSA based certificate (to be used with encryption) with the given options /// </summary> /// <param name="buildOptions">Allows for more advanced configuration</param> /// <returns>An exportable X509Certificate2 object (with private key)</returns> public static X509Certificate2 CreateNewCertificate(RSACertificateBuilderOptions buildOptions) { if (buildOptions == null) { throw new ArgumentNullException("buildOptions"); } string keyName = buildOptions.RSAKeyName ?? "RSAKey"; CngKey objCngKey = null; if (CngKey.Exists(keyName)) { objCngKey = CngKey.Open(keyName); objCngKey.Delete(); } var creationParameters = new CngKeyCreationParameters(); creationParameters.ExportPolicy = CngExportPolicies.AllowExport; creationParameters.KeyUsage = CngKeyUsages.AllUsages; creationParameters.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider; var keySizeProperty = new CngProperty("Length", BitConverter.GetBytes(buildOptions.KeySize ?? 4096), CngPropertyOptions.None); creationParameters.Parameters.Add(keySizeProperty); objCngKey = CngKey.Create(CngAlgorithm2.Rsa, keyName, creationParameters); var name = new X500DistinguishedName(buildOptions.FullSubjectName); X509CertificateSignatureAlgorithm certAlg; switch (buildOptions.HashingMethod ?? HashingMethods.Sha256) { case HashingMethods.Sha1: certAlg = X509CertificateSignatureAlgorithm.RsaSha1; break; case HashingMethods.Sha256: certAlg = X509CertificateSignatureAlgorithm.RsaSha256; break; case HashingMethods.Sha384: certAlg = X509CertificateSignatureAlgorithm.RsaSha384; break; case HashingMethods.Sha512: certAlg = X509CertificateSignatureAlgorithm.RsaSha512; break; default: throw new InvalidOperationException("Selected hashing method is not supported"); } var options = new X509CertificateCreationParameters(name) { SignatureAlgorithm = certAlg, TakeOwnershipOfKey = true }; return(objCngKey.CreateSelfSignedCertificate(options)); }
/// <summary> /// Create a ECDSA based certificate with the given options /// </summary> /// <param name="buildOptions">Allows for more advanced configuration</param> /// <returns>An exportable X509Certificate2 object (with private key)</returns> public static X509Certificate2 CreateNewSigningCertificate(ECCertificateBuilderOptions buildOptions) { if (buildOptions == null) { throw new ArgumentNullException("buildOptions"); } string keyName = buildOptions.ECKeyName ?? "ECDSAKey"; CngKey objCngKey = null; if (CngKey.Exists(keyName)) { objCngKey = CngKey.Open(keyName); objCngKey.Delete(); } var creationParameters = new CngKeyCreationParameters(); creationParameters.ExportPolicy = CngExportPolicies.AllowExport; creationParameters.KeyUsage = CngKeyUsages.Signing; CngAlgorithm keyAlg; switch (buildOptions.ECCurve ?? ECNamedCurves.P521) { case ECNamedCurves.P521: keyAlg = CngAlgorithm.ECDsaP521; break; case ECNamedCurves.P384: keyAlg = CngAlgorithm.ECDsaP384; break; case ECNamedCurves.P256: keyAlg = CngAlgorithm.ECDsaP256; break; default: throw new InvalidOperationException("Selected curve is not supported"); } objCngKey = CngKey.Create(keyAlg, keyName, creationParameters); var name = new X500DistinguishedName(buildOptions.FullSubjectName); X509CertificateSignatureAlgorithm certAlg; switch (buildOptions.HashingMethod ?? HashingMethods.Sha256) { case HashingMethods.Sha1: certAlg = X509CertificateSignatureAlgorithm.ECDsaSha1; break; case HashingMethods.Sha256: certAlg = X509CertificateSignatureAlgorithm.ECDsaSha256; break; case HashingMethods.Sha384: certAlg = X509CertificateSignatureAlgorithm.ECDsaSha384; break; case HashingMethods.Sha512: certAlg = X509CertificateSignatureAlgorithm.ECDsaSha512; break; default: throw new InvalidOperationException("Selected hashing method is not supported"); } var options = new X509CertificateCreationParameters(name) { SignatureAlgorithm = certAlg, TakeOwnershipOfKey = true }; return(objCngKey.CreateSelfSignedCertificate(options)); }