【问题标题】:How to use S3 SSE C (Server Side Encryption with Client Provided Keys) with Ruby如何在 Ruby 中使用 S3 SSE C(使用客户端提供的密钥进行服务器端加密)
【发布时间】:2020-01-19 11:34:10
【问题描述】:

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

ArgumentError: header x-amz-server-side-encryption-customer-key 具有字段值“QkExM0JGRTNDMUUyRDRCQzA5NjAwNEQ2MjRBNkExMDYwQzBGQjcxODJDMjM0\nnMUE2MTNENDRCOTcxRjA2Qzk1Mg=”,这不能包括 CR/LF

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

使用此标头提供 256 位、base64 编码的加密密钥 供 Amazon S3 用于加密或解密您的数据。

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

  • :sse_customer_algorithm (String) — 指定加密对象时使用的算法(例如,
  • :sse_customer_key (String) — 指定客户提供的供 Amazon S3 使用的加密密钥
  • :sse_customer_key_md5 (String) — 根据 RFC 指定加密密钥的 128 位 MD5 摘要

(我没有抄错,AWS 文档实际上是这样写的)

因此,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:密钥对 指定算法

我不确定我是否错误地生成了密钥,或者我是否提供了错误的密钥(或者这完全是一个不同的问题)。

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

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

【问题讨论】:

  • Base64.strict_encode64(key) 也许?

标签: ruby amazon-web-services amazon-s3 encryption aes


【解决方案1】:

首先,请确保您使用的是来自here的最新版SDK(2.2.2.2)

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

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();
}

【讨论】:

  • 这不是 Ruby
【解决方案2】:

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

正如 cmets 中的同事所说,strict_encode64 是一个选项,因为它符合 RFC 2045。

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

希望对您有所帮助! :)

【讨论】:

  • 我不是 100% 相信这是答案(还)。如果我这样做,我会在这里更新!
猜你喜欢
  • 1970-01-01
  • 2017-02-03
  • 2016-05-27
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 2016-10-16
相关资源
最近更新 更多