如何将 S3 SSE C(使用客户端提供的密钥的服务器端加密)与 Ruby 一起使用

How to use S3 SSE C (Server Side Encryption with Client Provided Keys) with Ruby

我正在尝试将文件上传到 S3 并使用 SSE-C encryption options 对其进行加密。我可以在没有 SSE-C 选项的情况下上传,但是当我提供 sse_customer_key 选项时,我收到以下错误:

ArgumentError: header x-amz-server-side-encryption-customer-key has field value "QkExM0JGRTNDMUUyRDRCQzA5NjAwNEQ2MjRBNkExMDYwQzBGQjcxODJDMjM0\nnMUE2MTNENDRCOTcxRjA2Qzk1Mg=", this cannot include CR/LF

我不确定问题出在我生成的密钥上还是编码上。我在这里尝试过不同的选项,但 AWS 文档不是很清楚。在一般的 SSE-C 文档中,它说您需要提供一个 x-amz-server-side -encryption -customer-key header,它被描述像这样:

Use this header to provide the 256-bit, base64-encoded encryption key for Amazon S3 to use to encrypt or decrypt your data.

但是,如果我查看 uploading a file 的 Ruby SDK 文档,这 3 个选项的描述略有不同

(我没有抄错,AWS 文档字面意思就是half-written)

所以 SDK 文档看起来像是您提供了原始 sse_customer_key 并且它会代表您对其进行 base64 编码(这对我来说很有意义)。

所以现在我正在构建这样的选项:

  sse_customer_algorithm: :AES256,
  sse_customer_key: sse_customer_key,
  sse_customer_key_md5: Digest::MD5.hexdigest(sse_customer_key)

我之前尝试过 Base64.encode64(sse_customer_key) 但这给了我一个不同的错误:

Aws::S3::Errors::InvalidArgument: The secret key was invalid for the specified algorithm

我不确定是我生成的密钥不正确还是我提供的密钥不正确(或者这完全是另一个问题)。

这就是我生成密钥的方式:

require "openssl"
OpenSSL::Cipher.new("AES-256-CBC").random_key

哦,你有没有注意到你的密钥包含'\n'?这很可能就是您收到 CR/LF 错误的原因: QkExM0JGRTNDMUUyRDRCQzA5NjAwNEQ2MjRBNkExMDYwQzBGQjcxODJDMjM0(\n)nMUE2MTNENDRCOTcxRjA2Qzk1Mg=

正如同事在评论中提到的,strict_encode64 是一个选项,因为它符合 RFC 2045。

顺便说一句,我从这里得到了这个见解:https://bugs.ruby-lang.org/issues/14664

希望对您有所帮助! :)

首先,请确保您使用的是 here

的最新版本 SDK (2.2.2.2)

因此,据我了解,当我们生成预签名的 URL 时,我们必须指定 SSECustomerMethod,并且在使用 URL 时,设置 "x-amz-server-side-encryption-customer-key" header使用客户密钥,您还需要设置 "x-amz-server-side-encryption-customer-algorithm" header.

var getPresignedUrlRequest = new GetPreSignedUrlRequest
{
    BucketName = bucketName,
    Key = "EncryptedObject",
    SSECustomerMethod= SSECustomerMethod.AES256,
    Expires = DateTime.Now.AddMinutes(5)
};
var url = AWSClients.S3.GetPreSignedURL(getPresignedUrlRequest);
var webRequest = HttpWebRequest.Create(url);
webRequest.Headers.Add("x-amz-server-side-encryption-customer-algorithm", "AES256");
webRequest.Headers.Add("x-amz-server-side-encryption-customer-key", base64Key);

using (var response = webRequest.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
{
    var contents = reader.ReadToEnd();
}