Пример #1
0
        public async Task <string> Decrypt(string data)
        {
            using var stream = GenerateStreamFromBase64String(data);
            var req = new DecryptRequest
            {
                KeyId          = this.keyId,
                CiphertextBlob = stream
            };
            var response = await client.DecryptAsync(req);

            var result = GetValueFromStream(response.Plaintext);

            return(result);
        }
        /// <summary>
        /// Decrypts a provided XML element.
        /// </summary>
        /// <param name="encryptedElement">Encrypted XML element.</param>
        /// <param name="ct">Cancellation token.</param>
        /// <returns>Decrypted XML element.</returns>
#pragma warning disable S3242 // Not altering Microsoft interface definition
        public async Task <XElement> DecryptAsync(XElement encryptedElement, CancellationToken ct)
#pragma warning restore S3242
        {
            ValidateConfig();

            logger?.LogDebug("Decrypting ciphertext DataProtection key using AWS key {0}", Config.KeyId);

            using (var memoryStream = new MemoryStream())
            {
                byte[] protectedKey = Convert.FromBase64String((string)encryptedElement.Element("value"));
                await memoryStream.WriteAsync(protectedKey, 0, protectedKey.Length, ct);

                var response = await kmsClient.DecryptAsync(new DecryptRequest
                {
                    EncryptionContext = ContextUpdater.GetEncryptionContext(Config, dpOptions.Value),
                    GrantTokens       = Config.GrantTokens,
                    CiphertextBlob    = memoryStream
                },
                                                            ct)
                               .ConfigureAwait(false);

                // Help indicates that Plaintext might be empty if the key couldn't be retrieved but
                // testing shows that you always get an exception thrown first
                using (var plaintext = response.Plaintext)
                {
                    // Ignoring all the good reasons mentioned in KmsXmlEncryptor and that the implementation would
                    // be error-prone, hard to test & review, as well as vary between NET Full & NET Core, it's not
                    // actually permitted to access the buffer of response.Plaintext because it was populated in
                    // the SDK from a constructor which disallows any subsequent writing.
                    //
                    // Yet more reasons that this needs to be handled at a framework level, providing clear Secure* primitives.
                    return(XElement.Load(plaintext));
                }
            }
        }
Пример #3
0
        public string Decrypt(EncryptedValue encryptedValue, IIncomingLogicalMessageContext context)
        {
            if (encryptedValue == null || String.IsNullOrEmpty(encryptedValue.EncryptedBase64Value))
            {
                return(null);
            }

            if (!context.Headers.ContainsKey(EncryptionHeaders.RijndaelKeyIdentifier))
            {
                return(null);
            }

            var decryptlabel = context.Headers[EncryptionHeaders.RijndaelKeyIdentifier];

            var decryptRequest = new DecryptRequest {
                KeyId = decryptlabel
            };
            var value = Convert.FromBase64String(encryptedValue.EncryptedBase64Value);

            decryptRequest.CiphertextBlob = new System.IO.MemoryStream(value);

            var response = _client.DecryptAsync(decryptRequest).GetAwaiter().GetResult();

            if (response != null)
            {
                return(Encoding.UTF8.GetString(response.Plaintext.ToArray()));
            }

            return(null);
        }
Пример #4
0
        private async Task <byte[]> GetDecryptedDataKey()
        {
            var request = new DecryptRequest
            {
                CiphertextBlob = new MemoryStream(Convert.FromBase64String(encryptedDataKey))
            };
            var response = await kmsService.DecryptAsync(request);

            return(response.Plaintext.ToArray());
        }
Пример #5
0
        private async Task <IDictionary <string, string> > ReadParametersFromEnvironmentVariables()
        {
            var parameters = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase);

            foreach (DictionaryEntry envVar in Environment.GetEnvironmentVariables())
            {
                var key   = envVar.Key as string;
                var value = envVar.Value as string;
                if ((key == null) || (value == null))
                {
                    continue;
                }
                if (key.StartsWith("STR_", StringComparison.Ordinal))
                {
                    // plain string value
                    parameters.Add(EnvToVarKey(key), value);
                }
                else if (key.StartsWith("SEC_", StringComparison.Ordinal))
                {
                    // secret with optional encryption context pairs
                    var parts = value.Split('|');
                    Dictionary <string, string> encryptionContext = null;
                    if (parts.Length > 1)
                    {
                        encryptionContext = new Dictionary <string, string>();
                        for (var i = 1; i < parts.Length; ++i)
                        {
                            var pair = parts[i].Split('=', 2);
                            if (pair.Length != 2)
                            {
                                continue;
                            }
                            encryptionContext.Add(
                                Uri.UnescapeDataString(pair[0]),
                                Uri.UnescapeDataString(pair[1])
                                );
                        }
                    }
                    var plaintextStream = (await _kmsClient.DecryptAsync(new DecryptRequest {
                        CiphertextBlob = new MemoryStream(Convert.FromBase64String(value)),
                        EncryptionContext = encryptionContext
                    })).Plaintext;
                    parameters.Add(EnvToVarKey(key), Encoding.UTF8.GetString(plaintextStream.ToArray()));
                }
            }
            return(parameters);

            // local functions
            string EnvToVarKey(string key) => "/" + key.Substring(4).Replace('_', '/');
        }
