Введение

Каждый разработчик в России рано или поздно проходит через то, что к нему приходит менеджер и говорит, что нужно что-то как-то подписывать через КриптоПро. Разработчик начинает искать информацию в интернете и получает в выдаче кучу терминов вроде СКЗИ, ГОСТ Р 34.10, Стрибог, Кузнечик, PKCS#7, PKCS#11, CAdES-BES, X.509, отсоединенная подпись и др. Попытки во всём этом разобраться приводят его либо на строгие академические статьи с тоннами высшей математики, либо на форумы КриптоПро, где суровые системные администраторы общаются на своём эльфийском.

Дальше будет попытка разобраться во всём этом на человеческом языке.

1. Три кита криптографии: Хэш, Подпись и Шифр

Самая частая ошибка новичков (и авторов плохих ТЗ) - свалить все криптографические термины в одну кучу. В любой современной защищённой системе (будь то ГОСТ или западный стек) работают три абсолютно разных «кита». У каждого из них своя математика и своя строгая роль. Давайте разберём их обязанности.

Кит 1: Хэширование

Делает уникальный сжатый отпечаток

Кит 2: Электронная подпись

Гарантирует авторство и неизменность

Кит 3: Блочное шифрование

Прячет данные от посторонних глаз

Кит первый: Хэширование

Например, ГОСТ Р 34.11-2012 (он же «Стрибог»)

Представьте, что у вас есть огромный договор на 50 мегабайт. Гонять такой объем данных через сложные математические формулы подписи — долго и вычислительно дорого. Поэтому документ сначала нужно «сжать» без потери уникальности.

Функция хэширования берет файл любого размера и превращает его в короткую строку фиксированной длины (например, в 64 символа).

  • Главное свойство: Из хэша невозможно восстановить исходный текст.

  • Главный эффект: Если вы измените в договоре на 50 МБ хотя бы одну запятую, итоговый хэш изменится до неузнаваемости.

Кит второй: Асимметричная электронная подпись

Например, ГОСТ Р 34.10-2012

Электронная подпись отвечает на два главных вопроса: «Кто это подписал?» и «Не изменился ли документ по дороге?». Она работает на базе асимметричной криптографии, где у вас всегда есть пара ключей:

  1. Закрытый ключ: Лежит у вас на защищенном токене или флешке под пин-кодом. Знаете его только вы. Им вы генерируете подпись.

  2. Открытый ключ: Доступен всему миру внутри вашего сертификата. С его помощью любой проверяющий (или сервер ФНС) может убедиться, что подпись сделана именно вашим закрытым ключом.

Магия в том, что закрытый ключ берет хэш вашего документа (от Кит 1) и с помощью разных математических методов превращает его в уникальный цифровой росчерк.

Кит третий: Симметричное блочное шифрование

Например, ГОСТ Р 34.12-2015 (шифры «Магма» и «Кузнечик»)

А вот этот кит как раз занимается тем, что превращает ваши данные в нечитаемую кашу, которую никто не сможет расшифровать без секретного ключа. Это симметричное шифрование: и для закрытия данных, и для их открытия используется один и тот же ключ.

2. Три поколения отечественной криптографии (История ГОСТ)

Криптография не стоит на месте: компьютеры становятся мощнее, математики находят новые уязвимости, а суперкомпьютеры учатся быстрее перебирать ключи. Поэтому регуляторы примерно раз в 10–15 лет проводят масштабную ревизию стандартов и принудительно переводят всю страну на новые алгоритмы.

Поколение

Подпись

Хэш

Шифрование

Статус

1990-е

ГОСТ Р 34.10-94

ГОСТ Р 34.11-94 (отпечаток в 256 бит)

ГОСТ 28147-89

Не используются

2000-е

ГОСТ Р 34.10-2001 (новый революционный алгоритм, основанный на элиптических кривых)

ГОСТ Р 34.11-94 (такой же)

ГОСТ 28147-89

Выпуск сертификатов на ГОСТ-2001 официально прекращен в 2019 году

2012+

ГОСТ Р 34.10-2012 (усиленные эллиптические кривые, ключи 256/512 бит)

ГОСТ Р 34.11-2012 (Стрибог, 256/512 бит)

ГОСТ Р 34.12-2015 (Магма - тот же ГОСТ 28147-89, только с фиксацией определённых констант, и Кузнечик - принципиально новый алгоритм)

Используются сейчас

3. А что у них? Западные аналоги

Российские ГОСТы не уникальны по своей логике — они решают те же самые задачи, что и международные алгоритмы. Чтобы вам было проще ориентироваться, давайте сопоставим наши алгоритмы с тем западным стеком (RSA, AES, SHA), с которым вы наверняка сталкивались при настройке обычного веб-сервера Nginx или работы с JWT-токенами.

Западный мир криптографии прошел точно такой же путь эволюции от уязвимого софта к стойкому.

