perl - 如何验证自签名证书?

标签 perl ssl ssl-certificate io-socket-ssl

我使用 Net::Jabber::Client 通过 XMPP 发送消息。

我连接的服务器使用自签名证书:

DEBUG: .../IO/Socket/SSL.pm:2853: new ctx 45728400
DEBUG: .../IO/Socket/SSL.pm:1540: start handshake
DEBUG: .../IO/Socket/SSL.pm:717: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:750: using SNI with hostname my.host.name
DEBUG: .../IO/Socket/SSL.pm:785: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:806: set socket to non-blocking to enforce timeout=10
DEBUG: .../IO/Socket/SSL.pm:819: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:822: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:832: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:842: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:862: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:819: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2754: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2707: ok=0 [0] /CN=my.host.name/CN=my.host.name
DEBUG: .../IO/Socket/SSL.pm:822: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:825: SSL connect attempt failed

DEBUG: .../IO/Socket/SSL.pm:825: local error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:828: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1963: downgrading SSL only, not closing socket
DEBUG: .../IO/Socket/SSL.pm:2875: free ctx 45728400 open=
DEBUG: .../IO/Socket/SSL.pm:2879: free ctx 45728400 callback
DEBUG: .../IO/Socket/SSL.pm:2886: OK free ctx 45728400

我发现我可以通过SSL_fingerprint和/或SSL_verifycn_name来通过自签名证书的验证。

为了让它正常工作,我破解了 this

my %ssl_params = (
    SSL_verify_mode => $self->{SIDS}->{newconnection}->{ssl_verify},
    SSL_hostname    => 'my.host.name',
    SSL_verifycn_name => 'my.host.name',
);

没有成功=(

我尝试使用->get_fingerprint来获取指纹并将其传递给SSL_fingerprint参数,但是:

IO::Socket::SSL->start_SSL(
    $self->{SIDS}->{$sid}->{sock},
    $self->{SIDS}->{$sid}->{ssl_params}
) or die "$IO::Socket::SSL::SSL_ERROR";

失败并出现错误:

SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed at

哪个选项传递给 IO::Socket::SSL 来验证自签名证书?

最佳答案

使用指纹可能是验证自签名证书的最简单方法,该证书由您自己控制。使用 SSL_fingerprint 时,它不会关心任何其他类型的验证,即不再检查名称、吊销、过期等 - 因此,如果您也想对此进行检查,则不应使用 SSL_fingerprint

获取网站的指纹可以通过在不进行验证的情况下连接到该网站一次(因为您还不信任证书)并获取指纹或直接从证书获取指纹来完成。

通过询问服务器来获取指纹,假设连接没有被拦截,这样就可以得到正确的指纹:

use IO::Socket::SSL;
print IO::Socket::SSL->new(
    PeerHost => 'example.com:443',
    # switch off validation since the certificate is not trusted yet
    SSL_verify_mode => SSL_VERIFY_NONE,
)->get_fingerprint,"\n";

目前给出 sha256$642de54d84c30494157f53f657bf9f89b4ea6c8b16351fd7ec258d556f821040 ,可以直接用作 SSL_fingerprint 的参数。

如果您已经拥有该网站的证书,则可以直接在其上计算指纹:

# get the certificate
$ openssl s_client -connect example.com:443 -servername example.com 
...
-----BEGIN CERTIFICATE-----
MIIF8jCCBNqgAwIBAgIQDmTF+8I2reFLFyrrQceMsDANBgkqhkiG9w0BAQsFADBw
...
-----END CERTIFICATE-----

# take this PEM certificate and get fingerprint
$ openssl x509 -fingerprint -sha256 -noout -in cert.pem
SHA256 Fingerprint=64:2D:E5:4D:84:C3:04:94:15:7F:53:F6:57:BF:9F:89:B4:EA:6C:8B:16:35:1F:D7:EC:25:8D:55:6F:82:10:40

显示的指纹实际上与以前相同,只是书写方式不同。通过删除所有 ':'(仅用于提高可读性),我们会得到 642DE5....1040 ,并通过在其前面添加使用的哈希算法 sha256 ,我们会得到一些东西可用于 SSL_fingerprint:sha256$642DE5...1040

要使用指纹连接到站点:

my $cl = IO::Socket::SSL->new(
    PeerHost => 'example.com:443',
    SSL_fingerprint => 'sha256$642DE5...1040'
);

关于perl - 如何验证自签名证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53400241/

相关文章:

perl - 模块安装成功但找不到

perl - 如何从 Perl 设置文件权限?

python - 安装 virtualenvwrapper-powershell 时出现 HTTP 错误 402

amazon-web-services - AWS 上的 Multi-Tenancy 应用程序 - 多个 SSL 证书安装策略

android - 适用于 Wordpress、IOS 和 Android 的 SSL 证书

android - 带有android应用程序的自签名证书

perl - 如何使用 perl oneliner 将一行使用正则表达式拆分为多行?

arrays - 散列 perl 值中的数组

perl - SSL 握手错误

java - 数字证书如何在SSL之上提供额外的安全性