извлечение подписанных данных из pkcs7 в python


У меня есть USB cryptotoken и возможность подписывать данные и упаковывать их в файл pkcs. затем я могу извлечь сертификат и данные из этого файла с помощью openssl следующим образом:

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

Итак, мой вопрос заключается в том, как сделать то же самое с помощью python (pyopenssl)?

Я попытался сделать так, как описано здесь, но есть другой случай - у меня есть прикрепленная подпись и нет отдельного файла подписи и сертификата - у меня есть ASN.1 закодированный файл, содержащий в качестве сертификатов данные и подпись

1 3

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() пригодится.

Все сказанное, следующий фрагмент кода может сделать это для вас - хотя из вашего описания мне не ясно, является ли сертификат подписывающего лица включен в файл .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)) 

В случае, если вы решите использовать этот подход, вот предостережение об использовании этого модуля Привязок OpenSSL напрямую : Введите описание изображения здесь