为什么ruby get cert信任链与gnutls-cli不同

i7uaboj4  于 2023-02-12  发布在  Ruby
关注(0)|答案(1)|浏览(121)

我在使用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的拼音代码引用
谢谢!

zkure5ic

zkure5ic1#

www.netflix.com为例,信任链中使用了三个证书:
1.公钥PIN为3TGagkVvINvo827M04z0YZlg5kctebcod1Qwb83pA0s=CN=www.netflix.com证书,其签名人为:

  1. DigiCert中介证书CN=DigiCert TLS RSA SHA256 2020 CA1,公钥PIN为RQeZkB42znUfsDIIFWIRiYEcKl7nHwNFwWCrnMMJbVc=,签名人为:
  2. DigiCert根证书颁发机构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证书。
连接或收到的响应没有什么不同;只是工具在运行时打印出来的内容不同。

相关问题