提升 asio ssl:如果私钥传递上下文::use_private_key,则不调用密码回调

Boost asio ssl: password callback not called if private key passed with context::use_private_key

本文关键字:key private 调用 回调 密码 use 如果 ssl asio 私钥 上下文      更新时间:2023-10-16

我正在编写一个使用boost asio ssl的测试单元。

我在 Ubuntu 1.54 上使用 Boost 14.04 64 位。

我计划使测试自给自足,而不是依赖文件来指定私钥,因此我想在测试本身中对密钥及其密码进行硬编码(它们只是测试密钥和密码(。

代码如下。目前它什么都不做,但我只是试图在指定私钥时使密码回调工作:

std::string password_callback(
  std::size_t max_length,
  boost::asio::ssl::context::password_purpose purpose)
{
    return "test";
}
TEST(StreamReader, sslStream)
{
    std::string certificate = "-----BEGIN CERTIFICATE-----n
MIIFJjCCAw4CCQDQjrFrRcdRkjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJTn
BLABLABLABLA";
    std::string key = "-----BEGIN RSA PRIVATE KEY-----n
Proc-Type: 4,ENCRYPTEDn
DEK-Info: DES-EDE3-CBC,06622C22CAB27AC2n
n
JMudxXy4ZxB733xh7QO4elsVCTzJZuWl9Go4ZMuWx0DZb2fYHqXynKZSf7UactSwn
vhKJnLPZaa5U+xOr9cdpSd3SwtQyNu6yaVQH3af2ILRwUsw9mQmI8yqIIF1Y6AgVn
BLABLABLABLA";
    boost::asio::io_service io_service;
    boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12);
    ctx.set_password_callback(password_callback);
    ctx.use_certificate(boost::asio::const_buffer(certificate.c_str(), certificate.size()), boost::asio::ssl::context::pem);
    ctx.use_private_key(boost::asio::const_buffer(key.c_str(), key.size()), boost::asio::ssl::context::pem);
    ctx.set_verify_mode(boost::asio::ssl::verify_peer);
}

执行use_private_key时,不会调用密码回调,我必须在控制台中手动输入密码。如果我用use_private_key_file替换use_private_key,则调用回调。

我希望在使用use_private_key时也会调用password_callback

我错过了什么吗?

反映了底层OpenSSL API的限制:

加密仅适用于从文件加载密钥:

从文件加载的私钥可以加密。为了成功加载加密密钥,必须提供返回密码的函数,请参见ssl_ctx_set_default_passwd_cb(3(。(从技术角度来看,证书文件也可能被加密,但是没有意义,因为证书中的数据无论如何都被认为是公开的。

(来自ssl_ctx_use_privatekey_file(

请考虑在应用程序内部使用原始密钥。通过查看二进制文件应该很难发现原始密钥。当然,您可以将密钥分散在位中并手动加密它们,但请记住,坚定的攻击者总是可以弄清楚的。

这背后的基本原理可能是,只要密码不同时传递,就可以安全地传递受密码保护的密钥文件。一旦您将密钥嵌入到还包含用于解密它的密码短语的程序中,无论如何传递它本质上都是不安全的。

更新

事实上,通过修补 Boost Asio 来获得所需的行为应该不难:use_private_key上下文成员函数最终调用支持密码回调::PEM_read_bio_PrivateKey

您可以添加它:

  //evp_private_key.p = ::PEM_read_bio_PrivateKey(bio.p, 0, 0, 0);
  evp_private_key.p = ::PEM_read_bio_PrivateKey(bio.p, 0, 
          handle_->default_passwd_callback,
          handle_->default_passwd_callback_userdata); // SEHE WAS HERE

以获得您想要的行为。

请务必 ping Asio 开发人员/boost 邮件列表,无论他们是否有兴趣将其添加为一项功能。

我必须更新此线程,因为我处于同样的情况。似乎现在已实现对此的支持:

https://github.com/boostorg/asio/blob/a2204b67f85cf63936a1daaacee830b6b69cec9f/include/boost/asio/ssl/impl/context.ipp#L845

好消息!