【问题标题】:OpenSSL API with AES encryption with GCM (Galois Counter Mode)带有 GCM 的 AES 加密的 OpenSSL API(伽罗瓦计数器模式)
【发布时间】:2018-09-26 18:58:44
【问题描述】:

我在 C++ 中使用 OpenSSL API 来执行私钥的基本加密/解密。我正在尝试不同的加密模式,由于某种原因,在使用 GCM (Galois Counter Mode) 加密和 AES 时出现错误。其他模式(例如 CBC)也可以正常工作。

相关代码(为清楚起见进行了编辑)是:

void encrypt_private_key(
  EVP_PKEY* key_handle,
  const char* password, 
  std::size_t password_length
)
{
  std::unique_ptr<BIO, decltype(&BIO_free)> bio_ptr(BIO_new(BIO_s_mem()), &BIO_free);
  if (!bio_ptr) { /* handle error */ }

  const EVP_CIPHER* enc = EVP_aes_256_gcm();
  int result = PEM_write_bio_PKCS8PrivateKey(
    bio_ptr.get(), 
    key_handle, 
    enc, 
    const_cast<char*>(password),
    password_length, 
    nullptr, 
    nullptr
  );

  if (result != 1) { /* handle error code */ }

  // ... do stuff with encrypted key
}

在这里,我得到一个错误代码。当我使用ERR_reason_error_string() 打印错误代码时,我收到消息"error setting cipher params"

请注意,如果我将密码从 EVP_aes_256_gcm() 更改为 EVP_aes_256_cbc(),它可以正常工作。

阅读relevant docs,我看到GCM 模式可以使用EVP_CIPHER_CTX_ctrl 函数获取一些额外的参数和调整。但是,AFAIK 这似乎是可选的。除了传递给PEM_write_bio_PKCS8PrivateKey 的参数之外,我没有看到为什么EVP_aes_256_gcm() 不应该在没有设置其他参数的情况下正常工作的原因。

那么我在这里做错了什么?

为什么我在尝试将 GCM 模式与 AES 加密一起使用时会出错?会不会是 OpenSSL 根本没有实现这一点? (我在这里使用的是旧版本的 OpenSSL - OpenSSL 1.0 - 所以这可能是问题所在。但是,如果它不支持 GCM 模式,我希望得到一个编译时错误,告诉我 EVP_aes_256_gcm() 甚至不是定义,而不是像这样的运行时错误。)

【问题讨论】:

    标签: c++ encryption openssl


    【解决方案1】:

    不支持此 GCM 操作模式作为加密私钥的密码。使用 openssl genpkey 工具,版本 1.0.2n,用于生成 PKCS#8 格式的私钥,以下命令显示您遇到的相同错误消息:

    $ openssl genpkey -algorithm rsa -aes-128-gcm
    ..............++++++
    .......++++++
    Enter PEM pass phrase:
    Verifying - Enter PEM pass phrase:
    Error writing key
    140736195879880:error:0D0A7072:asn1 encoding routines:PKCS5_pbe2_set_iv:error setting cipher params:p5_pbev2.c:131:
    140736195879880:error:2307D00D:PKCS12 routines:PKCS8_encrypt:ASN1 lib:p12_p8e.c:86:
    

    1.1.1 尝试同样的事情看起来更干净一些,但仍然没有运气:

    $openssl genpkey -algorithm rsa -aes-128-gcm
    genpkey: cipher mode not supported
    

    对于该版本,主程序级别的genpkey 工具的代码显式测试提供的密码here 以检查不支持的模式:

            if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE ||
                EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE ||
                EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE ||
                EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE) {
                BIO_printf(bio_err, "%s: cipher mode not supported\n", prog);
    

    确实,出于验证目的,此命令适用于 CBC 操作模式:

    $ openssl genpkey -algorithm rsa -aes-128-cbc
    .................++++++
    ..........................................................++++++
    Enter PEM pass phrase:
    Verifying - Enter PEM pass phrase:
    -----BEGIN ENCRYPTED PRIVATE KEY-----
    MIICzzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI/XYjzz9DQGgCAggA
    MB0GCWCGSAFlAwQBAgQQPCvupCCVI57DabGCXHCBbwSCAoCCHMMWy4IHvsdkABw2
    <truncated>
    

    你写道:

    但是,如果它不支持 GCM 模式,我希望得到一个编译 时间错误告诉我 EVP_aes_256_gcm() 甚至没有定义, 而不是像这样的运行时错误。

    一般不是不支持GCM模式,而是在做PKCS#8时不支持GCM模式加密私钥。在编译时无法知道该限制。

    【讨论】:

      【解决方案2】:

      我建议尝试 BoringSSL 库,它是 Google 的 OpenSSL 分支的一个分支。显然,他们在 GCM 中使用 AES 265 位加密从 Windows 上的 Chrome 版本 80 开始的 cookie(2020 年 2 月)

      【讨论】:

      • 那么我在这里做错了什么? 是个问题。这没有回答。
      猜你喜欢
      • 2016-10-14
      • 1970-01-01
      • 2015-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      • 2017-10-25
      • 1970-01-01
      相关资源
      最近更新 更多