在python中从pkcs7提取签名数据 [英] extract signed data from pkcs7 in python

查看:634
本文介绍了在python中从pkcs7提取签名数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

openssl cms -verify -in signature.p7s -inform DER -noverify -outform DER -signer cert.pem -out textdata

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

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

解决方案

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

首先,pyopenssl绑定本身在其所需功能所在的crypto模块上受到限制.实际上, pyopenssl crypto文档指出: 提到的 pyca/cryptography 模块是通过pyopenssl crypto模块的两个内部属性公开的,名称分别为_lib_ffi,需要使用它们来获得所需的功能.

然后CMS_verify()函数(这是您对此的逻辑选择)也不包含在pyca/cryptography绑定中.但是,出于您的目的,使用PKCS7_verify()可能足够好-您可以在StackExchange问​​题 OpenSSL中阅读有关此内容的全部信息. PKCS#7与S/MIME .函数 crypto.load_pkcs7_data() 派上用场. /p>

话虽如此,以下代码段可能会为您做到这一点-尽管从您的描述来看,我不清楚[c11>文件中是否包含签名者的证书(在这种情况下,您没有像您一样将-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)) 

如果您决定使用此方法,请有关使用此方法的警告直接使用OpenSSL绑定模块:

i have a usb cryptotoken and able to sign data and pack it in pkcs file. then i can extract certificate and data from that file using openssl as follows:

openssl cms -verify -in signature.p7s -inform DER -noverify -outform DER -signer cert.pem -out textdata

so my question is how to do the same using python (pyopenssl)?

i've tried to do as described here, but there is different case - i have attached signature and do not have separate signature and certificate file - i have ASN.1 encoded file, which contains as certificates as data and signature

解决方案

There are several hurdles to overcome to achieve what you are looking for.

First, the pyopenssl binding itself is limited when it comes to its crypto module, where you desired functionality resides. In fact, the pyopenssl crypto documentation states: The pyca/cryptography module mentioned is exposed via two internal attributes of the pyopenssl crypto module, with the names _lib and _ffi, which need to be used to get to the required functionality.

Then the CMS_verify() function that would be your logical choice for this is not included in the pyca/cryptography bindings either. However, for your purpose it is probably good enough to use PKCS7_verify() -- you can read all about that in a StackExchange question OpenSSL PKCS#7 vs. S/MIME. The function crypto.load_pkcs7_data() comes in handy.

All that said, the following code snippet might do it for you -- although from your description it is not clear to me whether the certificate of the signer is included in the .p7s file (in that case you do not have to give -signer as an argument to openssl cms -verify like you did). It worked for me, so give it a try:

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)) 

In case you decide to use this approach, here is a caveat about using this OpenSSL bindings module directly:

这篇关于在python中从pkcs7提取签名数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