我正在构建一个基于 Qt 的应用程序,它将通过 https 与网络服务器进行通信。该设置应允许使用本地证书和私钥进行客户端身份验证。应用程序必须在没有任何用户交互的情况下运行。
现在,当私钥文件受密码保护时,我遇到了一个问题:
OpenSSL 会提示输入密码,从而阻止整个应用程序!
openSSL API 允许通过回调来获取密码,但是通过 Qt Wrapper 无法访问。还有其他方法可以防止 openSSL 提示输入密码吗?或者这可以以某种方式被打断?
您可以在构造 QSslKey 时指定密码。构造函数采用一个密码短语,用于解密密钥,请参阅以下链接中的文档:
我想出了一个解决方案:
当解码函数中没有指定密码时,OpenSSL 只会提示输入密码。正如理查德摩尔在他的回答中指出的那样,QSslKey
有一个构造函数,您可以在其中传递密码。
只要在此处传递一个非空字符串,OpenSSL 就不会提示输入密码。加:如果密钥不受保护,密码将被忽略。因此,我只是确保传递了一个非空字符串,所以这是我的解决方案:
// Never use empty PWD, as this blocks. (Use null-string)
// PLUS: setting a password for a non-protected key still correctly loads the key!
QByteArray thePwd = pwd.isEmpty() ? QByteArray("\0", 1) : pwd.toUtf8();
// Try all encodings
QList<QSslKey> keys = QList<QSslKey>()
<< QSslKey( theKey, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, thePwd )
<< QSslKey( theKey, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey, thePwd )
<< QSslKey( theKey, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, thePwd )
<< QSslKey( theKey, QSsl::Dsa, QSsl::Der, QSsl::PrivateKey, thePwd );
// Find a valid encoding
foreach ( QSslKey k, keys ) {
if ( !k.isNull() ) {
ret = k;
break;
}
}
在查看在线文档时,我在解密私钥时看不到任何回调选项。
最简单的方法是使私钥免密码。以下是你可以做到的(假设你有受密码保护的 RSA 密钥):
openssl rsa -in privateKey.pem -out newPrivateKey.pem
这里privateKey.pem
有密码保护,但newPrivateKey.pem
不是。请注意,虽然这意味着私钥不受保护,但这是进行不间断 SSL 通信的常用技术(即使在stunnel
例如使用)。假设私钥存储在具有受限权限并受操作系统访问策略保护的目录中。
更难的方法是通过直接与 OpenSSL 链接而不是通过包装器来编写应用程序。这样,您就可以对密码回调进行细粒度控制。