3

我很难使用新的 LWP (6.x) 获得 PKCS12 证书。基本上,这段代码在 perl5.8.8 和旧的Crypt::SSLeay(0.57 版)和LWP(5.826 版)下工作:

local $ENV{HTTPS_PKCS12_PASSWORD} = $sslPassword;
local $ENV{HTTPS_PKCS12_FILE} = $pkcs12_cert;
my $response = LWP::UserAgent->new->request(POST($url, Content => $content));

...但不在 perl5.14.2 和最新版本的 Crypt::SSLeay 0.64) 和 LWP (6.03) 下。

不起作用,我的意思是我得到了一个 HTTP::Response 对象,例如:

bless( {
     '_content' => 'Can\'t connect to host:port
',
     '_rc' => 500,
     '_headers' => bless( { 
                            'client-warning' => 'Internal response',
                            'client-date' => 'Thu, 27 Sep 2012 18:28:34 GMT',
                            'content-type' => 'text/plain'
                          }, 'HTTP::Headers' ),
     '_msg' => 'Can\'t connect to host:port',
     '_request' => ...
)

我知道最近 LWP 中很多与 ssl 相关的代码发生了变化;PKCS12 支持是否仍然有效?我应该设置不同的变量/选项以获取证书和密码吗?

我也尝试将其传递给 LWP::UserAgent->new 但没有运气:

ssl_opts => {
    SSL_use_cert => 1,
    SSL_cert_file => $pkcs12_cert,
    SSL_passwd_cb => sub { $sslPassword },
}

跟进:我将 PKCS12 证书转换为 PEM:

openssl pkcs12 -in my_pkcs12.p12 -out mycert.pem -clcerts -nokeys
openssl pkcs12 -in my_pkcs.p12 -out mykey.pem -nocerts
<passphrase entered>

并可以通过以下方式使用新文件:

curl -k --cert mycert.pem --key mykey.pem --pass passphrase --cert-type PEM https://url

...并在测试脚本中设置这些环境变量:

$ENV{HTTPS_CERT_FILE} = 'mycert.pem';
$ENV{HTTPS_KEY_FILE}  = 'mykey.pem';

...并且旧 LWP 下也可以正常工作,并且在新 LWP 下也不能正常工作。所以至少它不是特定于 PKCS12 证书的问题,而是在内部更改 SSL 处理方式方面更基本的东西。

4

4 回答 4

3

至少对于 PEM 文件,这适用于新的 LWP(似乎不再识别环境变量 - 可能默认情况下不再使用 Crypt::SSLeay?)

my $ua = LWP::UserAgent->new(
    ssl_opts => {
        SSL_use_cert => 1,
        verify_hostname => 0,
        SSL_cert_file => 'mycert.pem',
        SSL_key_file => 'mypass.pem',
        SSL_passwd_cb => sub { $passphrase },
    },
);

这些选项记录在IO::Socket::SSL中;这里没有提到如何使用 PKCS12 证书,所以至少对于这部分问题,我仍在寻找。

于 2012-09-27T19:00:20.973 回答
1

我一直在草莓 perl 5.14.2 和 WWW::Mechanize 1.72 中使用 PKCS12 证书。

use Net::SSL ();
use WWW::Mechanize;
BEGIN {
    $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "Net::SSL";
    $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
}
$ENV{HTTPS_PKCS12_FILE} = $pfxfile;
$ENV{HTTPS_PKCS12_PASSWORD} = $pfxpass;
$ua = WWW::Mechanize->new();
$ua->cookie_jar({});
$ua->get($url);

真正的痛苦是让它与代理一起工作。

于 2013-11-02T11:04:09.160 回答
0

LWP 6.02开始,LWP 对 HTTPS 的处理被拆分为LWP::Protocol::https,这取决于使用IO::Socket::SSL,除非该默认值被显式覆盖

假设您在加载之前没有添加use Net::SSL或覆盖,它会自动选择不查看环境变量的内容:$Net::HTTPS::SSL_SOCKET_CLASSLWP::UserAgentIO::Socket::SSL

local $ENV{HTTPS_PKCS12_PASSWORD} = $sslPassword;
local $ENV{HTTPS_PKCS12_FILE} = $pkcs12_cert;

如果您确实$Net::HTTPS::SSL_SOCKET_CLASS通过环境或在您的脚本中明确覆盖,您还需要再次通过环境禁用主机验证:

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

或通过

my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
于 2014-04-16T12:00:42.513 回答
0

IO::Socket::SSL (刚刚发布的)1.988 版本增加了对 DER 和 PKCS#12 格式的透明支持,因此现在应该可以在 SSL_cert_file 中简单地提供 PKCS#12 文件。

于 2014-05-17T22:15:44.683 回答