在python中从pkcs7中提取签名数据

bor*_*une 6 python openssl pem x509 pkcs#7

我有一个 USB 加密令牌,能够对数据进行签名并将其打包到 pkcs 文件中。然后我可以使用 openssl 从该文件中提取证书和数据,如下所示:

openssl cms -verify -in signature.p7s -inform DER -noverify -outform DER -signer cert.pem -out textdata
Run Code Online (Sandbox Code Playgroud)

所以我的问题是如何使用 python (pyopenssl) 做同样的事情?

我已尝试按照此处所述进行操作,但存在不同的情况-我附加了签名但没有单独的签名和证书文件-我有 ASN.1 编码文件,其中包含作为数据和签名的证书

Rei*_*eek 5

要实现您的目标,需要克服几个障碍。

首先,pyopenssl绑定本身在涉及其crypto模块时受到限制,您需要的功能驻留在该模块中。事实上,pyopenssl crypto文件规定: 在此处输入图片说明pyca/cryptography提到 的模块通过模块的两个内部属性公开pyopenssl crypto,名称_lib_ffi,需要使用它们来获得所需的功能。

那么CMS_verify()作为您的逻辑选择的函数也不包含在pyca/cryptography绑定中。但是,出于您的目的,使用它可能已经足够了PKCS7_verify()- 您可以在 StackExchange 问题OpenSSL PKCS#7 vs. S/MIME 中阅读所有相关内容。该功能crypto.load_pkcs7_data()派上用场。

综上所述,以下代码片段可能会为您完成——尽管根据您的描述,我不清楚签名者的证书是否包含在.p7s文件中(在这种情况下,您不必-signer作为参数提供给openssl cms -verify像你一样)。它对我有用,所以试一试:

from OpenSSL import crypto
from OpenSSL._util import (
    ffi as _ffi,
    lib as _lib,
)

# Or, alternatively:
# from cryptography.hazmat.bindings.openssl.binding import Binding
# _lib = Binding.lib
# _ffi = Binding.ffi

with open('message_der.p7s', 'rb') as f:
    p7data = f.read()
p7 = crypto.load_pkcs7_data(crypto.FILETYPE_ASN1, p7data)

bio_out =crypto._new_mem_buf()
res = _lib.PKCS7_verify(p7._pkcs7, _ffi.NULL, _ffi.NULL, _ffi.NULL, bio_out, _lib.PKCS7_NOVERIFY)
if res == 1:
    databytes = crypto._bio_to_string(bio_out)
    print(databytes)
else:
    errno = _lib.ERR_get_error()
    errstrlib = _ffi.string(_lib.ERR_lib_error_string(errno))
    errstrfunc = _ffi.string(_lib.ERR_func_error_string(errno))
    errstrreason = _ffi.string(_lib.ERR_reason_error_string(errno)) 
Run Code Online (Sandbox Code Playgroud)

如果您决定使用这种方法,这里有一个关于直接使用这个 OpenSSL 绑定模块的警告在此处输入图片说明