如果使用context :: use_private_key传递私钥,则不会调用asio ssl:password callback

时间:2014-11-30 21:35:28

标签: c++ ssl boost boost-asio

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

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

我打算让测试自给自足,而不是依赖文件来指定私钥,所以我想在测试中对密钥及其密码进行硬编码(它们只是测试密钥和密码)。

代码如下。现在它什么也没做,但我只是在指定私钥时尝试使密码回调工作:

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\
MIIFJjCCAw4CCQDQjrFrRcdRkjANBgkqhkiG9w0BAQsFADBVMQswCQYDVQQGEwJT\n\
BLABLABLABLA";

    std::string key = "-----BEGIN RSA PRIVATE KEY-----\n\
Proc-Type: 4,ENCRYPTED\n\
DEK-Info: DES-EDE3-CBC,06622C22CAB27AC2\n\
\n\
JMudxXy4ZxB733xh7QO4elsVCTzJZuWl9Go4ZMuWx0DZb2fYHqXynKZSf7UactSw\n\
vhKJnLPZaa5U+xOr9cdpSd3SwtQyNu6yaVQH3af2ILRwUsw9mQmI8yqIIF1Y6AgV\n\
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替换为use_private_key_file,则会调用回调。

我希望在使用password_callback时也可以调用use_private_key

我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

这反映了底层OpenSSL API的限制:

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

  

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

(来自ssl_ctx_use_privatekey_file

考虑从应用程序内部使用 raw 键。从查看二进制文件时难以发现原始密钥。当然,您可以将密钥分散到位并手动加密,但请记住,确定的攻击者总是能够解决它。

这背后的基本原理可能是,密码短语保护的密钥文件可以安全地传递,只要密码短语不会同时传递。只要将密钥嵌入到也包含用于解密密码的密码中的程序中,传递它本身就是不安全的。

<强>更新

事实上,通过修补Boost Asio来获得理想的行为并不困难:use_private_key上下文成员函数最终调用::PEM_read_bio_PrivateKey does support a password callback

您可以添加它:

  //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开发者/推广邮件列表是否有兴趣将其添加为功能。