示例#1
0
        private static async Task <DecryptionContext> MdeEncAlgoDecryptObjectAsync(
            JObject document,
            Encryptor encryptor,
            EncryptionProperties encryptionProperties,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            JObject plainTextJObj = new JObject();

            foreach (string path in encryptionProperties.EncryptedPaths)
            {
                string propertyName = path.Substring(1);
                if (!document.TryGetValue(propertyName, out JToken propertyValue))
                {
                    throw new InvalidOperationException($"{nameof(encryptionProperties.EncryptedPaths)} includes a path: '{path}' which was not found.");
                }

                byte[] cipherTextWithTypeMarker = propertyValue.ToObject <byte[]>();

                if (cipherTextWithTypeMarker == null)
                {
                    continue;
                }

                byte[] cipherText = new byte[cipherTextWithTypeMarker.Length - 1];
                Buffer.BlockCopy(cipherTextWithTypeMarker, 1, cipherText, 0, cipherTextWithTypeMarker.Length - 1);

                byte[] plainText = await EncryptionProcessor.MdeEncAlgoDecryptPropertyAsync(
                    encryptionProperties,
                    cipherText,
                    encryptor,
                    diagnosticsContext,
                    cancellationToken);

                EncryptionProcessor.DeserializeAndAddProperty(
                    (TypeMarker)cipherTextWithTypeMarker[0],
                    plainText,
                    plainTextJObj,
                    propertyName);
            }

            List <string> pathsDecrypted = new List <string>();

            foreach (JProperty property in plainTextJObj.Properties())
            {
                document[property.Name] = property.Value;
                pathsDecrypted.Add("/" + property.Name);
            }

            DecryptionContext decryptionContext = EncryptionProcessor.CreateDecryptionContext(
                pathsDecrypted,
                encryptionProperties.DataEncryptionKeyId);

            document.Remove(Constants.EncryptedInfo);
            return(decryptionContext);
        }
示例#2
0
        private static async Task <DecryptionContext> LegacyEncAlgoDecryptContentAsync(
            JObject document,
            EncryptionProperties encryptionProperties,
            Encryptor encryptor,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            if (encryptionProperties.EncryptionFormatVersion != 2)
            {
                throw new NotSupportedException($"Unknown encryption format version: {encryptionProperties.EncryptionFormatVersion}. Please upgrade your SDK to the latest version.");
            }

            byte[] plainText = await encryptor.DecryptAsync(
                encryptionProperties.EncryptedData,
                encryptionProperties.DataEncryptionKeyId,
                encryptionProperties.EncryptionAlgorithm,
                cancellationToken);

            if (plainText == null)
            {
                throw new InvalidOperationException($"{nameof(Encryptor)} returned null plainText from {nameof(DecryptAsync)}.");
            }

            JObject plainTextJObj;

            using (MemoryStream memoryStream = new MemoryStream(plainText))
                using (StreamReader streamReader = new StreamReader(memoryStream))
                    using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                    {
                        plainTextJObj = JObject.Load(jsonTextReader);
                    }

            List <string> pathsDecrypted = new List <string>();

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

            DecryptionContext decryptionContext = EncryptionProcessor.CreateDecryptionContext(
                pathsDecrypted,
                encryptionProperties.DataEncryptionKeyId);

            document.Remove(Constants.EncryptedInfo);

            return(decryptionContext);
        }
示例#3
0
        private static DecryptionContext CreateDecryptionContext(
            List <string> pathsDecrypted,
            string dataEncryptionKeyId)
        {
            DecryptionInfo decryptionInfo = new DecryptionInfo(
                pathsDecrypted,
                dataEncryptionKeyId);

            DecryptionContext decryptionContext = new DecryptionContext(
                new List <DecryptionInfo>()
            {
                decryptionInfo
            });

            return(decryptionContext);
        }
示例#4
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, DecryptionContext)> DecryptAsync(
            Stream input,
            Encryptor encryptor,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            if (input == null)
            {
                return(input, null);
            }

            Debug.Assert(input.CanSeek);
            Debug.Assert(encryptor != null);
            Debug.Assert(diagnosticsContext != null);

            JObject itemJObj = EncryptionProcessor.RetrieveItem(input);
            JObject encryptionPropertiesJObj = EncryptionProcessor.RetrieveEncryptionProperties(itemJObj);

            if (encryptionPropertiesJObj == null)
            {
                input.Position = 0;
                return(input, null);
            }

            EncryptionProperties encryptionProperties = encryptionPropertiesJObj.ToObject <EncryptionProperties>();
            DecryptionContext    decryptionContext    = encryptionProperties.EncryptionAlgorithm switch
            {
                CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized => await EncryptionProcessor.MdeEncAlgoDecryptObjectAsync(
                    itemJObj,
                    encryptor,
                    encryptionProperties,
                    diagnosticsContext,
                    cancellationToken),
                CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized => await EncryptionProcessor.LegacyEncAlgoDecryptContentAsync(
                    itemJObj,
                    encryptionProperties,
                    encryptor,
                    diagnosticsContext,
                    cancellationToken),
                _ => throw new NotSupportedException($"Encryption Algorithm : {encryptionProperties.EncryptionAlgorithm} is not supported."),
            };

            input.Dispose();
            return(EncryptionProcessor.BaseSerializer.ToStream(itemJObj), decryptionContext);
        }
示例#5
0
        public static async Task <(JObject, DecryptionContext)> DecryptAsync(
            JObject document,
            Encryptor encryptor,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            Debug.Assert(document != null);

            Debug.Assert(encryptor != null);

            JObject encryptionPropertiesJObj = EncryptionProcessor.RetrieveEncryptionProperties(document);

            if (encryptionPropertiesJObj == null)
            {
                return(document, null);
            }

            EncryptionProperties encryptionProperties = encryptionPropertiesJObj.ToObject <EncryptionProperties>();
            DecryptionContext    decryptionContext    = encryptionProperties.EncryptionAlgorithm switch
            {
                CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized => await EncryptionProcessor.MdeEncAlgoDecryptObjectAsync(
                    document,
                    encryptor,
                    encryptionProperties,
                    diagnosticsContext,
                    cancellationToken),
                CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized => await EncryptionProcessor.LegacyEncAlgoDecryptContentAsync(
                    document,
                    encryptionProperties,
                    encryptor,
                    diagnosticsContext,
                    cancellationToken),
                _ => throw new NotSupportedException($"Encryption Algorithm : {encryptionProperties.EncryptionAlgorithm} is not supported."),
            };

            return(document, decryptionContext);
        }