我在使用gnutls-cli
命令和ruby代码测试网站的cert pinning时发现了一个奇怪的现象,有时候两种方法得到的证书信任链数量不一样。
命令行gnutls-cli github-cloud.s3.amazonaws.com
将得到4:
(我删除了一些冗余信息)
Certificate[0] info:
subject `CN=*.s3.amazonaws.com'
pin-sha256="hK1awhGE7onU0O+/0pwyTCX1ngEBhLhdNNtD8P11+xY="
Certificate[1] info:
subject `CN=Amazon,OU=Server CA 1B,O=Amazon,C=US'
pin-sha256="JSMzqOOrtyOT1kmau6zKhgT676hGgczD5VMdRMyJZFA="
Certificate[2] info:
subject `CN=Amazon Root CA 1,O=Amazon,C=US'
pin-sha256="++MBgDH5WGvL9Bcn5Be30cRcL0f5O+NyoXuWtQdX1aI="
Certificate[3] info:
subject `CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\
pin-sha256="KwccWaCgrnaw6tsrrSO61FgLacNgG2MMLq8GE6+oP5I="
使用ruby(www.example.com):github-cloud.s3.amazonaws.com):
/CN=*.s3.amazonaws.com
hK1awhGE7onU0O+/0pwyTCX1ngEBhLhdNNtD8P11+xY=
/C=US/O=Amazon/OU=Server CA 1B/CN=Amazon
JSMzqOOrtyOT1kmau6zKhgT676hGgczD5VMdRMyJZFA=
/C=US/O=Amazon/CN=Amazon Root CA 1
++MBgDH5WGvL9Bcn5Be30cRcL0f5O+NyoXuWtQdX1aI=
命令行gnutls-cli www.netflix.com
将得到2:
Certificate[0] info:
subject `CN=www.netflix.com,O=Netflix\, Inc.
pin-sha256:3TGagkVvINvo827M04z0YZlg5kctebcod1Qwb83pA0s=
Certificate[1] info:
subject `CN=DigiCert TLS RSA SHA256 2020 CA1,O=DigiCert Inc
pin-sha256="RQeZkB42znUfsDIIFWIRiYEcKl7nHwNFwWCrnMMJbVc="
使用Ruby(www.netflix.com):
/C=US/ST=California/L=Los Gatos/O=Netflix, Inc./CN=www.netflix.com
3TGagkVvINvo827M04z0YZlg5kctebcod1Qwb83pA0s=
/C=US/O=DigiCert Inc/CN=DigiCert TLS RSA SHA256 2020 CA1
RQeZkB42znUfsDIIFWIRiYEcKl7nHwNFwWCrnMMJbVc=
/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=
下面是Ruby代码:
#!/usr/bin/env ruby
require 'colorize'
require 'net/http'
require 'openssl'
require 'base64'
domain = "www.netflix.com"
http = Net::HTTP.new(domain, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_callback = lambda do | preverify_ok, cert_store |
return false unless preverify_ok
end_cert = cert_store.chain[0]
return true unless end_cert.to_der == cert_store.current_cert.to_der
cert_store.chain.each do |i|
sha256 = OpenSSL::Digest::SHA256.new
digest = sha256.digest(i.public_key.to_der)
spki = Base64.strict_encode64(digest)
puts i.subject.to_s, spki
end
true
end
res = http.get '/'
对Implementing HTTPS certificate/pubkey pinning with Ruby的拼音代码引用
谢谢!
1条答案
按热度按时间zkure5ic1#
以www.netflix.com为例,信任链中使用了三个证书:
1.公钥PIN为
3TGagkVvINvo827M04z0YZlg5kctebcod1Qwb83pA0s=
的CN=www.netflix.com
证书,其签名人为:CN=DigiCert TLS RSA SHA256 2020 CA1
,公钥PIN为RQeZkB42znUfsDIIFWIRiYEcKl7nHwNFwWCrnMMJbVc=
,签名人为:CN=DigiCert Global Root CA
,公钥PIN码r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=
1和#2是在您与远程主机建立连接时由远程主机发送给您的。#3存在于您的设备上,用于验证#1和#2是否为您可以信任的有效证书。
当您在Net::HTTP内部使用OpenSSL连接到这些主机时,它会提供额外的信息,并打印完整的信任证书链,以便您知道根CA签署了什么#2。您没有通过线路与#1和#2沿着发送#3,但它会告诉您,因为OpenSSL知道它是信任链的一部分。
当您使用
gnutls-cli www.netflix.com --print-cert </dev/null 2>&1
进行连接时,它非常简洁,只打印#1和#2 --远程主机发送的证书--并告诉您:状态:证书受信任。
...基于它知道您磁盘上的根CA用于签署中间证书,并且中间证书用于签署Netflix证书。
连接或收到的响应没有什么不同;只是工具在运行时打印出来的内容不同。