Раскрываем Секреты: Создание Отсоединенной Подписи CAdES-BES с ГОСТ Р в Python – Ваш Полный Гид!
Пошаговое руководство по генерации безопасных электронных подписей российского стандарта для ваших файлов с использованием Python.
Основные моменты
- Отсоединенная подпись CAdES-BES: Позволяет подписывать данные, сохраняя подпись отдельно от самого файла, что идеально для верификации без необходимости встраивания исходных данных в файл подписи.
- Алгоритмы ГОСТ Р: Использование российских криптографических стандартов ГОСТ Р 34.10-2012 (для создания электронной подписи) и ГОСТ Р 34.11-2012 (для хеширования) обеспечивает соответствие нормативным требованиям и высокий уровень безопасности.
- Реализация на Python: Представлен практический пример кода с использованием библиотек
gostcryptoиasn1cryptoдля формирования структуры подписи CAdES-BES в соответствии со стандартами.
Введение: Зачем нужна отсоединенная подпись CAdES-BES ГОСТ Р?
В современном цифровом мире обеспечение подлинности и целостности электронных документов имеет первостепенное значение. Электронные подписи (ЭП) служат этой цели, предоставляя криптографические гарантии. CAdES (CMS Advanced Electronic Signatures) – это набор стандартов для расширенных электронных подписей, построенных на основе CMS (Cryptographic Message Syntax). CAdES-BES (Basic Electronic Signature) является базовым форматом, который подтверждает, что подпись была создана конкретным подписантом.
Отсоединенная подпись (detached signature) означает, что сама подпись хранится отдельно от подписываемых данных. Это особенно удобно, когда исходный файл велик или когда его нежелательно изменять. Использование алгоритмов ГОСТ Р (Государственный Стандарт Российской Федерации) обеспечивает соответствие российскому законодательству и криптографическим требованиям.
Это руководство покажет, как создать отсоединенную подпись CAdES-BES с использованием алгоритмов ГОСТ Р в Python, что позволит вам интегрировать надежные механизмы ЭП в ваши приложения.
Иллюстрация процесса создания и упаковки цифровой подписи.
Ключевые компоненты и стандарты
Для создания подписи CAdES-BES ГОСТ Р необходимо понимать основные стандарты и компоненты, участвующие в процессе.
Алгоритмы ГОСТ Р: Основа российской криптографии
Российские стандарты ГОСТ Р играют ключевую роль в обеспечении криптографической защиты информации.
ГОСТ Р 34.10-2012: Стандарт электронной подписи
Этот стандарт определяет алгоритмы формирования и проверки электронной подписи на основе эллиптических кривых. Он пришел на смену ГОСТ Р 34.10-2001 и предлагает повышенный уровень безопасности. Для подписей CAdES-BES мы будем использовать именно этот стандарт.
ГОСТ Р 34.11-2012: Стандарт хеширования
Данный стандарт определяет алгоритм хеш-функции ("Стрибог"), используемый для вычисления хеш-значения (дайджеста) подписываемых данных. Дайджест затем подписывается с использованием ГОСТ Р 34.10-2012. Стандарт предусматривает два варианта длины хеш-значения: 256 бит и 512 бит.
CAdES-BES: Базовый формат улучшенной электронной подписи
CAdES-BES (CMS Advanced Electronic Signatures - Basic Electronic Signature) – это базовый уровень формата CAdES, определенный в ETSI TS 101 733. Он обеспечивает подтверждение того, что подпись была создана, и связывает ее с подписанными данными через хеш.
Структура SignedData
Это основная структура CMS, содержащая саму подпись и связанную информацию. В случае отсоединенной подписи, поле encapContentInfo (инкапсулированное содержимое) не содержит исходные данные, а только указывает их тип.
SignedAttributes: Гарантия целостности контекста
Подписываемые атрибуты (SignedAttributes) являются критически важной частью CAdES. Они подписываются вместе с хешем документа и включают как минимум:
content-type: Идентификатор типа подписываемых данных.message-digest: Хеш-значение подписываемых данных.signing-time: Время создания подписи (необязательный, но рекомендуемый атрибут для BES).
Подписание этих атрибутов защищает от некоторых видов атак, например, от подмены самого хеша.
Отсоединенная подпись: Гибкость и эффективность
При использовании отсоединенной подписи, файл подписи (часто с расширением .sig или .p7s) создается отдельно от исходного документа. Это позволяет:
- Хранить и передавать документ и подпись независимо.
- Подписывать очень большие файлы без необходимости включать их содержимое в структуру подписи.
- Применять несколько подписей к одному документу без изменения самого документа.
Сертификация ГОСТ Р как символ соответствия российским стандартам криптографии.
Практическая реализация: Подписываем файл в Python
Для создания отсоединенной подписи CAdES-BES с ГОСТ Р в Python мы воспользуемся комбинацией библиотек: gostcrypto для криптографических операций ГОСТ и asn1crypto для формирования ASN.1 структур, необходимых для CAdES/CMS.
Необходимые инструменты: Библиотеки Python
Убедитесь, что у вас установлены следующие библиотеки:
pip install gostcrypto asn1crypto
- gostcrypto: Предоставляет реализации российских криптографических алгоритмов, включая ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012.
- asn1crypto: Мощная библиотека для работы с ASN.1 структурами, которая поможет нам построить формат CAdES-BES.
Пошаговый процесс создания подписи
- Импорт библиотек и подготовка данных: Подключаем необходимые модули.
- Загрузка исходного файла, закрытого ключа ГОСТ и сертификата: Для создания подписи необходим закрытый ключ стандарта ГОСТ Р 34.10-2012 и соответствующий ему сертификат открытого ключа.
- Вычисление хеш-суммы файла: Используем ГОСТ Р 34.11-2012 (например, 256-битную версию) для получения дайджеста подписываемого файла.
- Формирование подписываемых атрибутов (
SignedAttributes): Создаем структуру, включающую тип контента, дайджест сообщения и время подписи. - Хеширование
SignedAttributes: Получаем хеш-сумму сериализованных подписываемых атрибутов, также используя ГОСТ Р 34.11-2012. - Создание цифровой подписи: Подписываем хеш атрибутов закрытым ключом ГОСТ Р 34.10-2012.
- Формирование объекта
SignerInfo: Этот объект содержит информацию о подписанте, использованных алгоритмах, подписываемых атрибутах и самой подписи. - Сборка структуры
SignedData: Основная структура CMS, содержащаяSignerInfoи другую метаинформацию. Для отсоединенной подписи исходные данные не включаются. - Обертывание в
ContentInfoи сохранение подписи: Финальная структура, готовая для сохранения в файл (обычно с расширением .p7s или .sig).
Фрагмент кода Python
from datetime import datetime, timezone
import gostcrypto.gostsignature as gostsig
import gostcrypto.gosthash as gosthash
from gostcrypto import encoding # Может понадобиться для специфических кодировок ключей
from asn1crypto import cms, core, x509, algos, pem
# --- Параметры ---
FILE_TO_SIGN_PATH = 'document.txt' # Путь к подписываемому файлу
PRIVATE_KEY_PATH = 'private_key.pem' # Путь к файлу закрытого ключа ГОСТ (PEM формат)
CERTIFICATE_PATH = 'certificate.cer' # Путь к файлу сертификата ГОСТ (DER или PEM формат)
SIGNATURE_OUTPUT_PATH = 'document.txt.p7s' # Путь для сохранения файла отсоединенной подписи
# --- 1. Загрузка данных и ключей/сертификатов ---
try:
# Чтение файла для подписи
with open(FILE_TO_SIGN_PATH, 'rb') as f:
data_to_sign = f.read()
# Загрузка закрытого ключа ГОСТ Р 34.10-2012
# gostcrypto ожидает ключ в бинарном формате (DER) или специальном PEM с GOST параметрами
# Если ключ в PEM, его нужно предварительно обработать или убедиться, что gostcrypto его понимает
# Для примера, предположим, что ключ уже в подходящем формате или gostcrypto.load_private_key это обработает.
with open(PRIVATE_KEY_PATH, 'rb') as f:
private_key_pem_data = f.read()
# Пытаемся определить, PEM ли это, и извлечь DER-содержимое, если необходимо для gostcrypto
# gostcrypto.load_private_key может ожидать DER-байт или специфичный PEM.
# Этот шаг может потребовать адаптации в зависимости от формата вашего ключа.
# В данном примере мы предполагаем, что load_private_key справится с PEM или вы предоставите DER.
# Для простоты, если это PEM, используем encoding.pem_armor_decode, если он есть
try:
# Пробуем декодировать PEM, если это он
_, _, private_key_der_data = pem.unarmor(private_key_pem_data)
except ValueError:
# Если не PEM, считаем, что это DER
private_key_der_data = private_key_pem_data
private_key = gostsig.load_private_key(private_key_der_data) # Пароль, если ключ зашифрован
# Загрузка сертификата подписанта (для SignerIdentifier и включения в подпись)
with open(CERTIFICATE_PATH, 'rb') as f:
cert_data = f.read()
# asn1crypto.x509.Certificate.load может загружать PEM или DER автоматически
certificate = x509.Certificate.load(cert_data)
except FileNotFoundError as e:
print(f"Ошибка: Файл не найден - {e.filename}")
exit()
except Exception as e:
print(f"Ошибка при загрузке ключей/сертификата: {e}")
exit()
# --- 2. Вычисление хеша файла (ГОСТ Р 34.11-2012, 256 бит) ---
data_digest = gosthash.new('streebog256', data_to_sign).digest()
# --- 3. Формирование SignedAttributes ---
# Обязательные атрибуты для CAdES-BES: content-type, message-digest. signing-time рекомендуется.
signed_attrs = cms.CMSAttributes([
cms.CMSAttribute({
'type': cms.CMSAttributeType('content_type'),
'values': [cms.ContentType('data')] # OID for id-data: 1.2.840.113549.1.7.1
}),
cms.CMSAttribute({
'type': cms.CMSAttributeType('message_digest'),
'values': [data_digest]
}),
cms.CMSAttribute({
'type': cms.CMSAttributeType('signing_time'),
# Время должно быть в UTC и формате UTCTime или GeneralizedTime
'values': [core.UTCTime(datetime.now(timezone.utc))]
}),
# Можно добавить другие атрибуты, например, signing_certificate_v2 (ETSI TS 101 733 / RFC 5035)
# Для CAdES-BES часто ожидается ETSI-defined SigningCertificateV2 attribute
# cms.CMSAttribute({
# 'type': cms.CMSAttributeType('1.2.840.113549.1.9.16.2.47'), # id-aa-signingCertificateV2
# 'values': [...] # Требует структуры ESSCertIDv2
# })
])
# Сериализация SignedAttributes (в DER формате, SET OF) для последующего хеширования
# Важно: атрибуты должны быть закодированы как SET OF для хеширования
signed_attrs_der = signed_attrs.dump()
# --- 4. Хеширование SignedAttributes (ГОСТ Р 34.11-2012, 256 бит) ---
signed_attrs_hash = gosthash.new('streebog256', signed_attrs_der).digest()
# --- 5. Создание подписи хеша атрибутов (ГОСТ Р 34.10-2012) ---
# gostsig.sign подписывает переданные байты (в нашем случае хеш атрибутов)
raw_signature = gostsig.sign(private_key, signed_attrs_hash)
# --- 6. Формирование SignerInfo ---
signer_info = cms.SignerInfo({
'version': 'v1', # Версия в зависимости от типа sid (issuerAndSerialNumber -> v1, subjectKeyIdentifier -> v3)
'sid': cms.SignerIdentifier({
'issuer_and_serial_number': cms.IssuerAndSerialNumber({
'issuer': certificate.issuer,
'serial_number': certificate.serial_number
})
}),
'digest_algorithm': algos.DigestAlgorithm({'algorithm': '1.2.643.7.1.1.2.2'}), # OID ГОСТ Р 34.11-2012 (256) - Streebog256
'signed_attrs': signed_attrs, # Включаем сами атрибуты
'signature_algorithm': algos.SignedDigestAlgorithm({'algorithm': '1.2.643.7.1.1.1.1'}), # OID ГОСТ Р 34.10-2012 (256)
'signature': raw_signature,
# 'unsigned_attrs': опционально
})
# --- 7. Сборка SignedData ---
# Для отсоединенной подписи, encap_content_info.content не указывается
signed_data = cms.SignedData({
'version': 'v1', # или v3, v4, v5 в зависимости от используемых фич
'digest_algorithms': [algos.DigestAlgorithm({'algorithm': '1.2.643.7.1.1.2.2'})], # Алгоритмы хеширования, используемые подписантами
'encap_content_info': cms.EncapsulatedContentInfo({
'content_type': cms.ContentType('data'), # Тип исходных данных
# 'content': data_to_sign # НЕ включаем для отсоединенной подписи
}),
'certificates': [certificate], # Включаем сертификат подписанта
# 'crls': [], # Можно включить CRL
'signer_infos': [signer_info]
})
# --- 8. Обертывание в ContentInfo и сохранение ---
content_info = cms.ContentInfo({
'content_type': cms.ContentType('signed_data'), # OID for id-signedData: 1.2.840.113549.1.7.2
'content': signed_data
})
# Сохранение отсоединенной подписи в файл
with open(SIGNATURE_OUTPUT_PATH, 'wb') as f:
f.write(content_info.dump()) # Сериализация в DER формат
print(f"Отсоединенная подпись CAdES-BES ГОСТ Р успешно создана и сохранена в: {SIGNATURE_OUTPUT_PATH}")
Разбор кода: Что происходит "под капотом"?
- Загрузка данных: Читается файл, который необходимо подписать, а также закрытый ключ и сертификат подписанта. Формат ключа и сертификата должен быть совместим с используемыми библиотеками.
gostcryptoобычно работает с ключами в формате DER или специфическом PEM для ГОСТ.asn1cryptoможет парсить сертификаты в DER или PEM формате. - Хеширование файла: С помощью
gosthash.new('streebog256', data_to_sign).digest()вычисляется дайджест (хеш) содержимого файла по алгоритму ГОСТ Р 34.11-2012 (256-битная версия "Стрибог"). - Формирование
SignedAttributes: Создается ASN.1 структураcms.CMSAttributes, содержащая обязательные для CAdES-BES атрибуты: тип контента (content_type), дайджест сообщения (message_digest), и время подписи (signing_time). Эти атрибуты сериализуются в DER-формат (signed_attrs.dump()), так как именно эта бинарная строка будет хешироваться и подписываться. - Хеширование
SignedAttributes: Сериализованные атрибуты хешируются тем же алгоритмом ГОСТ Р 34.11-2012. - Создание подписи: Функция
gostsig.sign(private_key, signed_attrs_hash)использует загруженный закрытый ключ ГОСТ Р 34.10-2012 для подписи хеша атрибутов. - Формирование
SignerInfo: Это ключевая структура, описывающая одного подписанта. Она включает:sid(Signer Identifier): Идентификатор подписанта, обычно через издателя и серийный номер сертификата (IssuerAndSerialNumber).digest_algorithm: OID алгоритма хеширования, использованного дляSignedAttributes(в нашем случае, ГОСТ Р 34.11-2012).signed_attrs: Сами подписываемые атрибуты.signature_algorithm: OID алгоритма подписи (ГОСТ Р 34.10-2012).signature: Непосредственно цифровая подпись (байты).
- Сборка
SignedData: Эта структура "обертывает" всю информацию о подписи. Для отсоединенной подписи полеencap_content_infoне содержит самих данных (content), а лишь указывает их тип (content_type: 'data'). ВSignedDataтакже включаются использованные алгоритмы хеширования, сертификат(ы) подписантов и массив структурSignerInfo. - Обертывание в
ContentInfoи сохранение:SignedDataупаковывается в финальную структуруContentInfo, которая затем сериализуется в DER-формат (content_info.dump()) и сохраняется в файл. Этот файл и является отсоединенной электронной подписью.
Важно: Представленный код является примером. Реальная работа с криптографическими ключами и сертификатами требует строгого соблюдения мер безопасности, включая безопасное хранение ключей и управление жизненным циклом сертификатов. Также может потребоваться более сложная обработка ошибок и адаптация под конкретные форматы ключей/сертификатов.
Визуализация процесса: Схема создания подписи
Чтобы лучше понять последовательность шагов при создании отсоединенной подписи CAdES-BES с использованием алгоритмов ГОСТ Р, рассмотрим следующую ментальную карту. Она иллюстрирует ключевые этапы, начиная от подготовки данных и заканчивая формированием файла подписи.
Эта схема наглядно демонстрирует все этапы, которые проходит система для генерации корректной отсоединенной подписи CAdES-BES ГОСТ Р.
Сравнение подходов: Обзор библиотек для Python
При реализации поддержки ГОСТ и CAdES в Python разработчики могут столкнуться с выбором между различными библиотеками и подходами. Диаграмма ниже представляет сравнительный анализ нескольких условных подходов по ключевым критериям. Оценки носят субъективный характер и призваны дать общее представление.
Как видно из диаграммы, подход с использованием gostcrypto и asn1crypto предлагает хороший баланс между соответствием стандартам ГОСТ, возможностью реализации CAdES и доступностью (бесплатные open-source библиотеки), хотя и требует более глубокого понимания структур ASN.1. Коммерческие решения, такие как Chilkat (если они поддерживают ГОСТ в вашей конфигурации), могут предложить большую простоту использования и полноту CAdES "из коробки", но ценой лицензионных отчислений.
Ключевые идентификаторы объектов (OID) в подписях ГОСТ CAdES-BES
Идентификаторы объектов (Object Identifiers, OID) играют фундаментальную роль в структурах ASN.1, таких как CMS/CAdES. Они однозначно определяют алгоритмы, типы данных, атрибуты и другие элементы. Ниже приведена таблица с некоторыми ключевыми OID, релевантными для создания подписей ГОСТ Р CAdES-BES.
| OID | Описание | Мнемоника / Ссылка на стандарт |
|---|---|---|
1.2.643.7.1.1.2.2 |
Алгоритм хеширования ГОСТ Р 34.11-2012 (256 бит, "Стрибог") | id-tc26-gost3411-12-256 |
1.2.643.7.1.1.1.1 |
Алгоритм цифровой подписи ГОСТ Р 34.10-2012 (с 256-битными параметрами) | id-tc26-gost3410-12-256 |
1.2.840.113549.1.7.1 |
Тип содержимого "data" (произвольные данные) | id-data (PKCS#7/CMS) |
1.2.840.113549.1.7.2 |
Тип содержимого "signedData" (подписанные данные CMS) | id-signedData (PKCS#7/CMS) |
1.2.840.113549.1.9.3 |
Атрибут "contentType" (тип содержимого) | contentType (PKCS#9 / CMS) |
1.2.840.113549.1.9.4 |
Атрибут "messageDigest" (дайджест сообщения) | messageDigest (PKCS#9 / CMS) |
1.2.840.113549.1.9.5 |
Атрибут "signingTime" (время подписи) | signingTime (PKCS#9 / CMS) |
1.2.840.113549.1.9.16.2.47 |
Атрибут "id-aa-signingCertificateV2" (рекомендован для CAdES) | ETSI TS 101 733 / RFC 5035 |
Знание этих OID помогает при отладке и анализе структур электронных подписей, а также при работе с низкоуровневыми криптографическими библиотеками.
Важные аспекты и рекомендации
При работе с электронными подписями, особенно в контексте государственных стандартов, важно учитывать ряд аспектов для обеспечения безопасности и корректности.
Управление ключами и сертификатами
Закрытые ключи должны храниться в строгой тайне и с использованием защищенных механизмов (например, аппаратные токены PKCS#11, защищенные хранилища ОС). Компрометация закрытого ключа ведет к возможности подделки подписей от имени владельца. Сертификаты открытых ключей должны быть выданы доверенными удостоверяющими центрами (УЦ) и своевременно обновляться.
Обработка ошибок и исключений
В коде, работающем с криптографией, крайне важна тщательная обработка ошибок. Некорректные ключи, сертификаты, данные или ошибки в криптографических операциях могут привести к невалидным подписям или уязвимостям. Всегда проверяйте возвращаемые значения функций и обрабатывайте возможные исключения.
Совместимость и версии библиотек
Убедитесь, что версии используемых библиотек (gostcrypto, asn1crypto и их зависимостей, таких как OpenSSL) совместимы между собой и поддерживают необходимые алгоритмы ГОСТ. Иногда для поддержки ГОСТ на уровне системы может потребоваться специальная сборка OpenSSL.
Проверка (валидация) созданной подписи
После создания подписи рекомендуется проводить ее проверку с использованием эталонных инструментов или сервисов валидации (например, сервисы УЦ, тестовые площадки государственных порталов, если они поддерживают CAdES-BES ГОСТ Р). Это поможет убедиться в корректности сформированной подписи и ее соответствии стандартам.
Обзор различных профилей цифровых подписей, включая CAdES, в контексте европейского регламента eIDAS. Подобные профили существуют и для российских стандартов.
Часто задаваемые вопросы (FAQ)
Что такое отсоединенная подпись и в чем ее преимущество?
Отсоединенная подпись (detached signature) — это электронная подпись, которая хранится отдельно от подписываемых данных, обычно в отдельном файле. Ее главное преимущество заключается в том, что исходный документ не изменяется и не включается в файл подписи. Это удобно для:
- Подписания больших файлов (не нужно копировать их в структуру подписи).
- Передачи и хранения документа и подписи по отдельности.
- Множественного подписания одного документа разными лицами без изменения оригинала.
- Проверки подлинности документа без необходимости извлекать его из контейнера подписи.
Какие версии ГОСТ Р используются для подписи CAdES-BES?
Для создания подписи CAdES-BES с использованием российских стандартов, как правило, применяются:
- ГОСТ Р 34.10-2012: Для генерации и проверки самой цифровой подписи (алгоритм на эллиптических кривых).
- ГОСТ Р 34.11-2012 ("Стрибог"): Для вычисления хеш-значения (дайджеста) подписываемых данных и подписываемых атрибутов.
Важно использовать актуальные версии стандартов и убедиться, что ваш криптопровайдер и библиотеки их поддерживают.
Обязательно ли использовать asn1crypto вместе с gostcrypto?
gostcrypto предоставляет низкоуровневые функции для выполнения криптографических операций ГОСТ (хеширование, подпись). Однако формат CAdES-BES (как и любой CMS-совместимый формат) требует формирования сложных структур данных в соответствии со стандартом ASN.1.
Библиотека asn1crypto как раз предназначена для работы с ASN.1: она позволяет удобно создавать, парсить и сериализовывать такие структуры. Таким образом, для формирования полноценной подписи CAdES-BES, а не просто "сырой" ГОСТ-подписи, использование asn1crypto (или аналогичной библиотеки для работы с ASN.1/CMS) в связке с gostcrypto является практически необходимым и рекомендуемым подходом.
Где взять закрытый ключ и сертификат ГОСТ?
Закрытый ключ и соответствующий ему сертификат открытого ключа стандарта ГОСТ Р выдаются аккредитованными Удостоверяющими Центрами (УЦ). Процесс получения обычно включает:
- Подачу заявления в УЦ.
- Предоставление необходимых документов для идентификации.
- Генерацию ключевой пары (закрытый ключ генерируется пользователем на защищенном носителе или средствами УЦ).
- Выпуск сертификата Удостоверяющим Центром.
Для тестовых целей или разработки можно использовать тестовые УЦ или сгенерировать самоподписанные сертификаты (однако такие сертификаты не будут доверенными в реальных системах).
Как проверить правильность созданной подписи?
Проверка (валидация) созданной подписи CAdES-BES ГОСТ Р включает несколько шагов:
- Проверка целостности подписи: Убедиться, что сама структура подписи не повреждена.
- Проверка подлинности подписи: С использованием открытого ключа из сертификата подписанта проверить, что подпись действительно была создана соответствующим закрытым ключом. Это включает проверку подписи над
SignedAttributes. - Проверка соответствия хеша данных: Извлечь
message-digestизSignedAttributes, заново вычислить хеш исходного документа (который должен быть предоставлен отдельно для отсоединенной подписи) и сравнить их. - Проверка сертификата: Убедиться, что сертификат подписанта действителен (не истек, не отозван) и выдан доверенным УЦ (проверка цепочки сертификатов).
Для автоматической проверки можно использовать специализированные программы, онлайн-сервисы валидации или написать собственный код, используя те же библиотеки (gostcrypto, asn1crypto).
Рекомендуемые запросы для дальнейшего изучения
- Как проверить отсоединенную подпись CAdES-BES ГОСТ Р в Python?
- Генерация ключей и сертификатов ГОСТ Р для электронной подписи.
- Различия между CAdES-BES, CAdES-T, CAdES-C и CAdES-X-L.
- Использование PKCS#11 токенов для подписи ГОСТ Р в Python.
Источники
Last updated May 12, 2025