【问题标题】:Is Google returning different certificates for different clients?Google 是否会为不同的客户返回不同的证书?
【发布时间】:2021-11-29 15:53:13
【问题描述】:

对于一个类,我正在查看google.com 的 TLS 证书链。当我在 Chrome 或 Firefox 浏览器中点击时,根证书显示为GTS Root R1,有效期最高为 2036,自签名,所以它必须是根证书。

但是,如果我使用以下代码在 Python 中进行检查,我会得到一个有效期为 2028 的 GTS Root R1 证书,该证书由 GlobalSign nv-sa 签名,所以这次它不是根证书!

Google.com 是否有可能返回两个不同的证书链,具体取决于发出请求的客户端?如果它假设客户端接受GTS Root R1作为根证书,它返回这个,否则它返回一个由GlobalSign nv-sa签名的?

如果是,为什么?

以下是带有证书及其摘要/sha256 的链。现在,当我在浏览器中查看证书链时,前两个具有相同的digest / sha-256,但第三个具有不同的digest。所以我绝对认为我会根据客户获得不同的链条......

Certificate #0
Subject b'CN': b'*.google.com'
notBefore: b'20211101021952Z'
notAfter: b'20220124021951Z'
version:2
sigAlg: b'sha256WithRSAEncryption'
digest: b'E9:7C:86:18:34:DE:F4:11:4D:2D:5E:6F:1A:49:22:A1:04:EE:9E:7C:8D:CB:72:3F:6D:67:58:8F:7E:F3:4B:AB'
issuer: <X509Name object '/C=US/O=Google Trust Services LLC/CN=GTS CA 1C3'>

Certificate #1
Subject b'C': b'US'
Subject b'O': b'Google Trust Services LLC'
Subject b'CN': b'GTS CA 1C3'
notBefore: b'20200813000042Z'
notAfter: b'20270930000042Z'
version:2
sigAlg: b'sha256WithRSAEncryption'
digest: b'23:EC:B0:3E:EC:17:33:8C:4E:33:A6:B4:8A:41:DC:3C:DA:12:28:1B:BC:3F:F8:13:C0:58:9D:6C:C2:38:75:22'
issuer: <X509Name object '/C=US/O=Google Trust Services LLC/CN=GTS Root R1'>

Certificate #2
Subject b'C': b'US'
Subject b'O': b'Google Trust Services LLC'
Subject b'CN': b'GTS Root R1'
notBefore: b'20200619000042Z'
notAfter: b'20280128000042Z'
version:2
sigAlg: b'sha256WithRSAEncryption'
digest: b'3E:E0:27:8D:F7:1F:A3:C1:25:C4:CD:48:7F:01:D7:74:69:4E:6F:C5:7E:0C:D9:4C:24:EF:D7:69:13:39:18:E5'
issuer: <X509Name object '/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA'>

我用来获取证书的python代码:

from OpenSSL import SSL, crypto
import socket, certifi

def dump_cert(cert):
    for component in cert.get_subject().get_components():
        print("Subject %s: %s" % (component))
             
    print("notBefore:", cert.get_notBefore())
    print("notAfter:", cert.get_notAfter())
    print("version:" + str(cert.get_version()))
    print("sigAlg:", cert.get_signature_algorithm())
    print("digest:", cert.digest('sha256'))
    print("issuer:", cert.get_issuer())
    print()
    
def get_connection_chain(host, port = 443):
    dst = (str.encode(host), port)
    ctx = SSL.Context(SSL.TLSv1_2_METHOD)
    s = socket.create_connection(dst)
    s = SSL.Connection(ctx, s)
    s.set_connect_state()
    s.set_tlsext_host_name(dst[0])

    s.sendall(b'HEAD / HTTP/1.2\n\n')
    s.recv(16)
    return (s, s.get_peer_cert_chain())

def dump_chain(chain):
    for pos, cert in enumerate(chain):
        print("Certificate #" + str(pos))
        dump_cert(cert)

conn, chain = get_connection_chain("google.ch")
dump_chain(chain)

【问题讨论】:

  • 很可能在这两种情况下都发送了相同的证书链,只是浏览器的链验证将在您运行的平台上的第一个 trusted 证书处停止上的浏览器是 GTS Root R1。如果您暂时从受信任证书的平台列表中删除该证书(但确保 Globalsign 仍然存在)并重新连接浏览器,您将看到完整的链。
  • 我用从 python 获得的链更新了问题。当我在浏览器中查看链时,只有前两个证书具有相同的摘要。第三个有不同的摘要,所以当浏览器询问时它肯定会发送不同的证书。
  • "浏览器中的链..." 我的意思是你看到的浏览器显示的链并不完全是发送的链。
  • 我刚刚通过测试确认了这一点。两种情况下都发送相同的链,浏览器只是根据其链验证程序显示不同的根证书。

标签: python ssl ssl-certificate root-certificate


【解决方案1】:

感谢President James K. Polk,我想我更了解发生了什么:

  • 根据https://pki.goog/repository/,具有相同公钥的GTS Root R1证书有两个版本:
    • 根证书GTS Root R1
    • 中间证书GTS Root R1 Cross,由GlobalSign nv-sa签名,是根证书。

因此浏览器会收到问题中给出的证书链。然后从证书链的叶节点开始,即Certificate #0。浏览器通过其存储的根证书列表来验证叶证书。如果没有找到,它会转到下一个条目,Certificate #1

在google.com的例子中,它发现它有一个Certificate #1的根证书并使用这个,忽略Certificate #2。尽管我不太确定它为什么会这样:

  • 它是否希望在某个时候摆脱GlobalSign 证书?
  • 是为了冗余吗?如果一个证书被吊销,另一个证书仍然有效吗?

描述此内容的一篇博文如下:https://scotthelme.co.uk/cross-signing-alternate-trust-paths-how-they-work/

【讨论】:

  • 证书链验证很复杂,但一个简化的版本是这样的:从叶子证书开始。是否格式正确、合理且未过期?它是由证书颁发的我已经完全信任吗?如果是这样,我们就完成了。否则,颁发者是链中的下一个证书吗?如果是这样,请使用该证书重复所有这些测试,依此类推
  • 它希望在某个时候摆脱 GlobalSign 证书吗? 是的,这就是原因。将新的根证书加入 PKI 生态系统是一个艰难而漫长的过程。在发生这种情况时,将有一些平台可以信任您的根,而其他平台则不信任。在此过渡期间,您需要让您的根证书由已经广泛信任的根证书签名,并以与您的示例中所做的完全相同的方式进行部署。一个问题是:为什么 Globalsign 会帮助竞争对手? “为了钱”是一个答案。现实更复杂。
猜你喜欢
  • 1970-01-01
  • 2021-12-31
  • 2014-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
相关资源
最近更新 更多