public inbox for gost@lists.stargrave.org
Atom feed
From: Sergey Matveev <stargrave@stargrave•org>
To: gost@lists.cypherpunks.su
Subject: Re: Проблема с верификацией ЭЦП pygost
Date: Mon, 7 Jul 2025 17:03:30 +0300	[thread overview]
Message-ID: <aGvTw3sAo7Cw7pLG@stargrave.org> (raw)
In-Reply-To: <1751895664.713624990@f162.i.mail.ru>

[-- Attachment #1: Type: text/plain, Size: 3929 bytes --]

Приветствую!

*** Богдан ветров [2025-07-07 16:41]:
>Буду крайне признателен,если вы посмотрите мой код и поможете понять в чем я не прав.
>Ссылка на github:  https://github.com/sebastianfym/pygost_test.git

* Если что, то я совершенно не знаю как устроен и работает asn1crypto.
  Не то чтобы это проблема, но с ним ничего не подскажу
* PyGOST ничего не знает про ASN.1 и он выполняет только низкоуровневые
  функции чисто криптографии

--8<--# 0 [                                  8a41d3c09 | main.py ]--8<--
  14 curve = CURVES["id-tc26-gost-3410-12-256-paramSetA"]
--8<----------------------------------------------------------------8<--
Судя по сертификату приложенному к вашей CMS, в нём используется

    publicKeyParamSet: OBJECT IDENTIFIER 1.2.643.2.2.36.0 (id_GostR3410_2001_CryptoPro_XchA_ParamSet)

а вы используете id-tc26-gost-3410-12-256-paramSetA. Это две разные
эллиптические кривые. id-tc26-gost-3410-12-256-paramSetB должна подойти.

--8<--# 1 [                                  8a41d3c09 | main.py ]--8<--
  35 public_key_info = certificate['tbs_certificate']['subject_public_key_info']
  37 public_key_bytes = public_key_info['public_key'].native
  39 pub = pub_unmarshal(public_key_bytes)
--8<----------------------------------------------------------------8<--

В ГОСТовых сертификатах хранится не сырое значение 512/1024 бит значение
ключа, а обёрнутое в ASN.1 OCTET STRING. pub_unmarshal просто преобразует
набор байт которые вы ему предоставили и не проверяет всё ли с ними корректно.

--8<--# 2 [                                  8a41d3c09 | main.py ]--8<--
  42 dgst = gost34112012256.new(pdf_data).digest()
  44 # Читаем подпись из файла .sig в бинарном режиме
  45 signer_info = signed_data['signer_infos'][0]
  46 signature = signer_info['signature'].native
  56 # Проверяем подпись
  57 result = verify(curve, pub, dgst, signature)
--8<----------------------------------------------------------------8<--
Так проверка подписи точно не пройдёт, так как у вас современный CMS,
где подпись делается не над detached данными, а над структурой
signedAttrs из CMS (содержащей id_pkcs9_at_contentType,
id_pkcs9_at_signingTime, id_pkcs9_at_messageDigest,
id_aa_signingCertificateV2 атрибуты). Необходимо проверять подпись над
этой signedAttrs структуры закодированной в DER, без IMPLICIT ASN.1 tag.
Как это сделать asn1crypto -- понятия не имею. Есть много примеров
работы с ГОСТ CMS и сертификатами в PyDERASN проекте:
http://www.pyderasn.cypherpunks.su/ -- там же и проверка совместно с
PyGOST напротив многочисленных примеров из ТК26 рекомендаций.

Хэш PDF-ки можно проверить напротив атрибута id_pkcs9_at_messageDigest.
Возможно хэш придётся перевернуть (у нас с ГОСТовыми алгоритмами разброд
и шатание касательно endianness).

-- 
Sergey Matveev (http://www.stargrave.org/)
LibrePGP: 12AD 3268 9C66 0D42 6967  FD75 CB82 0563 2107 AD8A

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

      reply	other threads:[~2025-07-07 14:03 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-07 13:41 Проблема с верификацией ЭЦП pygost Богдан ветров
2025-07-07 14:03 ` Sergey Matveev [this message]