Esempio n. 1
0
        public static async Task <JObject> DecryptAsync(
            JObject document,
            Encryptor encryptor,
            CosmosDiagnosticsContext diagnosticsContext,
            IReadOnlyDictionary <List <string>, string> pathsToEncrypt,
            CancellationToken cancellationToken)
        {
            Debug.Assert(document != null);
            Debug.Assert(encryptor != null);
            Debug.Assert(diagnosticsContext != null);

            foreach (List <string> paths in pathsToEncrypt.Keys)
            {
                foreach (string path in paths)
                {
                    if (document.TryGetValue(path.Substring(1), out JToken propertyValue))
                    {
                        EncryptionProperties encryptionProperties = new EncryptionProperties(
                            encryptionFormatVersion: 2,
                            CosmosEncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256,
                            pathsToEncrypt[paths],
                            propertyValue.ToObject <byte[]>(),
                            path);

                        JObject propPlainTextJObj = await PropertyEncryptionProcessor.DecryptContentAsync(
                            encryptionProperties,
                            encryptor,
                            diagnosticsContext,
                            cancellationToken);

                        foreach (JProperty property in propPlainTextJObj.Properties())
                        {
                            document[property.Name] = property.Value;
                        }
                    }
                }
            }

            if (document.TryGetValue(Constants.EncryptedInfo, out JToken encryptedInfo))
            {
                EncryptionProperties encryptionProperties = JsonConvert.DeserializeObject <EncryptionProperties>(encryptedInfo.ToString());

                JObject plainTextJObj = await PropertyEncryptionProcessor.DecryptContentAsync(
                    encryptionProperties,
                    encryptor,
                    diagnosticsContext,
                    cancellationToken);

                document.Remove(Constants.EncryptedInfo);

                foreach (JProperty property in plainTextJObj.Properties())
                {
                    document.Add(property.Name, property.Value);
                }
            }

            return(document);
        }
Esempio n. 2
0
        private async Task <Stream> DeserializeAndDecryptResponseAsync(
            Stream content,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            JObject contentJObj = EncryptionProcessor.BaseSerializer.FromStream <JObject>(content);
            JArray  result      = new JArray();

            if (!(contentJObj.SelectToken(Constants.DocumentsResourcePropertyName) is JArray documents))
            {
                throw new InvalidOperationException("Feed response Body Contract was violated. Feed response did not have an array of Documents");
            }

            foreach (JToken value in documents)
            {
                if (!(value is JObject document))
                {
                    result.Add(value);
                    continue;
                }

                try
                {
                    JObject decryptedDocument;
                    if (this.pathsToEncrypt != null)
                    {
                        decryptedDocument = await PropertyEncryptionProcessor.DecryptAsync(
                            document,
                            this.encryptor,
                            diagnosticsContext,
                            this.pathsToEncrypt,
                            cancellationToken);
                    }
                    else
                    {
                        decryptedDocument = await EncryptionProcessor.DecryptAsync(
                            document,
                            this.encryptor,
                            diagnosticsContext,
                            cancellationToken);
                    }

                    result.Add(decryptedDocument);
                }
                catch (Exception exception)
                {
                    if (this.decryptionResultHandler == null)
                    {
                        throw;
                    }

                    result.Add(document);

                    MemoryStream memoryStream = EncryptionProcessor.BaseSerializer.ToStream(document);
                    Debug.Assert(memoryStream != null);
                    bool wasBufferReturned = memoryStream.TryGetBuffer(out ArraySegment <byte> encryptedStream);
                    Debug.Assert(wasBufferReturned);

                    this.decryptionResultHandler(
                        DecryptionResult.CreateFailure(
                            encryptedStream,
                            exception));
                }
            }

            JObject decryptedResponse = new JObject();

            foreach (JProperty property in contentJObj.Properties())
            {
                if (property.Name.Equals(Constants.DocumentsResourcePropertyName))
                {
                    decryptedResponse.Add(property.Name, (JToken)result);
                }
                else
                {
                    decryptedResponse.Add(property.Name, property.Value);
                }
            }

            return(EncryptionProcessor.BaseSerializer.ToStream(decryptedResponse));
        }
Esempio n. 3
0
        /// <remarks>
        /// If there isn't any data that needs to be decrypted, input stream will be returned without any modification.
        /// Else input stream will be disposed, and a new stream is returned.
        /// In case of an exception, input stream won't be disposed, but position will be end of stream.
        /// </remarks>
        public static async Task <Stream> DecryptAsync(
            Stream input,
            Encryptor encryptor,
            CosmosDiagnosticsContext diagnosticsContext,
            IReadOnlyDictionary <List <string>, string> pathsToEncrypt,
            CancellationToken cancellationToken)
        {
            Debug.Assert(input != null);
            Debug.Assert(input.CanSeek);
            Debug.Assert(encryptor != null);
            Debug.Assert(diagnosticsContext != null);

            JObject itemJObj;

            using (StreamReader sr = new StreamReader(input, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
            {
                using JsonTextReader jsonTextReader = new JsonTextReader(sr);
                itemJObj = JsonSerializer.Create().Deserialize <JObject>(jsonTextReader);
            }

            if (pathsToEncrypt != null)
            {
                foreach (List <string> paths in pathsToEncrypt.Keys)
                {
                    foreach (string path in paths)
                    {
                        if (itemJObj.TryGetValue(path.Substring(1), out JToken propertyValue))
                        {
                            EncryptionProperties encryptionProperties = new EncryptionProperties(
                                encryptionFormatVersion: 2,
                                CosmosEncryptionAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256,
                                pathsToEncrypt[paths],
                                propertyValue.ToObject <byte[]>(),
                                path);

                            JObject propPlainTextJObj = await PropertyEncryptionProcessor.DecryptContentAsync(
                                encryptionProperties,
                                encryptor,
                                diagnosticsContext,
                                cancellationToken);

                            foreach (JProperty property in propPlainTextJObj.Properties())
                            {
                                itemJObj[property.Name] = property.Value;
                            }
                        }
                    }

                    input.Dispose();
                }
            }

            JToken token = itemJObj[Constants.EncryptedInfo];

            if (token != null)
            {
                JProperty encryptionPropertiesJProp = itemJObj.Property(Constants.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>();

                JObject plainTextJObj = await PropertyEncryptionProcessor.DecryptContentAsync(
                    encryptionProperties,
                    encryptor,
                    diagnosticsContext,
                    cancellationToken);

                foreach (JProperty property in plainTextJObj.Properties())
                {
                    itemJObj.Add(property.Name, property.Value);
                }

                itemJObj.Remove(Constants.EncryptedInfo);
                input.Dispose();
            }

            return(EncryptionProcessor.BaseSerializer.ToStream(itemJObj));
        }