internal virtual Option <JObject> EncryptKeyAndBuildResult(
            IAmazonKeyManagementService kmsClient,
            string region,
            string arn,
            byte[] dataKeyPlainText)
        {
            try
            {
                TimerOptions encryptTimerOptions =
                    new TimerOptions {
                    Name = MetricsUtil.AelMetricsPrefix + ".kms.aws.encrypt." + region
                };
                using (MetricsUtil.MetricsInstance.Measure.Timer.Time(encryptTimerOptions))
                {
                    // Note we can't wipe plaintext key till end of calling method since underlying buffer shared by all requests
                    EncryptRequest encryptRequest = new EncryptRequest
                    {
                        KeyId     = arn,
                        Plaintext = new MemoryStream(dataKeyPlainText)
                    };
                    Task <EncryptResponse> encryptAsync = kmsClient.EncryptAsync(encryptRequest);

                    byte[] encryptedKeyEncryptionKey = encryptAsync.Result.CiphertextBlob.ToArray();

                    return(Option <JObject> .Some(BuildKmsRegionKeyJson(region, arn, encryptedKeyEncryptionKey)));
                }
            }
            catch (AggregateException e)
            {
                Logger.LogWarning(e, "Failed to encrypt generated data key via region {region} KMS", region);

                // TODO Consider adding notification/CW alert
                return(Option <JObject> .None);
            }
        }
        /// <summary>
        /// Encrypts the provided XML element.
        /// </summary>
        /// <param name="plaintextElement">XML element to encrypt.</param>
        /// <param name="ct">Cancellation token.</param>
        /// <returns>Encrypted XML data.</returns>
#pragma warning disable S3242 // Not altering Microsoft interface definition
        public async Task <EncryptedXmlInfo> EncryptAsync(XElement plaintextElement, CancellationToken ct)
#pragma warning restore S3242
        {
            ValidateConfig();

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

            // Some implementations of this e.g. DpapiXmlEncryptor go to some lengths to create a memory
            // stream, use unsafe code to pin & zero it, and so on.
            //
            // Currently not doing any such zeroing here, as this neglects that the XElement above is in memory,
            // is a managed construct containing ultimately a System.String, and therefore the plaintext is
            // already at risk of compromise, copying during GC, paging to disk etc. If we'd been starting with SecureString,
            // there'd be a good pre-existing case for handling the subsequent memory copies carefully (and it'd
            // essentially be forced as you can't copy or stream a SecureString without unsafe code).
            //
            // Even ignoring that, the subsequent code sending a MemoryStream out over the web to AWS calls ToArray inside
            // the SDK and then stores the result as a System.String, twice, as part of outgoing JSON, and that's
            // before considering HTTP-layer buffering...
            //
            // Since the AWS code eventually just gets UTF8 byte[] for request content, the ideal would be that
            // instead of a memory stream and a standard JSON handler, the AWS code prepares all the usual JSON and then
            // gets a specific UTF8 byte[] entry of the base64 plaintext which a caller can pin and erase (and the SDK could
            // do the same with its own request content byte[]).
            //
            // It doesn't.
            //
            // Even then the HttpClient usage would buffer the plaintext enroute.
            //
            // In conclusion pinning & zeroing this particular stream seems to be complex & error-prone overkill for
            // handling data that is already exposed in memory - not that I wouldn't be thrilled to see
            // a properly reviewed SecureMemoryStream and SecureHttpStreamContent in the framework...
            //
            // To at least reduce stream allocation churn & thus copying, pre-allocate a reasonable capacity.
            using (var memoryStream = new MemoryStream(4096))
            {
                plaintextElement.Save(memoryStream);
                memoryStream.Seek(0, SeekOrigin.Begin);

                var response = await kmsClient.EncryptAsync(new EncryptRequest
                {
                    EncryptionContext = ContextUpdater.GetEncryptionContext(Config, dpOptions.Value),
                    GrantTokens       = Config.GrantTokens,
                    KeyId             = Config.KeyId,
                    Plaintext         = memoryStream
                },
                                                            ct)
                               .ConfigureAwait(false);

                using (var cipherText = response.CiphertextBlob)
                {
                    var element = new XElement("encryptedKey",
                                               new XComment(" This key is encrypted with AWS Key Management Service. "),
                                               new XElement("value", Convert.ToBase64String(cipherText.ToArray())));

                    return(new EncryptedXmlInfo(element, typeof(KmsXmlDecryptor)));
                }
            }
        }
示例#3
0
        public async Task <string> Encrypt(string data)
        {
            using (var stream = GenerateStreamFromString(data))
            {
                var req = new EncryptRequest
                {
                    Plaintext = stream,
                    KeyId     = this.keyId
                };
                var response = await client.EncryptAsync(req);

                var result = Convert.ToBase64String(response.CiphertextBlob.ToArray());
                return(result);
            }
        }
示例#4
0
        public EncryptedValue Encrypt(string value, IOutgoingLogicalMessageContext context)
        {
            var encrypted = _client.EncryptAsync(new EncryptRequest
            {
                KeyId     = _encryptionKeyIdentifier,
                Plaintext = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(value))
            }).GetAwaiter().GetResult();

            string base64Value = encrypted != null?Convert.ToBase64String(encrypted.CiphertextBlob.ToArray())  : null;

            context.Headers[EncryptionHeaders.RijndaelKeyIdentifier] = _encryptionKeyIdentifier;

            return(new EncryptedValue
            {
                EncryptedBase64Value = base64Value
            });
        }
示例#5
0
        /// <summary>
        /// Encrypts the passed data with a Master Key. This method will encrypt
        /// a payload up to a maximum size of 4096 bytes. The master key with the
        /// specified ID will be used to encrypt the data.
        /// </summary>
        /// <param name="keyId">The identifier for the master key.</param>
        /// <param name="data">The data to encrypt.</param>
        /// <returns>Encrypted data.</returns>
        /// <exception cref="System.ArgumentNullException"></exception>
        /// <exception cref="System.ArgumentException">You must provide some data to encrypt</exception>
        /// <exception cref="PayloadTooLargeException"></exception>
        /// <exception cref="KeyManagementServiceUnavailableException"></exception>
        public byte[] EncryptData(string keyId, byte[] data)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("AwsKmsKeyManager");
            }

            ValidateMasterKey(keyId);

            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 > MaxEncryptPayloadSize)
            {
                throw new PayloadTooLargeException(MaxEncryptPayloadSize, data.Length);
            }

            var res = RetryPolicy.ExecuteAndCapture(() =>
            {
                using (var msPlainText = new MemoryStream(data))
                {
                    var req = new EncryptRequest
                    {
                        KeyId     = keyId,
                        Plaintext = msPlainText
                    };

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

            ValidateResponse(res);

            return(((EncryptResponse)res.Result).CiphertextBlob.ToArray());
        }
 private Amazon.KeyManagementService.Model.EncryptResponse CallAWSServiceOperation(IAmazonKeyManagementService client, Amazon.KeyManagementService.Model.EncryptRequest request)
 {
     Utils.Common.WriteVerboseEndpointMessage(this, client.Config, "AWS Key Management Service", "Encrypt");
     try
     {
         #if DESKTOP
         return(client.Encrypt(request));
         #elif CORECLR
         return(client.EncryptAsync(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;
     }
 }