从 python 中的 pkcs7 提取签名数据
extract signed data from pkcs7 in python
我有一个 USB 加密令牌,能够签署数据并将其打包到 pkcs 文件中。然后我可以使用 openssl 从该文件中提取证书和数据,如下所示:
openssl cms -verify -in signature.p7s -inform DER -noverify -outform DER -signer cert.pem -out textdata
所以我的问题是如何使用 python (pyopenssl) 做同样的事情?
我已经尝试按照描述的方式去做 here,但是有不同的情况 - 我附加了签名但没有单独的签名和证书文件 - 我有 ASN.1 编码文件,其中包含作为数据和签名的证书
要实现您的目标,需要克服几个障碍。
首先,pyopenssl
绑定本身在其 crypto
模块(您需要的功能所在的模块)方面受到限制。事实上,the pyopenssl crypto
documentation 指出:
提到的 pyca/cryptography
模块通过 pyopenssl crypto
模块的两个内部属性公开,名称为 _lib
和 _ffi
,需要使用它们来获得所需的功能。
那么 CMS_verify()
函数将是您合乎逻辑的选择,它也不包含在 pyca/cryptography
绑定中。但是,为了您的目的,使用 PKCS7_verify()
可能就足够了——您可以在 StackExchange 问题中阅读所有相关内容 OpenSSL PKCS#7 vs. S/MIME. The function 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))
如果您决定使用这种方法,这里是 a caveat about using this OpenSSL bindings module directly:
我有一个 USB 加密令牌,能够签署数据并将其打包到 pkcs 文件中。然后我可以使用 openssl 从该文件中提取证书和数据,如下所示:
openssl cms -verify -in signature.p7s -inform DER -noverify -outform DER -signer cert.pem -out textdata
所以我的问题是如何使用 python (pyopenssl) 做同样的事情?
我已经尝试按照描述的方式去做 here,但是有不同的情况 - 我附加了签名但没有单独的签名和证书文件 - 我有 ASN.1 编码文件,其中包含作为数据和签名的证书
要实现您的目标,需要克服几个障碍。
首先,pyopenssl
绑定本身在其 crypto
模块(您需要的功能所在的模块)方面受到限制。事实上,the pyopenssl crypto
documentation 指出:
pyca/cryptography
模块通过 pyopenssl crypto
模块的两个内部属性公开,名称为 _lib
和 _ffi
,需要使用它们来获得所需的功能。
那么 CMS_verify()
函数将是您合乎逻辑的选择,它也不包含在 pyca/cryptography
绑定中。但是,为了您的目的,使用 PKCS7_verify()
可能就足够了——您可以在 StackExchange 问题中阅读所有相关内容 OpenSSL PKCS#7 vs. S/MIME. The function 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))
如果您决定使用这种方法,这里是 a caveat about using this OpenSSL bindings module directly: