Создание и сохранение объектов CMS / PKCS # 7 в Python - PullRequest
0 голосов
/ 01 ноября 2019

Мне нужно иметь возможность генерировать, сохранять и читать данные CMS / PKCS # 7 в Python. Кажется, что это можно сделать с помощью библиотеки asn1crypto, но мне трудно найти функции, которые позволили бы мне сохранить данные на диск (в формате PEM / DER). В asn1crypto / tests / test_cms.py есть testbench, но он показывает только, как прочитать данные CMS / PKCS # 7 из файлов и сохранить их в соответствующих объектах asn1crypto.cms. Я не смог найти руководство или даже список функций (методов) asn1crypto.cms.

На данный момент я могу сгенерировать все необходимые компоненты, такие как подпись, зашифрованные данные, симметричный ключ и т. Д., Поэтому мне нужно найти способ объединить их в CMS / PKCS# 7 совместимых форматов файлов. По сути, я ищу эквивалентный поток Python для возможностей оболочки openssl cms и openssl engine. Простой пример Python, показывающий, как создать и сохранить объект CMS (например, SignedData, EnvelopedData и т. Д.), Прошел бы долгий путь.

1 Ответ

0 голосов
/ 06 ноября 2019

Итак, после многих дней игры с пакетами asn1crypto и pkcs11, я смог создать подписанный файл данных. Для подписи я использовал слот для подписи PIV в своем Yubikey 5. Ниже приведен отрывок из моего скрипта, показывающий его суть (простите большой код):

from asn1crypto import cms, util, algos, x509, core, pem
import pkcs11
from pkcs11 import Attribute, ObjectClass, KeyType

# Creating a SignedData object from cms
sd = cms.SignedData()

# Populating some of its fields
sd['version']='v1'
sd['encap_content_info']=util.OrderedDict([
        ('content_type', 'data'),
        ('content', b'Just a test')])
sd['digest_algorithms']=[ util.OrderedDict([
        ('algorithm', 'sha256'),
        ('parameters', None) ])

# Initiating my Yubikey smart card
lib = pkcs11.lib('.../onepin-opensc-pkcs11.so')
token = lib.get_token(token_label='PIV Card Holder pin (PIV_II)')
session = token.open(user_pin='123456')

# Getting the private key and certificate objects using pkcs11
privateKey = next(session.get_objects({
        Attribute.CLASS: ObjectClass.PRIVATE_KEY,
        Attribute.LABEL: "SIGN key" })
certObj = next(session.get_objects({
        Attribute.CLASS: ObjectClass.CERTIFICATE,
        Attribute.LABEL: 'Certificate for Digital Signature' })

# Getting the raw value (DER) of certificate and storing it in x509
cert = x509.Certificate.load(certObj[Attribute.VALUE])

# Adding this certificate to SignedData object
sd['certificates'] = cert

# Setting signer info section
signer_info = cms.SignerInfo()
signer_info['version']=cms_version
signer_info['digest_algorithm']=util.OrderedDict([
                ('algorithm', 'sha256'),
                ('parameters', None) ])
signer_info['signature_algorithm']=util.OrderedDict([
                ('algorithm', 'sha256_rsa'),
                ('parameters', None) ])

# Creating a signature using a private key object from pkcs11
signer_info['signature'] = privateKey.sign(
        data, 
        mechanism=pkcs11.mechanisms.Mechanism.SHA256_RSA_PKCS )

# Finding subject_key_identifier from certificate (asn1crypto.x509 object)
key_id = cert.key_identifier_value.native
signer_info['sid'] = cms.SignerIdentifier({
        'subject_key_identifier': key_id })

# Adding SignerInfo object to SignedData object
sd['signer_infos'] = [ signer_info ]

# Writing everything into ASN.1 object
asn1obj['content_type'] = 'signed_data'
asn1obj['content'] = sd

# This asn1obj can be dumped to a disk using dump() method (DER format)
fout = open('signed_data.der','wb+')
fout.write(asn1obj.dump())

Затем я проверил подпись, используя openssl cms -verify -in signed_data.der -inform DER -CAfile rootCertificate.pemи это сработало!

...