コード例 #1
0
        public async Task PutAsync(string name, string secret, string kmsKey = "alias/credstash", bool autoVersion = true, string versionArg = null, Dictionary <string, string> encryptionContext = null, int?expireEpoch = null)
        {
            var version         = autoVersion ? IntWithPadding((await GetHighestVersion(name).ConfigureAwait(false) + 1).ToString()) : IntWithPadding(versionArg ?? string.Empty);
            var keyDataResponse = await GenerateKeyData(kmsKey, encryptionContext).ConfigureAwait(false);

            var encryptionResponse = SealAes(keyDataResponse, secret);

            var key      = Convert.ToBase64String(keyDataResponse.CiphertextBlob);
            var contents = Convert.ToBase64String(encryptionResponse.CipherText);
            var hmac     = encryptionResponse.Hmac.ToHexString();

            var credstashItem = new CredstashItem(name, version, contents, CredstashItem.DefaultDigest, hmac, key);

            await _amazonDynamoDb.PutItemAsync(new PutItemRequest
            {
                Item                     = CredstashItem.ToAttributeValueDict(credstashItem, expireEpoch),
                TableName                = Options.Table,
                ConditionExpression      = "attribute_not_exists(#name)",
                ExpressionAttributeNames = new Dictionary <string, string> {
                    { "#name", "name" }
                }
            }).ConfigureAwait(false);
        }
コード例 #2
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));
        }