/// <summary> /// This method constructs an Asymmetric data encryptor from a certificate found in the certificate store. /// </summary> /// <param name="storeLocation">The store location.</param> /// <param name="storeName">The store name.</param> /// <param name="certificateSelector">The certificate predicate selector, cannot be null.</param> /// <param name="keySelector">The delegate that extracts the key data from the certificate, cannot be null.</param> /// <exception cref="InvalidOperationException">The certificate could not be found or loaded.</exception> /// <exception cref="SecurityException">The calling context is denied access to the certificate store.</exception> /// <exception cref="CryptographicException">The encryption operation failed.</exception> /// <returns>The asymmetric key, cannot be null.</returns> private static AsymmetricDataEncryptor LoadCertificateKey(StoreLocation storeLocation, StoreName storeName, Predicate <X509Certificate2> certificateSelector, Func <X509Certificate2, string> keySelector) { // argument validation done in public method for first three arguments, last argument trusted to be not null X509Store store = null; try { store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); X509Certificate2 certificate = store.Certificates.Cast <X509Certificate2>().FirstOrDefault(cert => certificateSelector(cert)); if (certificate != null) { // capture keydata once so that multiple calls to encrypt/decrypt for a single instance of AsymmetricDataEncryptor always behaves the same // but keep the key under DPAPI encryption to protect from crash dump attacks IStringEncryptor encryptor = StringEncryptor.Create(CurrentUserDataEncryptor.Instance); string keyDataCipher = encryptor.Encrypt(AsymmetricDataEncryptor.InMemoryKeyName, keySelector(certificate)); return(new AsymmetricDataEncryptor(() => encryptor.Decrypt(AsymmetricDataEncryptor.InMemoryKeyName, keyDataCipher))); } } finally { if (store != null) { store.Close(); store = null; } } throw new InvalidOperationException("The requested certificate could not be loaded."); }
/// <summary> /// Creates an AsymmetricDataEncryptor instance with a new RSA key. /// </summary> /// <returns>The asymmetric key, cannot be null.</returns> public static AsymmetricDataEncryptor GenerateRandomEncryptor() { // capture keydata once so that multiple calls to encrypt/decrypt for a single instance of AsymmetricDataEncryptor always behaves the same // but keep the key under DPAPI encryption to protect from crash dump attacks IStringEncryptor encryptor = StringEncryptor.Create(CurrentUserDataEncryptor.Instance); string keyDataCipher = encryptor.Encrypt(AsymmetricDataEncryptor.InMemoryKeyName, AsymmetricDataEncryptor.GenerateKey()); return(new AsymmetricDataEncryptor(() => encryptor.Decrypt(AsymmetricDataEncryptor.InMemoryKeyName, keyDataCipher))); }