public static CertificateShortcutProviderKey EncryptPassphrase(X509Certificate2 certificate, ProtectedString passphrase) { // Instead of directly encrypting the passphrase with the certificate, // we use an intermediate random symmetric key. // The passphrase is encrypted with the symmetric key, and the symmetric key is encrypted with the certificate. // (asymmetric encryption is not suited to encrypt a lot of data) // symmetric encryption: var randomKey = new ProtectedBinary(true, CryptoRandom.Instance.GetRandomBytes(32)); var passphraseBinary = new ProtectedBinary(true, passphrase.ReadUtf8()); var encryptedPassphrase = EncryptSecret(passphraseBinary, randomKey, out var iv); // now we asymmetrically encrypt the random key. byte[] encryptedRandomKey; RSA rsa; ECDsa ecdsa; if ((rsa = certificate.GetRSAPublicKey()) != null) { encryptedRandomKey = rsa.Encrypt(randomKey.ReadData(), RSAEncryptionPadding.OaepSHA256); } else if ((ecdsa = certificate.GetECDsaPublicKey()) != null) { // TODO: // https://stackoverflow.com/questions/47116611/how-can-i-encrypt-data-using-a-public-key-from-ecc-x509-certificate-in-net-fram // var ecdh = ECDiffieHellman.Create(ecdsa.ExportParameters(false)); throw new NotSupportedException("Certificate's key type not supported."); } else { throw new NotSupportedException("Certificate's key type not supported."); } var result = new CertificateShortcutProviderKey(certificate, encryptedRandomKey, iv, encryptedPassphrase); return(result); }
public static ProtectedBinary DecryptPassphrase(CertificateShortcutProviderKey keyFile) { var fromSourceCertificate = keyFile.ReadCertificate(); var fromStoreCertificate = LoadFromStore(fromSourceCertificate); if (fromStoreCertificate == null) { throw new InvalidOperationException("The specified certificate could not be found in the store."); } // First we decrypt the symmetric key: ProtectedBinary decryptedKey; RSA rsa; ECDsa ecdsa; if ((rsa = fromStoreCertificate.GetRSAPrivateKey()) != null) { decryptedKey = new ProtectedBinary(true, rsa.Decrypt(keyFile.EncryptedKey, RSAEncryptionPadding.OaepSHA256)); } else if ((ecdsa = fromStoreCertificate.GetECDsaPrivateKey()) != null) { // TODO: // https://stackoverflow.com/questions/47116611/how-can-i-encrypt-data-using-a-public-key-from-ecc-x509-certificate-in-net-fram // var ecdh = ECDiffieHellman.Create(ecdsa.ExportParameters(false)); throw new NotSupportedException("Certificate's key type not supported."); } else { throw new NotSupportedException("Certificate's key type not supported."); } // Then we use the symmetric key to decrypt the passphrase: var decryptedPassphrase = DecryptSecret(keyFile.EncryptedPassphrase, decryptedKey, keyFile.IV); return(decryptedPassphrase); }