FeedIterator <DataEncryptionKeyProperties> GetDataEncryptionKeyIterator( string startId = null, string endId = null, bool isDescending = false, string continuationToken = null, QueryRequestOptions requestOptions = null) { if (!(this.GetDataEncryptionKeyStreamIterator( startId, endId, isDescending, continuationToken, requestOptions) is FeedIteratorInternal dekStreamIterator)) { throw new InvalidOperationException($"Expected FeedIteratorInternal."); } return(new FeedIteratorCore <DataEncryptionKeyProperties>( dekStreamIterator, (responseMessage) => { FeedResponse <DataEncryptionKeyProperties> results = this.ClientContext.ResponseFactory.CreateQueryFeedResponse <DataEncryptionKeyProperties>(responseMessage, ResourceType.ClientEncryptionKey); foreach (DataEncryptionKeyProperties result in results) { Uri dekUri = DataEncryptionKeyCore.CreateLinkUri(this.ClientContext, this, result.Id); this.ClientContext.DekCache.Set(this.Id, dekUri, result); } return results; })); }
private async Task <JObject> DecryptContentAsync( EncryptionProperties encryptionProperties, DatabaseCore database, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (encryptionProperties.EncryptionFormatVersion != 1) { throw CosmosExceptionFactory.CreateInternalServerErrorException($"Unknown encryption format version: {encryptionProperties.EncryptionFormatVersion}. Please upgrade your SDK to the latest version."); } DataEncryptionKeyCore tempDek = (DataEncryptionKeyInlineCore)database.GetDataEncryptionKey(id: "unknown"); (DataEncryptionKeyProperties _, InMemoryRawDek inMemoryRawDek) = await tempDek.FetchUnwrappedByRidAsync( encryptionProperties.DataEncryptionKeyRid, diagnosticsContext, cancellationToken); byte[] plainText = inMemoryRawDek.AlgorithmUsingRawDek.DecryptData(encryptionProperties.EncryptedData); JObject plainTextJObj = null; using (MemoryStream memoryStream = new MemoryStream(plainText)) using (StreamReader streamReader = new StreamReader(memoryStream)) using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) { plainTextJObj = JObject.Load(jsonTextReader); } return(plainTextJObj); }
internal DataEncryptionKeyInlineCore(DataEncryptionKeyCore dataEncryptionKey) { if (dataEncryptionKey == null) { throw new ArgumentException(nameof(dataEncryptionKey)); } this.dataEncryptionKey = dataEncryptionKey; }
internal DataEncryptionKeyCore( CosmosClientContext clientContext, DatabaseCore database, string keyId) { this.Id = keyId; this.ClientContext = clientContext; this.LinkUri = DataEncryptionKeyCore.CreateLinkUri(clientContext, database, keyId); this.Database = database; }
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); }
public async Task <Stream> EncryptAsync( Stream input, EncryptionOptions encryptionOptions, DatabaseCore database, EncryptionKeyWrapProvider encryptionKeyWrapProvider, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { Debug.Assert(input != null); Debug.Assert(encryptionOptions != null); Debug.Assert(database != null); Debug.Assert(diagnosticsContext != null); if (encryptionOptions.PathsToEncrypt == null) { throw new ArgumentNullException(nameof(encryptionOptions.PathsToEncrypt)); } if (encryptionOptions.PathsToEncrypt.Count == 0) { return(input); } foreach (string path in encryptionOptions.PathsToEncrypt) { if (string.IsNullOrEmpty(path) || path[0] != '/' || path.LastIndexOf('/') != 0) { throw new ArgumentException($"Invalid path {path ?? string.Empty}", nameof(encryptionOptions.PathsToEncrypt)); } } if (encryptionOptions.DataEncryptionKey == null) { throw new ArgumentException("Invalid encryption options", nameof(encryptionOptions.DataEncryptionKey)); } if (encryptionKeyWrapProvider == null) { throw new ArgumentException(ClientResources.EncryptionKeyWrapProviderNotConfigured); } DataEncryptionKey dek = database.GetDataEncryptionKey(encryptionOptions.DataEncryptionKey.Id); DataEncryptionKeyCore dekCore = (DataEncryptionKeyInlineCore)dek; (DataEncryptionKeyProperties dekProperties, InMemoryRawDek inMemoryRawDek) = await dekCore.FetchUnwrappedAsync( diagnosticsContext, cancellationToken); JObject itemJObj = EncryptionProcessor.baseSerializer.FromStream <JObject>(input); JObject toEncryptJObj = new JObject(); foreach (string pathToEncrypt in encryptionOptions.PathsToEncrypt) { string propertyName = pathToEncrypt.Substring(1); JToken propertyValueHolder = itemJObj.Property(propertyName).Value; // Even null in the JSON is a JToken with Type Null, this null check is just a sanity check if (propertyValueHolder != null) { toEncryptJObj.Add(propertyName, itemJObj.Property(propertyName).Value.Value <JToken>()); itemJObj.Remove(propertyName); } } MemoryStream memoryStream = EncryptionProcessor.baseSerializer.ToStream <JObject>(toEncryptJObj) as MemoryStream; Debug.Assert(memoryStream != null); Debug.Assert(memoryStream.TryGetBuffer(out _)); byte[] plainText = memoryStream.GetBuffer(); EncryptionProperties encryptionProperties = new EncryptionProperties( dataEncryptionKeyRid: dekProperties.ResourceId, encryptionFormatVersion: 1, encryptedData: inMemoryRawDek.AlgorithmUsingRawDek.EncryptData(plainText)); itemJObj.Add(Constants.Properties.EncryptedInfo, JObject.FromObject(encryptionProperties)); return(EncryptionProcessor.baseSerializer.ToStream(itemJObj)); }
public async Task <Stream> DecryptAsync( Stream input, DatabaseCore database, EncryptionKeyWrapProvider encryptionKeyWrapProvider, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { Debug.Assert(input != null); Debug.Assert(database != null); Debug.Assert(input.CanSeek); Debug.Assert(diagnosticsContext != null); if (encryptionKeyWrapProvider == null) { return(input); } JObject itemJObj = EncryptionProcessor.baseSerializer.FromStream <JObject>(input); JProperty encryptionPropertiesJProp = itemJObj.Property(Constants.Properties.EncryptedInfo); JObject encryptionPropertiesJObj = null; if (encryptionPropertiesJProp != null && encryptionPropertiesJProp.Value != null && encryptionPropertiesJProp.Value.Type == JTokenType.Object) { encryptionPropertiesJObj = (JObject)encryptionPropertiesJProp.Value; } if (encryptionPropertiesJObj == null) { input.Position = 0; return(input); } EncryptionProperties encryptionProperties = encryptionPropertiesJObj.ToObject <EncryptionProperties>(); if (encryptionProperties.EncryptionFormatVersion != 1) { throw CosmosExceptionFactory.CreateInternalServerErrorException($"Unknown encryption format version: {encryptionProperties.EncryptionFormatVersion}. Please upgrade your SDK to the latest version."); } DataEncryptionKeyCore tempDek = (DataEncryptionKeyInlineCore)database.GetDataEncryptionKey(id: "unknown"); (DataEncryptionKeyProperties _, InMemoryRawDek inMemoryRawDek) = await tempDek.FetchUnwrappedByRidAsync( encryptionProperties.DataEncryptionKeyRid, diagnosticsContext, cancellationToken); byte[] plainText = inMemoryRawDek.AlgorithmUsingRawDek.DecryptData(encryptionProperties.EncryptedData); JObject plainTextJObj = null; using (MemoryStream memoryStream = new MemoryStream(plainText)) using (StreamReader streamReader = new StreamReader(memoryStream)) using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) { plainTextJObj = JObject.Load(jsonTextReader); } foreach (JProperty property in plainTextJObj.Properties()) { itemJObj.Add(property.Name, property.Value); } itemJObj.Remove(Constants.Properties.EncryptedInfo); return(EncryptionProcessor.baseSerializer.ToStream(itemJObj)); }