Несвязанная подпись PKCS#7 SHA1+RSA без M2Crypto
Я пытаюсь создать неотделенную подпись на python3. В настоящее время у меня есть код, который делает это на python2 с m2crypto, но m2crypto не доступен для python3.
Я пробовал RSA, Pycrypto и OpenSSL, но не видел, как найти.
Вот эквивалентная команда OpenSSL:
openssl smime -sign -signer $CRTFILE -inkey $KEYFILE -outformDER -nodetach
Это nodetach
вариант, который я не могу имитировать с помощью rsa, pyopenssl или pycrypto.
Кто-нибудь делает это на python3? Я бы хотел как можно больше избегать использования Popen+openssl.
2 ответа
Я на самом деле в конечном итоге решить это с OpenSSL.crypto
Хотя и с некоторыми внутренними методами:
from OpenSSL import crypto
PKCS7_NOSIGS = 0x4 # defined in pkcs7.h
def create_embeded_pkcs7_signature(data, cert, key):
"""
Creates an embeded ("nodetached") pkcs7 signature.
This is equivalent to the output of::
openssl smime -sign -signer cert -inkey key -outform DER -nodetach < data
:type data: bytes
:type cert: str
:type key: str
""" # noqa: E501
assert isinstance(data, bytes)
assert isinstance(cert, str)
try:
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
signcert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
except crypto.Error as e:
raise ValueError('Certificates files are invalid') from e
bio_in = crypto._new_mem_buf(data)
pkcs7 = crypto._lib.PKCS7_sign(
signcert._x509, pkey._pkey, crypto._ffi.NULL, bio_in, PKCS7_NOSIGS
)
bio_out = crypto._new_mem_buf()
crypto._lib.i2d_PKCS7_bio(bio_out, pkcs7)
signed_data = crypto._bio_to_string(bio_out)
return signed_data
Это возможно с помощью
cryptography
пакет в python 3.
Это команда OpenSSL, которую я пытался воспроизвести.
openssl smime -sign
-signer cert.crt
-inkey cert.key
-certfile intermediate.pem
-nodetach
-outform der
-in mdm.mobileconfig
-out mdm-signed.mobileconfig
import cyptography
with open('cert.crt', 'rb') as fp:
cert = cryptography.x509.load_pem_x509_certificate(fp.read())
with open('intermediate.pem', 'rb') as fp:
ca = cryptography.x509.load_pem_x509_certificate(fp.read())
with open('cert.key', 'rb') as fp:
key = cryptography.hazmat.primitives.serialization.load_pem_private_key(
fp.read(), None,
)
with open('data.bin', 'rb') as fp:
data = fp.read()
signed_data = cryptography.hazmat.primitives.serialization.pkcs7.PKCS7SignatureBuilder(
data=data,
signers=[
(cert, key, cryptography.hazmat.primitives.hashes.SHA512()),
],
additional_certs=[ca],
).sign(
cryptography.hazmat.primitives.serialization.Encoding.DER, options=[],
)
-nodetach
достигается по умолчанию с помощью
options=[]
поскольку
openssl
по умолчанию добавляет отдельный флаг.