如何在更新的LWP中使用PKCS12 SSL证书?

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个回答

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证书,因此至少对于这部分问题,我仍在搜索中。


跟进-一年后...我将我的PKCS12证书转换成了另一种格式,并使用了那个格式-并责备我的供应商合作伙伴选择了那种格式。 - Ether

1

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

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);

真正的痛苦在于如何让它与代理一起工作。

0

LWP 6.02 开始,LWP 对 HTTPS 的处理已经拆分到 LWP::Protocol::https 上,它依赖于 IO::Socket::SSL,除非明确覆盖了默认设置 explicitly overridden

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

0
IO::Socket::SSL 的最新版本 1.988 已经支持 DER 和 PKCS#12 格式,因此现在可以直接在 SSL_cert_file 中提供 PKCS#12 文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接