/// <summary> /// Initializes a new instance of the SessionKey class. /// </summary> /// <param name="keyData">Delegate that procures key data on demand, cannot be null.</param> /// <exception cref="ArgumentNullException">The keyData argument is null.</exception> /// <exception cref="CryptographicException">The encryption key could not be created, probably due to malformed key data.</exception> public SessionKey(Func <string> keyData) : this() { // omitting arg validation since this type in private this.keyData = keyData; this.algorithm = AsymmetricDataEncryptor.InstantiateAlgorithm(this.keyData); }
/// <summary> /// Decrypts a cipher into the original data. /// </summary> /// <param name="algorithm">The algorithm to use for decryption, cannot be null.</param> /// <param name="cipher">The cipher to decrypt, cannot be null but can be empty.</param> /// <returns>The resulting data, cannot be null but can be empty.</returns> /// <exception cref="ArgumentNullException">The key or cipher argument is null.</exception> /// <exception cref="CryptographicException">The encryption operation failed, probably due to malformed key or key mismatch.</exception> private static byte[] Decrypt(RSACryptoServiceProvider algorithm, byte[] cipher) { // omitting argument validation in private methods // KeySize is in bits, array lengths count bytes int blockSize = algorithm.KeySize / 8; // Concatenate the result of breaking the data into chunks that are individually decrypted // calling 'ToArray' to avoid decrypting twice return(AsymmetricDataEncryptor.Concatenate(AsymmetricDataEncryptor.Break(blockSize, cipher).Select(array => algorithm.Decrypt(array, true)).ToArray())); }
/// <summary> /// Decrypts a cipher into the original data. /// </summary> /// <param name="key">The key to the data to be used as entropy, cannot be null but can be empty.</param> /// <param name="cipher">The cipher to decrypt, cannot be null but can be empty.</param> /// <returns>The resulting data, cannot be null but can be empty.</returns> /// <exception cref="ArgumentNullException">The key or cipher argument is null.</exception> /// <exception cref="CryptographicException">The encryption operation failed, probably due to malformed key or key mismatch.</exception> public byte[] Decrypt(string key, byte[] cipher) { if (key == null) { throw new ArgumentNullException("key"); } if (cipher == null) { throw new ArgumentNullException("cipher", string.Format(CultureInfo.InvariantCulture, "Object cannot be null for key {0}", key)); } using (RSACryptoServiceProvider algorithm = AsymmetricDataEncryptor.InstantiateAlgorithm(this.keyData)) { return(AsymmetricDataEncryptor.Decrypt(algorithm, cipher)); } }
/// <summary> /// Decrypts a cipher into the original data. /// </summary> /// <param name="key">The key to the data to be used as entropy, cannot be null but can be empty.</param> /// <param name="cipher">The cipher to decrypt, cannot be null but can be empty.</param> /// <returns>The resulting data, cannot be null but can be empty.</returns> /// <exception cref="ArgumentNullException">The key or cipher argument is null.</exception> /// <exception cref="CryptographicException">The encryption operation failed, probably due to malformed key or key mismatch.</exception> public byte[] Decrypt(string key, byte[] cipher) { if (key == null) { throw new ArgumentNullException("key"); } if (cipher == null) { throw new ArgumentNullException("cipher", string.Format(CultureInfo.InvariantCulture, "Object cannot be null for key {0}", key)); } if (this.disposed) { throw new ObjectDisposedException("This instance has been disposed."); } return(AsymmetricDataEncryptor.Decrypt(this.algorithm, cipher)); }
/// <summary> /// This method constructs an Asymmetric data encryptor from the public key of a certificate found in the certificate store. /// Use this method when you strictly intend to encrypt data. /// </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> /// <exception cref="ArgumentException">The storeLocation or storeName argument is not properly defined or the certificateName argument is null or empty or white spaces.</exception> /// <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> public static AsymmetricDataEncryptor LoadCertificatePublicKey(StoreLocation storeLocation, StoreName storeName, Predicate <X509Certificate2> certificateSelector) { if (!Enum.IsDefined(typeof(StoreLocation), storeLocation)) { throw new ArgumentOutOfRangeException("storeLocation"); } if (!Enum.IsDefined(typeof(StoreName), storeName)) { throw new ArgumentOutOfRangeException("storeName"); } if (certificateSelector == null) { throw new ArgumentNullException("certificateSelector"); } return(AsymmetricDataEncryptor.LoadCertificateKey(storeLocation, storeName, certificateSelector, certificate => certificate.PublicKey.Key.ToXmlString(false))); }
/// <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))); }