【问题标题】:extract signed data from pkcs7 in python从python中的pkcs7中提取签名数据
【发布时间】:2018-09-15 11:31:22
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: python openssl x509 pem pkcs#7


    【解决方案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 中阅读所有相关信息。函数crypto.load_pkcs7_data()就派上用场了。

    话虽如此,下面的代码 sn-p 可能会为你做这件事——尽管从你的描述中我不清楚签名者的证书是否包含在 .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

    【讨论】:

    • 加载PKCS#7文件的正确答案在stackoverflow.com/a/45111623/1548275
    • @JariTurkia 在那个答案中,我看不到从 PKCS7 文件中提取实际签名数据的位置并验证了签名,这就是这里的问题。有趣的链接到 pyopenssl 拉取请求虽然,它似乎填补了获取数据的空白。
    • 实际上,在那个答案中有一个建议的OpenSSL.crypto.load_pkcs7_data(type, buffer) 可以加载数据。鉴于OpenSSL.crypto.PKCS7 几乎没有实现任何有用的功能,显而易见的下一步是提取 X.509 证书。我花了一段时间试图让PKCS7_verify() 工作,但失败了。正如另一个答案中所建议的那样,获取 CData 指针并在那里读取 X.509 证书字节确实有效。
    • 我在这里的回答确实展示了如何利用PKCS7_verify(),这对你不起作用吗?
    • 执行_lib.PKCS7_verify() 总是返回 0。错误原因是“无数据”。我推测,PKCS7_verify() 不考虑不同类型的 PKCS#7 数据:签名、封装或签名&封装。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 2012-11-03
    • 1970-01-01
    • 2017-09-27
    • 2013-07-13
    • 2011-08-06
    • 1970-01-01
    相关资源
    最近更新 更多