【问题标题】:How can I use a PKCS12 ssl certificate with newer LWP?如何将 PKCS12 ssl 证书与较新的 LWP 一起使用?
【发布时间】:2012-09-19 14:30:51
【问题描述】:

我很难使用新的 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';

...并且 that 在旧 LWP 下也可以正常工作,但在新 LWP 下也无法正常工作。所以至少它不是特定于 PKCS12 证书的问题,而是更多内部更改 SSL 处理方式的基础。

【问题讨论】:

    标签: perl ssl pkcs#12


    【解决方案1】:

    至少对于 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 证书转换为不同的格式并改用它 - 并责备我的供应商合作伙伴选择该格式。
    【解决方案2】:

    我一直在草莓 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);
    

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2012-09-23
          • 1970-01-01
          • 1970-01-01
          • 2017-06-12
          • 2013-08-03
          • 2011-02-16
          • 1970-01-01
          • 1970-01-01
          • 2010-09-09
          相关资源
          最近更新 更多