如何在较新的LWP中使用PKCS12 ssl证书?

时间:2012-09-27 18:09:40

标签: perl ssl pkcs#12

我很难使用新的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 个答案:

答案 0 :(得分: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证书,所以对于问题的这一部分至少,我仍在搜索。

答案 1 :(得分:1)

我一直在使用带有WWW :: Mechanize 1.72的草莓perl 5.14.2中的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);

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

答案 2 :(得分:0)

LWP 6.02起,LWP对HTTPS的处理已解除绑定到LWP::Protocol::https,取决于使用IO::Socket::SSL,除非该默认值为explicitly overridden

假设您在加载use Net::SSL之前未添加$Net::HTTPS::SSL_SOCKET_CLASS或覆盖LWP::UserAgent,则会自动选择IO::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 });

答案 3 :(得分:0)

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