Пример #6
0
        public async Task <string> Decrypt(string encryptedData, string serviceAccountId)
        {
            var tuple = EnvelopeEncryptionUtils.Unwrap(encryptedData).ValueOrFailure("Invalid encrypted data format");

            var(encryptedDataKey, iv, actualEncryptedData) = tuple;

            var decryptionResult = await mAmazonKeyManagementService.DecryptAsync(new DecryptRequest
            {
                CiphertextBlob = new MemoryStream(Convert.FromBase64String(encryptedDataKey)),
            });

            var decrypted = RijndaelUtils.Decrypt(decryptionResult.Plaintext.ToArray(), iv, actualEncryptedData);

            return(Encoding.UTF8.GetString(decrypted));
        }
Пример #7
0
        public async Task <string> Decrypt(string encryptedData, string serviceAccountId)
        {
            var encryptedDataKey    = encryptedData.Split('$')[1];
            var actualEncryptedData = encryptedData.Split('$')[2];

            var decryptionResult = await mAmazonKeyManagementService.DecryptAsync(new DecryptRequest
            {
                CiphertextBlob = new MemoryStream(Convert.FromBase64String(encryptedDataKey)),
            });

            var dataKey = ConvertMemoryStreamToBase64String(decryptionResult.Plaintext);

            mSymmetricKeyManagement.SetEncryptionKey(dataKey);
            return(await mSymmetricKeyManagement.Decrypt(actualEncryptedData, serviceAccountId));
        }
Пример #8
0
        public byte[] Decrypt(byte[] keyBytes, Dictionary <string, string> context)
        {
            var cipherStream = new MemoryStream(keyBytes)
            {
                Position = 0
            };
            var request = new DecryptRequest
            {
                CiphertextBlob    = cipherStream,
                EncryptionContext = context
            };
            var response = _kmsClient.DecryptAsync(request).Result;
            var result   = new byte[response.Plaintext.Length];

            response.Plaintext.Read(result, 0, (int)response.Plaintext.Length);

            return(result);
        }
Пример #9
0
        /// <summary>
        /// Decrypts the passed data with a master key. This method will decrypt a
        /// payload of up to 6144 bytes returning the resulting clear text
        /// </summary>
        /// <param name="data">The encrypted data to decrypt.</param>
        /// <returns>Resulting clear text.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException">You must provide some data to encrypt</exception>
        /// <exception cref="PayloadTooLargeException"></exception>
        /// <exception cref="KeyManagementServiceUnavailableException"></exception>
        public byte[] DecryptData(byte[] data)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("AwsKmsKeyManager");
            }

            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (!data.Any())
            {
                throw new ArgumentException("You must provide some data to encrypt", nameof(data));
            }

            if (data.Length > MaxDecryptPayloadSize)
            {
                throw new PayloadTooLargeException(MaxDecryptPayloadSize, data.Length);
            }

            var res = RetryPolicy.ExecuteAndCapture(() =>
            {
                using (var msData = new MemoryStream(data))
                {
                    var req = new DecryptRequest
                    {
                        CiphertextBlob = msData
                    };

                    var t = _client.DecryptAsync(req);
                    t.ConfigureAwait(false);
                    return(t.GetAwaiter().GetResult());
                }
            });

            ValidateResponse(res);

            return(((DecryptResponse)res.Result).Plaintext.ToArray());
        }
Пример #10
0
        public virtual async Task <string> Decrypt(string ciphertext, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using var stream = new MemoryStream();
            var byteArray = Convert.FromBase64String(ciphertext);

            await stream.WriteAsync(byteArray, cancellationToken);

            cancellationToken.ThrowIfCancellationRequested();

            var request = new DecryptRequest {
                CiphertextBlob = stream
            };
            var response = await kmsClient.DecryptAsync(request, cancellationToken);

            cancellationToken.ThrowIfCancellationRequested();

            using var reader = new StreamReader(response.Plaintext);
            return(await reader.ReadToEndAsync());
        }
