internal async Task <(byte[], EncryptionKeyWrapMetadata, InMemoryRawDek)> WrapAsync( byte[] key, CosmosEncryptionAlgorithm encryptionAlgorithmId, EncryptionKeyWrapMetadata metadata, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { EncryptionKeyWrapProvider encryptionKeyWrapProvider = this.ClientContext.ClientOptions.EncryptionKeyWrapProvider; if (encryptionKeyWrapProvider == null) { throw new ArgumentException(ClientResources.EncryptionKeyWrapProviderNotConfigured); } EncryptionKeyWrapResult keyWrapResponse; using (diagnosticsContext.CreateScope("WrapDataEncryptionKey")) { keyWrapResponse = await encryptionKeyWrapProvider.WrapKeyAsync(key, metadata, cancellationToken); } // Verify DataEncryptionKeyProperties tempDekProperties = new DataEncryptionKeyProperties(this.Id, encryptionAlgorithmId, keyWrapResponse.WrappedDataEncryptionKey, keyWrapResponse.EncryptionKeyWrapMetadata); InMemoryRawDek roundTripResponse = await this.UnwrapAsync(tempDekProperties, diagnosticsContext, cancellationToken); if (!roundTripResponse.RawDek.SequenceEqual(key)) { throw CosmosExceptionFactory.CreateBadRequestException(ClientResources.KeyWrappingDidNotRoundtrip, diagnosticsContext: diagnosticsContext); } return(keyWrapResponse.WrappedDataEncryptionKey, keyWrapResponse.EncryptionKeyWrapMetadata, roundTripResponse); }
internal virtual byte[] GenerateKey(CosmosEncryptionAlgorithm encryptionAlgorithmId) { Debug.Assert(encryptionAlgorithmId == CosmosEncryptionAlgorithm.AE_AES_256_CBC_HMAC_SHA_256_RANDOMIZED, "Unexpected encryption algorithm id"); byte[] rawDek = new byte[32]; SecurityUtility.GenerateRandomBytes(rawDek); return(rawDek); }
internal virtual EncryptionAlgorithm GetEncryptionAlgorithm(byte[] rawDek, CosmosEncryptionAlgorithm encryptionAlgorithmId) { Debug.Assert(encryptionAlgorithmId == CosmosEncryptionAlgorithm.AE_AES_256_CBC_HMAC_SHA_256_RANDOMIZED, "Unexpected encryption algorithm id"); AeadAes256CbcHmac256EncryptionKey key = new AeadAes256CbcHmac256EncryptionKey(rawDek, AeadAes256CbcHmac256Algorithm.AlgorithmNameConstant); return(new AeadAes256CbcHmac256Algorithm(key, EncryptionType.Randomized, algorithmVersion: 1)); }
Task <DataEncryptionKeyResponse> CreateDataEncryptionKeyAsync( string id, CosmosEncryptionAlgorithm encryptionAlgorithm, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata, RequestOptions requestOptions = null, CancellationToken cancellationToken = default) { return(TaskHelper.RunInlineIfNeededAsync(() => this.database.CreateDataEncryptionKeyAsync(id, encryptionAlgorithm, encryptionKeyWrapMetadata, requestOptions, cancellationToken))); }
/// <summary> /// Initializes a new instance of <see cref="DataEncryptionKeyProperties"/>. /// </summary> /// <param name="id">Unique identifier for the data encryption key.</param> /// <param name="encryptionAlgorithm">Encryption algorithm that will be used along with this data encryption key to encrypt/decrypt data.</param> /// <param name="wrappedDataEncryptionKey">Wrapped (encrypted) form of the data encryption key.</param> /// <param name="encryptionKeyWrapMetadata">Metadata used by the configured key wrapping provider in order to unwrap the key.</param> public DataEncryptionKeyProperties( string id, CosmosEncryptionAlgorithm encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata) { this.Id = !string.IsNullOrEmpty(id) ? id : throw new ArgumentNullException(nameof(id)); this.EncryptionAlgorithmId = encryptionAlgorithm; this.WrappedDataEncryptionKey = wrappedDataEncryptionKey ?? throw new ArgumentNullException(nameof(wrappedDataEncryptionKey)); this.EncryptionKeyWrapMetadata = encryptionKeyWrapMetadata ?? throw new ArgumentNullException(nameof(encryptionKeyWrapMetadata)); }
async Task <DataEncryptionKeyResponse> CreateDataEncryptionKeyAsync( string id, CosmosEncryptionAlgorithm encryptionAlgorithmId, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata, RequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(id)) { throw new ArgumentNullException(nameof(id)); } if (encryptionAlgorithmId != CosmosEncryptionAlgorithm.AE_AES_256_CBC_HMAC_SHA_256_RANDOMIZED) { throw new ArgumentException(string.Format("Unsupported Encryption Algorithm {0}", encryptionAlgorithmId), nameof(encryptionAlgorithmId)); } if (encryptionKeyWrapMetadata == null) { throw new ArgumentNullException(nameof(encryptionKeyWrapMetadata)); } this.ClientContext.ValidateResource(id); DataEncryptionKeyCore newDek = (DataEncryptionKeyInlineCore)this.GetDataEncryptionKey(id); CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); byte[] rawDek = newDek.GenerateKey(encryptionAlgorithmId); (byte[] wrappedDek, EncryptionKeyWrapMetadata updatedMetadata, InMemoryRawDek inMemoryRawDek) = await newDek.WrapAsync( rawDek, encryptionAlgorithmId, encryptionKeyWrapMetadata, diagnosticsContext, cancellationToken); DataEncryptionKeyProperties dekProperties = new DataEncryptionKeyProperties(id, encryptionAlgorithmId, wrappedDek, updatedMetadata); Stream streamPayload = this.ClientContext.SerializerCore.ToStream(dekProperties); Task <ResponseMessage> responseMessage = this.CreateDataEncryptionKeyStreamAsync( streamPayload, requestOptions, cancellationToken); DataEncryptionKeyResponse dekResponse = await this.ClientContext.ResponseFactory.CreateDataEncryptionKeyResponseAsync(newDek, responseMessage); Debug.Assert(dekResponse.Resource != null); this.ClientContext.DekCache.Set(this.Id, newDek.LinkUri, dekResponse.Resource); this.ClientContext.DekCache.SetRawDek(dekResponse.Resource.SelfLink, inMemoryRawDek); return(dekResponse); }