示例#1
0
        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);
        }
示例#2
0
        public async Task EncryptionUTRewrapDekWithoutEncryptionSerializer()
        {
            string dekId = "mydek";
            EncryptionTestHandler testHandler = new EncryptionTestHandler();

            // Create a DEK using a properly setup client first
            Container    container = this.GetContainerWithMockSetup(testHandler);
            DatabaseCore databaseWithSerializer = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            DataEncryptionKeyResponse dekResponse = await databaseWithSerializer.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            Assert.AreEqual(HttpStatusCode.Created, dekResponse.StatusCode);

            // Clear the handler pipeline that would have got setup
            testHandler.InnerHandler = null;

            // Ensure rewrap for this key fails on improperly configured client
            try
            {
                DatabaseCore      database = (DatabaseCore)((ContainerCore)(ContainerInlineCore)this.GetContainer(testHandler)).Database;
                DataEncryptionKey dek      = database.GetDataEncryptionKey(dekId);
                await dek.RewrapAsync(this.metadata2);

                Assert.Fail();
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual(ClientResources.EncryptionKeyWrapProviderNotConfigured, ex.Message);
            }
        }
示例#3
0
        public async Task EncryptionUTCreateItemWithUnknownDek()
        {
            Container    container = this.GetContainerWithMockSetup();
            DatabaseCore database  = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            MyItem item = EncryptionUnitTests.GetNewItem();

            try
            {
                await container.CreateItemAsync(
                    item,
                    new PartitionKey(item.PK),
                    new ItemRequestOptions
                {
                    EncryptionOptions = new EncryptionOptions
                    {
                        DataEncryptionKey = database.GetDataEncryptionKey("random"),
                        PathsToEncrypt    = MyItem.PathsToEncrypt
                    }
                });

                Assert.Fail();
            }
            catch (CosmosException ex)
            {
                Assert.IsTrue(ex.Message.Contains(ClientResources.DataEncryptionKeyNotFound));
            }
        }
示例#4
0
        public async Task EncryptionUTRewrapDek()
        {
            Container    container = this.GetContainerWithMockSetup();
            DatabaseCore database  = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            string dekId = "mydek";
            DataEncryptionKeyResponse createResponse = await database.CreateDataEncryptionKeyAsync(dekId, EncryptionUnitTests.Algo, this.metadata1);

            DataEncryptionKeyProperties createdProperties = createResponse.Resource;

            Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode);
            this.VerifyWrap(this.dek, this.metadata1);

            DataEncryptionKey         dek            = database.GetDataEncryptionKey(dekId);
            DataEncryptionKeyResponse rewrapResponse = await dek.RewrapAsync(this.metadata2);

            DataEncryptionKeyProperties rewrappedProperties = rewrapResponse.Resource;

            Assert.IsNotNull(rewrappedProperties);

            Assert.AreEqual(dekId, rewrappedProperties.Id);
            Assert.AreEqual(createdProperties.CreatedTime, rewrappedProperties.CreatedTime);
            Assert.IsNotNull(rewrappedProperties.LastModified);
            Assert.AreEqual(createdProperties.ResourceId, rewrappedProperties.ResourceId);
            Assert.AreEqual(createdProperties.SelfLink, rewrappedProperties.SelfLink);

            IEnumerable <byte> expectedRewrappedKey = this.dek.Select(b => (byte)(b + 2));

            Assert.IsTrue(expectedRewrappedKey.SequenceEqual(rewrappedProperties.WrappedDataEncryptionKey));

            Assert.AreEqual(new EncryptionKeyWrapMetadata(this.metadata2.Value + this.metadataUpdateSuffix), rewrappedProperties.EncryptionKeyWrapMetadata);

            Assert.AreEqual(2, this.testHandler.Received.Count);
            RequestMessage rewrapRequestMessage = this.testHandler.Received[1];

            Assert.AreEqual(ResourceType.ClientEncryptionKey, rewrapRequestMessage.ResourceType);
            Assert.AreEqual(OperationType.Replace, rewrapRequestMessage.OperationType);
            Assert.AreEqual(createResponse.ETag, rewrapRequestMessage.Headers[HttpConstants.HttpHeaders.IfMatch]);

            Assert.IsTrue(this.testHandler.Deks.ContainsKey(dekId));
            DataEncryptionKeyProperties serverDekProperties = this.testHandler.Deks[dekId];

            Assert.IsTrue(serverDekProperties.Equals(rewrappedProperties));

            this.VerifyWrap(this.dek, this.metadata2);
            this.mockKeyWrapProvider.VerifyNoOtherCalls();
        }
示例#5
0
        private static async Task <MyItem> CreateItemAsync(Container container, string dekId, List <string> pathsToEncrypt)
        {
            DatabaseCore database = (DatabaseCore)((ContainerCore)(ContainerInlineCore)container).Database;

            MyItem item = EncryptionUnitTests.GetNewItem();

            ItemResponse <MyItem> response = await container.CreateItemAsync <MyItem>(
                item,
                requestOptions : new ItemRequestOptions
            {
                EncryptionOptions = new EncryptionOptions
                {
                    DataEncryptionKey = database.GetDataEncryptionKey(dekId),
                    PathsToEncrypt    = pathsToEncrypt
                }
            });

            Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
            Assert.AreEqual(item, response.Resource);
            return(item);
        }
        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));
        }