Аналог ГОСТ-94

Аналог ГОСТ-2012

Хэширование

MD5 / SHA-1 (Математики научились находить коллизии)

SHA-256 / SHA-512 (База для HTTPS)

Электронная подпись

RSA с короткими ключами (512/1024 бит взламываются перебором на фермах видеокарт)

RSA (2048+ бит) или быстрый ECDSA (на эллиптических кривых)

Блочное шифрование

DES / 3DES (Медленные, с мелким размером блока в 64 бита)

AES (128 / 256 бит) (Мировой стандарт, зашит в микроархитектуру современных процессоров)

4. Разбираемся с семейством стандартов PKCS и X.509

В предыдущих главах мы разобрались с математикой: у нас есть хэш «Стрибог», подпись ГОСТ 34.10 и шифр «Магма». Но как операционная система или ваш код на Python узнают, что конкретный набор байт — это именно открытый ключ ГОСТ, а не кусок видеофайла?

Математика без стандартов упаковки бесполезна. Чтобы софт разных разработчиков понимал друг друга, компания RSA Security создала семейство стандартов PKCS (Public-Key Cryptography Standards), а комитет ITU-T — стандарт X.509.

Как достучаться до железа: PKCS #11 и PKCS #1

Когда ваш закрытый ключ хранится на защищенном токене (например, Рутокен или Джакарта), операционная система не может просто скопировать его в оперативную память — токен этого не позволит из соображений безопасности.

  • PKCS #11 — это стандарт единого интерфейса (драйвера) для работы с аппаратными устройствами [OASIS PKCS11 TC]. Программа (например, КриптоПро) отправляет хэш внутрь токена по правилам PKCS#11, токен сам внутри себя подписывает его ГОСТом и отдает обратно только сырые байты подписи.

  • Связь с Западом: Для алгоритма RSA существует свой базовый стандарт PKCS #1, который описывает самую элементарную математику западной подписи [RFC 8017]. Для ГОСТа аналогом PKCS#1 являются сами российские стандарты.

Как хранить и запрашивать ключи: PKCS #12 и PKCS #10

Если ваш ключ хранится не на токене, а в виде файла на диске, или если вы только собираетесь получить подпись в Удостоверяющем центре (УЦ), в силу вступают другие стандарты:

  • PKCS #10 (Файлы .csr) — это стандарт запроса на выпуск сертификата [RFC 2986]. Вы генерируете пару ключей на компьютере, упаковываете свой открытый ключ и анкетные данные (ФИО, ИНН) по правилам PKCS#10 и отправляете этот файл в УЦ. В ответ вам будет выслан файл .cer - ваш сертификат.

  • PKCS #12 (Файлы .pfx или .p12) — это стандарт защищенного контейнера [RFC 7292]. Если приватный и публичный ключ генерирует УЦ, тогда он может выдать вам один файл, в котором под надежным паролем (зашифрованный «Магмой» или AES) лежат вместе и ваш закрытый ключ, и ваш открытый сертификат.

Цифровой паспорт: X.509 (Файлы .cer или .crt)

Когда УЦ проверил ваши документы, он выпускает ваш главный цифровой паспорт — сертификат соответствия стандарта X.509 [RFC 5280].

  • Обоснование: Этот стандарт строго определяет, в каких именно метаполях будут записаны ваш ИНН, СНИЛС, ОГРН, имя компании, срок действия подписи и, самое главное, сам ваш открытый ключ ГОСТ вместе с идентификаторами алгоритмов (OIDs) [RFC 5280]. Благодаря X.509 любая программа в мире знает, как прочитать ваши данные.

5. Форматы готовых подписей: PKCS #7, CAdES, XAdES и PAdES

