从文件以Python方式导出数字证书信息

nue99wik  于 2023-05-08  发布在  Python
关注(0)|答案(2)|浏览(108)

如果证书本身没有安装在工作站上,而是只用于特定的文件,那么以某种方式“pythonically”导出文件的数字证书的主题是可能的?
我需要以某种方式从文件中提取信息并检查它是否正确。最好使用Python/CMD/PowerShell

我目前使用的是这个python脚本(我修改了它以在Python 3.6上运行):http://www.zedwood.com/article/python-openssl-x509-parse-certificate来解析从原始可执行文件中提取的.cer文件。
我用我找到的这个小工具提取证书(我也修改了它以使用Python 3):https://blog.didierstevens.com/programs/disitool/,然后我用Windows certutil将它从DER编码的二进制转换为base-64。
但是,我用来从文件中提取证书的disitool脚本的问题是,它使用pefile python模块从可执行文件本身中字面上 * 切割 *“签名”字节数组,这使得提取的.cer文件无效,正如我在尝试使用OpenSSL.crypto模块加载证书时不断得到的python错误:

[('asn1 encoding routines', 'asn1_check_tlen', 'wrong tag'), ('asn1 encoding routines', 'asn1_item_embed_d2i', 'nested asn1 error'), ('asn1 encoding routines', 'asn1_template_noexp_d2i', 'nested asn1 error'), ('PEM routines', 'PEM_ASN1_read_bio', 'ASN1 lib')]

但是解析一个好的提取证书(使用我上面发布的第一个脚本)是有效的,正如你在这里看到的:

TL:DR -我想我只是需要一种从文件中导出证书的方法。此外,如果你觉得我的解决方案太复杂,如果你知道我如何从证书的主题字段中获得“雷德蒙”文本,我非常愿意接受其他想法:)

erhoui1w

erhoui1w1#

我在寻找类似的解决方案时遇到了这个问题。这就是我的工作。部分代码借用自disitool.py

import pefile
from OpenSSL import crypto
from OpenSSL.crypto import _lib, _ffi, X509

def get_certificates(self):
    certs = _ffi.NULL
    if self.type_is_signed():
        certs = self._pkcs7.d.sign.cert
    elif self.type_is_signedAndEnveloped():
        certs = self._pkcs7.d.signed_and_enveloped.cert

    pycerts = []
    for i in range(_lib.sk_X509_num(certs)):
        pycert = X509.__new__(X509)
        pycert._x509 = _lib.sk_X509_value(certs, i)
        pycerts.append(pycert)

    if not pycerts:
        return None
    return tuple(pycerts)

SignedFile = "/tmp/firefox.exe"

pe = pefile.PE(SignedFile)

address = pe.OPTIONAL_HEADER.DATA_DIRECTORY[
    pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]
].VirtualAddress
size = pe.OPTIONAL_HEADER.DATA_DIRECTORY[
    pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]
].Size

if address == 0:
    print("Error: source file not signed")
else:
    signature = pe.write()[address + 8 :]

    pkcs = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, bytes(signature))
    certs = get_certificates(pkcs)

    for cert in certs:
        c = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
        a = crypto.load_certificate(crypto.FILETYPE_PEM, c)
        # get data from parsed cert
        print(a.get_subject())
jv2fixgn

jv2fixgn2#

您可以使用cryptography包以更简洁的方式完成它:

import pefile
from cryptography.hazmat.primitives.serialization import pkcs7

signedFile = "/tmp/firefox.exe"
pe = pefile.PE(signedFile)

address = pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]].VirtualAddress
size = pe.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]].Size

signature = pe.write()[address + 8 :]
certs = pkcs7.load_der_pkcs7_certificates(bytes(signature))

for cert in certs:
    print(a.subject.rfc4514_string())

相关问题