【问题标题】:How can i get Certificate issuer information in python?如何在 python 中获取证书颁发者信息?
【发布时间】:2015-08-31 22:45:13
【问题描述】:

我想要 python 证书中的“颁发给”信息。我尝试使用 SSL 和 SSLSocket 库但没有发生。

【问题讨论】:

    标签: python ssl certificate ssl-certificate


    【解决方案1】:

    更新答案

    如果可以建立到远程服务器的连接,则可以使用ssl 标准库模块:

    import ssl, socket
    
    hostname = 'google.com'
    ctx = ssl.create_default_context()
    with ctx.wrap_socket(socket.socket(), server_hostname=hostname) as s:
        s.connect((hostname, 443))
        cert = s.getpeercert()
    
    subject = dict(x[0] for x in cert['subject'])
    issued_to = subject['commonName']
    issuer = dict(x[0] for x in cert['issuer'])
    issued_by = issuer['commonName']
    
    >>> issued_to
    u'*.google.com'
    >>> issued_by
    u'Google Internet Authority G2'
    

    原答案

    使用pyOpenSSL

    from OpenSSL import crypto
    
    cert_file = '/path/to/your/certificate'
    cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cert_file).read())
    subject = cert.get_subject()
    issued_to = subject.CN    # the Common Name field
    issuer = cert.get_issuer()
    issued_by = issuer.CN
    

    您还可以访问其他组件,例如组织(subject.O/issuer.O),组织单元(subject.OU/issuer.OU)。

    您的证书文件可能是其他格式,因此您可以尝试使用crypto.FILETYPE_ASN1 而不是crypto.FILETYPE_PEM

    【讨论】:

    • 感谢您的回复..我之前尝试过这个但得到 ImportError: No module named cryptography.hazmat.bindings.openssl.binding 并且尝试导入它但看起来很复杂..你有没有比这更简单的方法。 @mhawke
    • 您似乎没有正确安装 pyOpenSSL。缺少许多依赖项。其中之一是 cryptography 包,它是导致您的错误的包。您可以使用pip install pyopenssl 进行安装,它也应该安装依赖项,但是,您可能需要一个构建环境。您的屏幕截图显示了一个 Windows 环境 - 这可能更难开始。
    • 我已经用仅依赖标准库 sslsocket 模块的替代方法更新了我的原始答案。此方法需要连接到远程服务器,您接受keytool 答案表明这是可能的。我认为这是一个更好的解决方案,因为它不依赖于外部工具(您必须获取/安装/维护),并且它完全基于标准库,因此它可以在操作系统之间移植,而无需担心依赖关系。跨度>
    • 感谢您的回答。python 2.7.6 中没有 create_default_context() 方法,然后我将其升级到 2.7.9。并且此代码有效。是的,为此我不需要安装任何外部工具..再次感谢! @mhawke
    • 嘿!在大多数情况下,这是可行的,尽管我在某些网站上遇到了超时,例如 alipay.com:443,有什么想法吗?
    【解决方案2】:

    如果你使用requests,这里有一个简单的代码:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    
    from requests.packages.urllib3.contrib import pyopenssl as reqs
    
    
    def https_cert_subject_alt_names(host, port):
        """Read subject domains in https cert from remote server"""
    
        x509 = reqs.OpenSSL.crypto.load_certificate(
            reqs.OpenSSL.crypto.FILETYPE_PEM,
            reqs.ssl.get_server_certificate((host, port))
        )
        return reqs.get_subj_alt_name(x509)
    
    if __name__ == '__main__':
        domains = https_cert_subject_alt_names("www.yahoo.com", 443)
        print(domains)
    

    结果如下:

    [('DNS', '*.www.yahoo.com'), 
     ('DNS', 'www.yahoo.com'), 
     ('DNS', 'add.my.yahoo.com'), 
     ('DNS', 'au.yahoo.com'), 
     ('DNS', 'be.yahoo.com'), 
     ('DNS', 'br.yahoo.com'), 
     ('DNS', 'ca.my.yahoo.com'), 
     ('DNS', 'ca.rogers.yahoo.com'), 
     ('DNS', 'ca.yahoo.com'), 
     ('DNS', 'ddl.fp.yahoo.com'), 
     ('DNS', 'de.yahoo.com'), 
     ...
     ('DNS', 'mbp.yimg.com')]
    

    【讨论】:

      【解决方案3】:

      pyOpenSSL 库似乎已经过时,这是官方文档中所说的

      注意:Python Cryptographic Authority 强烈建议使用 pyca/cryptography 尽可能。

      有一些使用 Python 的标准库的变通方法,但其中大多数似乎很混乱。

      这是通过pyca/cryptography 进行操作的方法。它看起来非常简单明了

      from cryptography.x509 import load_pem_x509_certificate
      
      cert = load_pem_x509_certificate(certificate_content)
      certificate_serial_number = cert.serial_number
      certificate_issuer_info = cert.issuer.rfc4514_string()
      certificate_subject_info = cert.subject.rfc4514_string()
      

      结果将打印带有发行人详细信息的整行

      CN=name,O=Org\, Inc.,L=Tucson,ST=Arizona,C=US
      CN=Sectigo RSA Organization Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
      

      如果您需要任何特定的详细信息,可以通过cert.issuer 对象的属性获得。

      【讨论】:

        【解决方案4】:

        import os
        import re
        os.system('keytool -printcert -sslserver google.com:443 >cert.txt')
        fh = open("cert.txt", "r")
        content = fh.readlines()
        fh.close()
        content = content[2]
        m = re.search('CN=(.+?),', content)
        if m:
            found = m.group(1)
        print found
        

        【讨论】:

        • 感谢您的回复.. 请告诉我,什么是 keytool? @pyAnna
        • keytool 是一个密钥和证书管理实用程序。它允许用户使用数字签名管理他们自己的公钥/私钥对和相关证书,以用于自我认证(用户向其他用户/服务认证他/她自己)或数据完整性和认证服务。它还允许用户缓存其通信对等方的公钥(以证书的形式)。
        • 感谢@pyAnna 安装 JDK 后代码已经运行 :)
        猜你喜欢
        • 2016-04-20
        • 2013-07-09
        • 2021-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多