/// <summary>
        /// Decrypts the given EncryptedValue object returning the source string.
        /// </summary>
        public string Decrypt(EncryptedValue encryptedValue, IIncomingLogicalMessageContext context)
        {
            string keyIdentifier;

            if (TryGetKeyIdentifierHeader(out keyIdentifier, context))
            {
                return(DecryptUsingKeyIdentifier(encryptedValue, keyIdentifier));
            }
            Log.Warn($"Encrypted message has no '{EncryptionHeaders.RijndaelKeyIdentifier}' header. Possibility of data corruption. Upgrade endpoints that send message with encrypted properties.");
            return(DecryptUsingAllKeys(encryptedValue));
        }
 static string Decrypt(EncryptedValue encryptedValue, byte[] key)
 {
     using (var rijndael = new RijndaelManaged())
     {
         var encrypted = Convert.FromBase64String(encryptedValue.EncryptedBase64Value);
         rijndael.IV   = Convert.FromBase64String(encryptedValue.Base64Iv);
         rijndael.Mode = CipherMode.CBC;
         rijndael.Key  = key;
         using (var decryptor = rijndael.CreateDecryptor())
             using (var memoryStream = new MemoryStream(encrypted))
                 using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                     using (var reader = new StreamReader(cryptoStream))
                     {
                         return(reader.ReadToEnd());
                     }
     }
 }
        string DecryptUsingKeyIdentifier(EncryptedValue encryptedValue, string keyIdentifier)
        {
            byte[] decryptionKey;

            if (!keys.TryGetValue(keyIdentifier, out decryptionKey))
            {
                throw new InvalidOperationException($"Decryption key not available for key identifier '{keyIdentifier}'. Add this key to the rijndael encryption service configuration. Key identifiers are case sensitive.");
            }

            try
            {
                return(Decrypt(encryptedValue, decryptionKey));
            }
            catch (CryptographicException ex)
            {
                throw new InvalidOperationException("Unable to decrypt property using configured decryption key specified in key identifier header.", ex);
            }
        }
        string DecryptUsingAllKeys(EncryptedValue encryptedValue)
        {
            var cryptographicExceptions = new List <CryptographicException>();

            foreach (var key in decryptionKeys)
            {
                try
                {
                    return(Decrypt(encryptedValue, key));
                }
                catch (CryptographicException exception)
                {
                    cryptographicExceptions.Add(exception);
                }
            }
            var message = $"Could not decrypt message. Tried {decryptionKeys.Count} keys.";

            throw new AggregateException(message, cryptographicExceptions);
        }