Теперь мы подошли к финальной точке. Ваш код на Python взял хэш файла (Кит 1), через КриптоПро попросил токен (по протоколу PKCS#11) подписать его закрытым ключом (Кит 2). На выходе вы получили «сырые» байты подписи — просто набор случайных символов.

Если вы отправите эти сырые байты проверяющей стороне (например, в Честный Знак), их система выдаст ошибку. Почему? Потому что проверяющий софт не знает, чей это открытый ключ, в какое время была сделана подпись и какой именно ГОСТ использовался. Сырую подпись нужно упаковать в «коробку».

Базовая коробка: PKCS #7 / CMS

PKCS #7 (в современных стандартах называется CMS — Cryptographic Message Syntax) — это общепринятый стандарт упаковки криптографических сообщений [RFC 2315].

  • Что внутри: Метод signedData в вашем коде берет сырые байты подписи и упаковывает их в структурированный контейнер ASN.1. Туда же он дописывает идентификаторы алгоритмов ГОСТ и встраивает ваш сертификат X.509, чтобы проверяющий сразу видел, кто подписал документ.

Усовершенствованные коробки под разные задачи

Обычный PKCS#7 имеет огромный минус: в нем нет доверенного штампа времени. Вы можете перевести часы на компьютере назад и подписать документ «прошедшим числом». Чтобы решить эту проблему и адаптировать подпись под разные типы файлов, криптографы создали три усовершенствованных формата.

  • CAdES (CMS Advanced Electronic Signatures):

    Обоснование: Это расширение PKCS#7 [CAdES от КриптоПро]. Именно его вы используете в коде, указывая флаг CADESCOM_CADES_BES. Формат CAdES позволяет добавлять в подпись подписанные атрибуты времени (signingTime) и внешние штампы времени от штамп-серверов (TSA) [Жизненного цикла ЭП]. Идеален для отсоединенных подписей (когда подпись лежит в отдельном файле .sig рядом с исходным документом).

  • XAdES (XML Advanced Electronic Signatures):

    Обоснование: Если вы подписываете строго структурированный XML-документ (например, счет-фактуру для налоговой), создавать отдельный .sig файл неудобно. Стандарт XAdES описывает, как упаковать подпись ГОСТ в виде валидных XML-тегов прямо внутрь самого документа [ETSI EN 319 132].

  • PAdES (PDF Advanced Electronic Signatures):

    Обоснование: Создан специально для документов PDF. Подпись ГОСТ зашивается в специальный бинарный сектор внутри PDF-файла [ETSI EN 319 142]. Когда пользователь открывает такой файл в Adobe Reader, программа видит эту структуру, проверяет её по цепочке сертификатов и отображает красивый интерактивный штамп: «Документ подписан цифровой подписью».

Заключение

Криптография ГОСТ часто пугает обилием сложных аббревиатур. Однако за ними скрывается логичная и упорядоченная система, где у каждого элемента своя роль. Одни стандарты отвечают за математическую стойкость, другие — за доступ к железу, а третьи служат универсальной «упаковкой», позволяющей софту от разных разработчиков понимать друг друга.

Если провести параллели с привычным международным стеком, то весь путь данных выстраивается в понятную картину. В конечном счете работа с отечественной криптографией перестает быть черной магией и превращается в обычную, предсказуемую инженерную задачу.

Комментарии (8)


  1. Adgh
    23.09.2026 11:51

    Статья в хабе Python, но нет ни одного примера... Можно хотя бы привести пример как именно?

    ...код на Python взял хэш файла (Кит 1), через КриптоПро попросил токен (по протоколу PKCS#11) подписать его закрытым ключом (Кит 2). На выходе вы получили «сырые» байты подписи — просто набор случайных символов.


    1. yrustt Автор
      23.09.2026 11:51

      Пример есть в официальной документации КриптоПро:
      https://docs.cryptopro.ru/cades/pycades/pycades-samples/pycades-signhash-verifyhash


  1. martin_wanderer
    23.09.2026 11:51

    Если в разделах про хэширование и шифрование назвали алгоритмы, то в случае подписи как-то туманнее всего обошлись - "магия" и какие-то циферки на выходе. Правильно ли я понимаю, что "подпись" - это ни больше ни меньше, чем хэш, зашифрованный на секретном ключе? ( В отличие от собственно шифрования, где шифруют на публичном)


    1. yrustt Автор
      23.09.2026 11:51

      По-моему, лучше подходит определение математическое преобразование или функция f(x).

      Если шифрование - это математическое преобразование, которое может быть асимметричным и симметричным и предполагает возможность расшифровки, то хэширование вообще не предполагает наличие ключей и обязано быть необратимым.

      Тогда подпись - это математическое преобразование, результат которого можно "верифицировать на подлинность" зная определённые параметры. И она тоже является необратимой операцией.


      1. martin_wanderer
        23.09.2026 11:51

        Так конечно, строже, но, боюсь, менее понятно. Вот в RSA мне понятно, что хоть шифрование хоть подпись, это принципиально одна и та же математическая операция возведения в степень по модулю. Только показатель степени разный: в одном случае публичный, в другом секретный. А вот математику эллиптических кривых я уже не понимаю, потому может быть и сам вопрос некорректно ставлю. Так вот при подписи используется тот же самый алгоритм преобразования, что при шифровании?


        1. yrustt Автор
          23.09.2026 11:51

          Нет, сейчас алгоритмы абсолютно разные.


          1. martin_wanderer
            23.09.2026 11:51

            Спасибо. Тогда, мне кажется, самым маленьким (и не только) было бы чрезвычайно полезно понимать, как выполняется проверка подписи. Наверное что-то чему-то должно оказаться равно. А без этого нет доверия всей этой магии.


            1. yrustt Автор
              23.09.2026 11:51

              Если рассматривать алгоритмы на элиптических кривых, то там результат подписи - это два числа r и s. Тогда имея исходный документ (возможность получить хэш по Стрибог), открытый ключ и число s, алгоритм однозначно позволяет рассчитать r, если значения совпали, то значит всё верно.