internal static async Task <string> RotateEncryptionHelper(KeyRotationEntity rotationEntity, TableRequestOptions modifiedOptions, CancellationToken cancellationToken) { // Validate arguments: String encryptionDataString = rotationEntity.encryptionMetadataJson; TableEncryptionPolicy.ValidateKeyRotationArguments(rotationEntity, modifiedOptions, !String.IsNullOrWhiteSpace(encryptionDataString)); // Deserialize the old encryption data and validate: EncryptionData tableEncryptionData = Newtonsoft.Json.JsonConvert.DeserializeObject <EncryptionData>(encryptionDataString); if (tableEncryptionData.WrappedContentKey.EncryptedKey == null) { throw new InvalidOperationException(SR.KeyRotationNoKeyID); } // Use the key resolver to resolve the old KEK. Azure.KeyVault.Core.IKey oldKey = await modifiedOptions.EncryptionPolicy.KeyResolver.ResolveKeyAsync(tableEncryptionData.WrappedContentKey.KeyId, cancellationToken).ConfigureAwait(false); if (oldKey == null) { throw new ArgumentException(SR.KeyResolverCannotResolveExistingKey); } // Use the old KEK to unwrap the CEK. byte[] unwrappedOldKey = await oldKey.UnwrapKeyAsync(tableEncryptionData.WrappedContentKey.EncryptedKey, tableEncryptionData.WrappedContentKey.Algorithm, cancellationToken).ConfigureAwait(false); // Use the new KEK to re-wrap the CEK. Tuple <byte[], string> wrappedNewKeyTuple = await modifiedOptions.EncryptionPolicy.Key.WrapKeyAsync(unwrappedOldKey, null /* algorithm */, cancellationToken).ConfigureAwait(false); TaskCompletionSource <string> tcs = new TaskCompletionSource <string>(); tableEncryptionData.WrappedContentKey = new WrappedKey(modifiedOptions.EncryptionPolicy.Key.Kid, wrappedNewKeyTuple.Item1, wrappedNewKeyTuple.Item2); return(Newtonsoft.Json.JsonConvert.SerializeObject(tableEncryptionData)); }
/// <summary> /// Creates a new table operation that rotates the content encryption key of /// the given entity in a table. /// </summary> /// <param name="entity">The <see cref="KeyRotationEntity"/> entity to have its key rotated. Must be the output of a call to an "ExecuteQueryForKeyRotation()" call.</param> /// <returns>The <see cref="TableOperation"/> object.</returns> public static TableOperation RotateEncryptionKey(KeyRotationEntity entity) { // Validate a bunch of stuff here TableOperation rotationOperation = new TableOperation(null, TableOperationType.RotateEncryptionKey, false); rotationOperation.keyRotationEntity = entity; return(rotationOperation); }
private static void ValidateKeyRotationArguments(KeyRotationEntity rotationEntity, TableRequestOptions options, bool encryptionMetadataAvailable) { if (options.EncryptionPolicy == null) { throw new ArgumentException(SR.KeyRotationNoEncryptionPolicy, "options.EncryptionPolicy"); } if (options.EncryptionPolicy.Key == null) { throw new ArgumentException(SR.KeyRotationNoEncryptionKey, "options.EncryptionPolicy.Key"); } if (options.EncryptionPolicy.KeyResolver == null) { throw new ArgumentException(SR.KeyRotationNoEncryptionKeyResolver, "options.EncryptionPolicy.KeyResolver"); } if (rotationEntity.ETag == null) { throw new InvalidOperationException(SR.KeyRotationNoEtag); } }