private async Task <XElement> DecryptAsync(XElement encryptedElement) { var kid = (string)encryptedElement.Element("kid"); var symmetricKey = Convert.FromBase64String((string)encryptedElement.Element("key")); var symmetricIV = Convert.FromBase64String((string)encryptedElement.Element("iv")); var encryptedValue = Convert.FromBase64String((string)encryptedElement.Element("value")); var key = await _client.ResolveAsync(kid).ConfigureAwait(false); var result = await key.UnwrapKeyAsync(AzureKeyVaultXmlEncryptor.DefaultKeyEncryption, symmetricKey).ConfigureAwait(false); byte[] decryptedValue; using (var symmetricAlgorithm = AzureKeyVaultXmlEncryptor.DefaultSymmetricAlgorithmFactory()) { using (var decryptor = symmetricAlgorithm.CreateDecryptor(result, symmetricIV)) { decryptedValue = decryptor.TransformFinalBlock(encryptedValue, 0, encryptedValue.Length); } } using (var memoryStream = new MemoryStream(decryptedValue)) { return(XElement.Load(memoryStream)); } }
private static async Task <byte[]> UnwrapKeyInternal(EncryptionData encryptionData, IKeyEncryptionKeyResolver keyResolver, bool async, CancellationToken cancellationToken) { IKeyEncryptionKey oldKey = async ? await keyResolver.ResolveAsync(encryptionData.WrappedContentKey.KeyId, cancellationToken).ConfigureAwait(false) : keyResolver.Resolve(encryptionData.WrappedContentKey.KeyId, cancellationToken); if (oldKey == default) { throw Errors.ClientSideEncryption.KeyNotFound(encryptionData.WrappedContentKey.KeyId); } return(async ? await oldKey.UnwrapKeyAsync( encryptionData.WrappedContentKey.Algorithm, encryptionData.WrappedContentKey.EncryptedKey, cancellationToken).ConfigureAwait(false) : oldKey.UnwrapKey( encryptionData.WrappedContentKey.Algorithm, encryptionData.WrappedContentKey.EncryptedKey, cancellationToken)); }
#pragma warning disable CS1587 // XML comment is not placed on a valid language element /// <summary> /// Returns the content encryption key for blob. First tries to get the key encryption key from KeyResolver, /// then falls back to IKey stored on this EncryptionPolicy. Unwraps the content encryption key with the /// correct key wrapper. /// </summary> /// <param name="encryptionData">The encryption data.</param> /// <param name="async">Whether to perform asynchronously.</param> /// <param name="cancellationToken"></param> /// <returns> /// Encryption key as a byte array. /// </returns> /// <exception cref="Exception"> /// Exceptions thrown based on implementations of <see cref="IKeyEncryptionKey"/> and /// <see cref="IKeyEncryptionKeyResolver"/>. /// </exception> private async Task <Memory <byte> > GetContentEncryptionKeyAsync( #pragma warning restore CS1587 // XML comment is not placed on a valid language element EncryptionData encryptionData, bool async, CancellationToken cancellationToken) { IKeyEncryptionKey key = default; // If we already have a local key and it is the correct one, use that. if (encryptionData.WrappedContentKey.KeyId == _potentialCachedIKeyEncryptionKey?.KeyId) { key = _potentialCachedIKeyEncryptionKey; } // Otherwise, use the resolver. else if (_keyResolver != null) { key = async ? await _keyResolver.ResolveAsync(encryptionData.WrappedContentKey.KeyId, cancellationToken).ConfigureAwait(false) : _keyResolver.Resolve(encryptionData.WrappedContentKey.KeyId, cancellationToken); } // We throw for every other reason that decryption couldn't happen. Throw a reasonable // exception here instead of nullref. if (key == default) { throw Errors.ClientSideEncryption.KeyNotFound(encryptionData.WrappedContentKey.KeyId); } return(async ? await key.UnwrapKeyAsync( encryptionData.WrappedContentKey.Algorithm, encryptionData.WrappedContentKey.EncryptedKey, cancellationToken).ConfigureAwait(false) : key.UnwrapKey( encryptionData.WrappedContentKey.Algorithm, encryptionData.WrappedContentKey.EncryptedKey, cancellationToken)); }
private async Task <EncryptedXmlInfo> EncryptAsync(XElement plaintextElement) { byte[] value; using (var memoryStream = new MemoryStream()) { plaintextElement.Save(memoryStream, SaveOptions.DisableFormatting); value = memoryStream.ToArray(); } using (var symmetricAlgorithm = DefaultSymmetricAlgorithmFactory()) { var symmetricBlockSize = symmetricAlgorithm.BlockSize / 8; var symmetricKey = new byte[symmetricBlockSize]; var symmetricIV = new byte[symmetricBlockSize]; _randomNumberGenerator.GetBytes(symmetricKey); _randomNumberGenerator.GetBytes(symmetricIV); byte[] encryptedValue; using (var encryptor = symmetricAlgorithm.CreateEncryptor(symmetricKey, symmetricIV)) { encryptedValue = encryptor.TransformFinalBlock(value, 0, value.Length); } var key = await _client.ResolveAsync(_keyId).ConfigureAwait(false); var wrappedKey = await key.WrapKeyAsync(DefaultKeyEncryption, symmetricKey).ConfigureAwait(false); var element = new XElement("encryptedKey", new XComment(" This key is encrypted with Azure KeyVault. "), new XElement("kid", key.KeyId), new XElement("key", Convert.ToBase64String(wrappedKey)), new XElement("iv", Convert.ToBase64String(symmetricIV)), new XElement("value", Convert.ToBase64String(encryptedValue))); return(new EncryptedXmlInfo(element, typeof(AzureKeyVaultXmlDecryptor))); } }