Пример #11
0
        public async Task DecryptShouldDecryptTheCiphertext(
            [Frozen, Substitute] IAmazonKeyManagementService kmsClient,
            [Target] DefaultDecryptionService service
            )
        {
            var value         = "ZW5jcnlwdGVkIHZhcmlhYmxlCg==";
            var expectedValue = "decrypted variable";

            kmsClient
            .DecryptAsync(Any <DecryptRequest>())
            .Returns(new DecryptResponse
            {
                Plaintext = await CreateStreamFromString(expectedValue),
            });

            var cancellationToken = new CancellationToken(false);
            var response          = await service.Decrypt(value);

            response.Should().BeEquivalentTo(expectedValue);
            await kmsClient.Received().DecryptAsync(Is <DecryptRequest>(req => req.CiphertextBlob != null), Is(cancellationToken));
        }
 private Amazon.KeyManagementService.Model.DecryptResponse CallAWSServiceOperation(IAmazonKeyManagementService client, Amazon.KeyManagementService.Model.DecryptRequest request)
 {
     Utils.Common.WriteVerboseEndpointMessage(this, client.Config, "AWS Key Management Service", "Decrypt");
     try
     {
         #if DESKTOP
         return(client.Decrypt(request));
         #elif CORECLR
         return(client.DecryptAsync(request).GetAwaiter().GetResult());
         #else
                 #error "Unknown build edition"
         #endif
     }
     catch (AmazonServiceException exc)
     {
         var webException = exc.InnerException as System.Net.WebException;
         if (webException != null)
         {
             throw new Exception(Utils.Common.FormatNameResolutionFailureMessage(client.Config, webException.Message), webException);
         }
         throw;
     }
 }
Пример #13
0
        public async Task <Optional <string> > GetSecretAsync(string name, string version = null, Dictionary <string, string> encryptionContext = null, bool throwOnInvalidCipherTextException = true)
        {
            CredstashItem item;

            if (version == null)
            {
                var response = await _amazonDynamoDb.QueryAsync(new QueryRequest()
                {
                    TableName        = Options.Table,
                    Limit            = 1,
                    ScanIndexForward = false,
                    ConsistentRead   = true,
                    KeyConditions    = new Dictionary <string, Condition>()
                    {
                        {
                            "name", new Condition()
                            {
                                ComparisonOperator = ComparisonOperator.EQ,
                                AttributeValueList = new List <AttributeValue>()
                                {
                                    new AttributeValue(name)
                                }
                            }
                        }
                    }
                }).ConfigureAwait(false);

                item = CredstashItem.From(response.Items.FirstOrDefault());
            }
            else
            {
                var response = await _amazonDynamoDb.GetItemAsync(new GetItemRequest()
                {
                    TableName = Options.Table,
                    Key       = new Dictionary <string, AttributeValue>()
                    {
                        { "name", new AttributeValue(name) },
                        { "version", new AttributeValue(version) },
                    }
                }).ConfigureAwait(false);

                item = CredstashItem.From(response.Item);
            }

            if (item == null)
            {
                return(null);
            }

            DecryptResponse decryptResponse;

            try
            {
                decryptResponse = await _amazonKeyManagementService.DecryptAsync(new DecryptRequest()
                {
                    CiphertextBlob    = new MemoryStream(Convert.FromBase64String(item.Key)),
                    EncryptionContext = encryptionContext
                }).ConfigureAwait(false);
            }
            catch (InvalidCiphertextException e)
            {
                if (throwOnInvalidCipherTextException)
                {
                    throw new CredstashException("Could not decrypt hmac key with KMS. The credential may " +
                                                 "require that an encryption context be provided to decrypt " +
                                                 "it.", e);
                }
                return(new Optional <string>());
            }
            catch (Exception e)
            {
                throw new CredstashException("Decryption error", e);
            }
            var bytes   = decryptResponse.Plaintext.ToArray();
            var key     = new byte[32];
            var hmacKey = new byte[32];

            Buffer.BlockCopy(bytes, 0, key, 0, 32);
            Buffer.BlockCopy(bytes, 32, hmacKey, 0, 32);

            var contents = Convert.FromBase64String(item.Contents);

            var hmac   = new HMACSHA256(hmacKey);
            var result = hmac.ComputeHash(contents);

            if (!result.ToHexString().Equals(item.Hmac))
            {
                throw new CredstashException($"HMAC Failure for {item.Name} v{item.Version}");
            }

            IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CTR/NoPadding");

            cipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), _initializationVector));
            byte[] plaintext = cipher.DoFinal(contents);
            return(Encoding.UTF8.GetString(plaintext));
        }
