【问题标题】:Simple DER Cert Parsing in pythonpython中的简单DER证书解析
【发布时间】:2021-11-17 22:43:18
【问题描述】:

使用 python 解析具有 DER 格式的 X509 证书的二进制文件以提取公钥的最佳方法是什么。

【问题讨论】:

标签: python ssl-certificate public-key


【解决方案1】:

以上答案有些陈旧(截至 2017 年)。

您可以使用asn1crypto 以更好的方式执行此操作:

from asn1crypto.x509 import Certificate

with open("mycert.der", "rb") as f:
    cert = Certificate.load(f.read())

n = cert.public_key.native["public_key"]["modulus"]
e = cert.public_key.native["public_key"]["public_exponent"]

print("{:#x}".format(n))    # prints the modulus (hexadecimal)
print("{:#x}".format(e))    # same, for the public exponent

它相对较新(据我所知,2015 年年中),提供比已经提到的库更好的界面,并且比作者所说的 pyasn1 快​​得多。

【讨论】:

  • 模数打印命令抛出错误为ValueError: Error parsing asn1crypto.x509.Certificate - tag should have been 16, but 13 was found 为什么会这样?
  • 如果您尝试读取 PEM 格式的证书,可能会发生这种情况。上面的代码适用于 DER 编码的代码。 (有关证书格式的更多信息,请参阅here。)从 PEM 到 DER 的转换应该只是剥离页眉/页脚并对中间部分进行 base64 解码。
【解决方案2】:

我已经很久没有问这个问题了,虽然由于浏览量的原因,我想描述一下我是如何做到的。

通过使用 OpenSSL API,我们可以轻松地以非常易读的方式打印 DER 证书。尽管它的功能非常有限,但这只是一个例子。

print OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_TEXT,x509)

但是,我想直接控制 var 中的键(需要将其发送到其他函数),为此,我创建了以下函数

def parse_asn1_der(derfile):
    from pyasn1_modules import  rfc2437,rfc2459
    from pyasn1.codec.der import decoder
    certType = rfc2459.Certificate(); 
    raw=derfile #the result of open(fname,"rb").read()
    cert,rest = decoder.decode(raw, asn1Spec=certType)
    RSAKEYSDATA=frombits(cert.getComponentByName("tbsCertificate").getComponentByName("subjectPublicKeyInfo").getComponentByName("subjectPublicKey"))
    SignatureCert=frombits(cert.getComponentByName("signatureValue")).encode("hex")
    rsaType=rfc2437.RSAPublicKey();
    rsadata,rsadata_rest = decoder.decode(RSAKEYSDATA, asn1Spec=rsaType)
    print "----"
    print "Certificate Plain Data"
    print "RSA Modulus: %X" %rsadata.getComponentByName("modulus")
    print "RSA Public exponent: %X" %rsadata.getComponentByName("publicExponent")
    print "Signature: %s"%SignatureCert
    return rsadata.getComponentByName("modulus")

希望它可以帮助任何环顾四周的人。

【讨论】:

    【解决方案3】:

    Python 的内置 SSL 模块和 PyOpenSSL 都没有 API 来提取私钥并访问其信息。 M2Crypto 不再维护,并且不适用于 OpenSSL 1.0 及更高版本。

    PyOpenSSL 有一个公钥类,但它的功能有限:

    >>> with open("cert.der", "rb") as f:
    ...     der = f.read()
    ... 
    >>> import OpenSSL.crypto
    >>> x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, der)
    >>> pkey = x509.get_pubkey()
    >>> dir(pkey)
    ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'bits', 'check', 'generate_key', 'type']
    >>> pkey.bits()
    4096L
    >>> pkey.type() == OpenSSL.crypto.TYPE_RSA
    True
    

    Python 3.4 可能会获得 X509 类型,该类型会公开更多信息,例如 SPKI。

    【讨论】:

    • 存在任何方式来打印所有已解析的证书(就像 pyasn1.printPretty())或至少将 pubkey 打印为十六进制字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 2014-02-24
    • 1970-01-01
    • 2022-06-23
    相关资源
    最近更新 更多