/// <inheritdoc /> public string Decrypt(string input, out bool isLatestKey) { isLatestKey = false; if (string.IsNullOrEmpty(input)) { return(input); } byte[] initializationVector = new byte[16]; // Note: Each symbol in a Base32 string is 5 bits. byte[] buffer = new byte[input.Length * 5 / 8]; if (Base32EncoderDecoder.TryBase32Decode(input, buffer)) { using (MemoryStream memoryStream = new MemoryStream(buffer)) // Retrieve the IV from the encrypted string. memoryStream.Read(initializationVector, 0, initializationVector.Length); // Need just the text to decrypt now, ignoring the IV. byte[] cipherText = buffer.Skip(initializationVector.Length).ToArray(); string decryptedString = null; bool decryptionKeyFound = false; // Try to find the key used in the encryption. foreach (Key key in _aesEncryptionKeys) { if (TryDecryptStringFromBytes( cipherText, ConvertHexStringToByteArray(key.Value), initializationVector, out decryptedString)) { decryptionKeyFound = true; Debug.Assert(_aesEncryptionKeys[0] != null); if (key.Value == _aesEncryptionKeys[0].Value) { isLatestKey = true; } break; } } if (!decryptionKeyFound) { throw new CryptographicException(Resources.AESCryptographer_Decrypt_DecryptFailed_KeyNotFound); } return(decryptedString); } // If we get here, decryption failed. throw new CryptographicException( // ReSharper disable once AssignNullToNotNullAttribute string.Format(Resources.AESCryptographer_Decrypt_DecryptFailed_InputNotBase32String, input)); }
/// <inheritdoc /> public string Encrypt(string input) { if (string.IsNullOrEmpty(input)) { return(input); } using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider()) { Key encryptionKey = null; bool addNewKey = true; if (_aesEncryptionKeys.Count > 0) { // Check if there is any non-Expired keys to use. bool nonExpiredKeysFound = _aesEncryptionKeys.Count(k => k.Expiry > DateTime.Now) > 0; if (nonExpiredKeysFound) { encryptionKey = _aesEncryptionKeys[0]; addNewKey = false; } } if (addNewKey) { const int defaultKeyLifeInDays = 7; // Use the key automatically generated by the AesCryptoServiceProvider. // Store it as a hex string. string value = string.Concat(aes.Key.Select(b => b.ToString("x2"))); // For the expiry, use the number of days specified in the KeyLifeInDays property. DateTime expiry = DateTime.Now.Add( TimeSpan.FromDays(_provider != null ? _provider.KeyLifeInDays : defaultKeyLifeInDays)); encryptionKey = new Key(value, expiry); _aesEncryptionKeys.Add(encryptionKey); _aesEncryptionKeys = _aesEncryptionKeys.OrderByDescending(k => k.Expiry).ToList(); _provider?.AddKey(encryptionKey); } Debug.Assert(encryptionKey != null); byte[] encrypted = EncryptStringToBytes(input, ConvertHexStringToByteArray(encryptionKey.Value), aes.IV); return(Base32EncoderDecoder.Base32Encode(encrypted)); } }