Пример #14
0
        protected virtual async Task InitializeAsync(ILambdaConfigSource envSource, ILambdaContext context)
        {
            // read configuration from environment variables
            DeploymentTier      = envSource.Read("TIER");
            ModuleName          = envSource.Read("MODULE");
            _deadLetterQueueUrl = envSource.Read("DEADLETTERQUEUE");
            _loggingTopicArn    = envSource.Read("LOGGINGTOPIC");
            var framework = envSource.Read("LAMBDARUNTIME");

            LogInfo($"TIER = {DeploymentTier}");
            LogInfo($"MODULE = {ModuleName}");
            LogInfo($"DEADLETTERQUEUE = {_deadLetterQueueUrl ?? "NONE"}");
            LogInfo($"LOGGINGTOPIC = {_loggingTopicArn ?? "NONE"}");

            // read optional git-sha file
            var gitsha = File.Exists("gitsha.txt") ? File.ReadAllText("gitsha.txt") : null;

            LogInfo($"GITSHA = {gitsha ?? "NONE"}");

            // read module parameter values from parameters file
            var parameters = await ParseParameters("/", File.ReadAllText("parameters.json"));

            // create config where environment variables take precedence over those found in the parameter file
            _appConfig = new LambdaConfig(new LambdaMultiSource(new[] {
                envSource,
                new LambdaDictionarySource("", parameters)
            }));

            // initialize rollbar
            var          rollbarAccessToken = _appConfig.ReadText("RollbarToken", defaultValue: null);
            const string proxy    = "";
            const string platform = "lambda";

            _rollbarClient = RollbarClient.Create(new RollbarConfiguration(

                                                      // NOTE (2018-08-06, bjorg): the rollbar access token determines the rollbar project
                                                      //  the error report is associated with; when rollbar intergration is disabled,
                                                      //  use the module name instead so the logging recipient can determine the module
                                                      //  the log entry belongs to.
                                                      rollbarAccessToken ?? ModuleName,
                                                      proxy,
                                                      DeploymentTier,
                                                      platform,
                                                      framework,
                                                      gitsha
                                                      ));
            _rollbarEnabled = (rollbarAccessToken != null);
            LogInfo($"ROLLBAR = {(_rollbarEnabled ? "ENABLED" : "DISABLED")}");

            // local functions
            async Task <Dictionary <string, string> > ParseParameters(string parameterPrefix, string json)
            {
                var functionParameters = JsonConvert.DeserializeObject <Dictionary <string, LambdaFunctionParameter> >(json);
                var flatten            = new Dictionary <string, string>();

                await Flatten(functionParameters, parameterPrefix, "STACK_", flatten);

                return(flatten);

                // local functions
                async Task Flatten(Dictionary <string, LambdaFunctionParameter> source, string prefix, string envPrefix, Dictionary <string, string> target)
                {
                    foreach (var kv in source)
                    {
                        var value = kv.Value.Value;
                        switch (kv.Value.Type)
                        {
                        case LambdaFunctionParameterType.Collection:
                            await Flatten((Dictionary <string, LambdaFunctionParameter>) value, prefix + kv.Key + "/", envPrefix + kv.Key.ToUpperInvariant() + "_", target);

                            break;

                        case LambdaFunctionParameterType.Secret: {
                            var secret          = (string)value;
                            var plaintextStream = (await _kmsClient.DecryptAsync(new DecryptRequest {
                                    CiphertextBlob = new MemoryStream(Convert.FromBase64String(secret)),
                                    EncryptionContext = kv.Value.EncryptionContext
                                })).Plaintext;
                            target.Add(prefix + kv.Key, Encoding.UTF8.GetString(plaintextStream.ToArray()));
                            break;
                        }

                        case LambdaFunctionParameterType.Stack:
                            target.Add(prefix + kv.Key, envSource.Read(envPrefix + kv.Key.ToUpperInvariant()));
                            break;

                        case LambdaFunctionParameterType.Text:
                            target.Add(prefix + kv.Key, (string)value);
                            break;

                        default:
                            throw new NotSupportedException($"unsupported parameter type: '{kv.Value.Type.ToString()}'");
                        }
                    }
                }
            }
        }