如果证书本身未安装在工作站上但仅用于该特定文件,则可能以某种方式'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模块从可执行文件本身切割'签名'bytearray,这使得提取的.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 - 我想我只需要一种从文件中导出证书的方法。此外,如果您发现我的解决方案过于复杂,如果您知道如何从证书的主题字段中获取“Redmond”文本,我非常对其他想法开放:)< / p>
答案 0 :(得分:1)
我在寻找类似解决方案时碰到了这个问题。这对我有用。部分代码是从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())