Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline pavelsh  
#1 Оставлено : 14 мая 2025 г. 22:14:59(UTC)
pavelsh

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.12.2014(UTC)
Сообщений: 5

Поблагодарили: 3 раз в 3 постах
Здравствуйте. Подскажите пожалуйста.
Пробуем создать используя функции libcapi20 раздельную подпись в которой будет только идентификатор ключа подписанта
заполняем структуры
memset(&signerInfo, 0, sizeof(CMSG_SIGNER_ENCODE_INFO));
signerInfo.cbSize = sizeof(CMSG_SIGNER_ENCODE_INFO);
signerInfo.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
signerInfo.SignerId.f_name.KeyId.cbData = keyID.cbData;
signerInfo.SignerId.f_name.KeyId.pbData = keyID.pbData;
signerInfo.pCertInfo = nullptr;
signerInfo.hCryptProv = hCryptProv;
signerInfo.dwKeySpec = dwKeySpec;
signerInfo.HashAlgorithm.pszObjId = (LPSTR)szOID_CP_GOST_R3411_12_256;

memset(&signedInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
signedInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
signedInfo.cSigners = 1;
signedInfo.rgSigners = &signerInfo;
signedInfo.cCertEncoded = 0;
signedInfo.rgCertEncoded = nullptr;


и получаем аварийное завершение при вызове
hMsg = СryptMsgOpenToEncode(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
CMSG_DETACHED_FLAG,
CMSG_SIGNED,
&signedInfo,
nullptr,
nullptr);

если указываем вместо
signerInfo.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
signerInfo.SignerId.f_name.KeyId.cbData = keyID.cbData;
signerInfo.SignerId.f_name.KeyId.pbData = keyID.pbData;
signerInfo.pCertInfo = nullptr;

только
signerInfo.pCertInfo = pSignerCert->pCertInfo;
то подпись формируется успешно, но с данными структуры pCertInfo

Направте пожалуйста, как сделать раздельную подпись в которой будет только идентификатор ключа подписанта

Отредактировано пользователем 15 мая 2025 г. 10:30:42(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил pavelsh за этот пост.
Зубов Иван оставлено 21.05.2025(UTC)

Wanna join the discussion?! Login to your Форум КриптоПро forum account. Новые регистрации запрещены.

Offline Зубов Иван  
#2 Оставлено : 21 мая 2025 г. 15:42:34(UTC)
Зубов Иван

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 02.11.2017(UTC)
Сообщений: 60
Мужчина

Сказал «Спасибо»: 12 раз
Поблагодарили: 25 раз в 23 постах
Здравствуйте.

Крэш это нехорошо, посмотрим, постараемся исправить. Спасибо, что пожаловались.

Если запустить ваш код под Windows, то поведение будет точно таким же: при signerInfo.pCertInfo = 0 крэш, при заполнении этого поля подпись формируется успешно. Следовательно, это поле заполнять требуется согласно реализации Windows и согласно нашей реализации. И действительно, в документации Microsoft нет информации, что поле можно не заполнять:
Цитата:
pCertInfo
A pointer to a CERT_INFO structure that contains the
Issuer, SerialNumber, and SubjectPublicKeyInfo members.
The pbData members of the Issuer and SerialNumber structures combined uniquely identify a certificate. The Algorithm member of the SubjectPublicKeyInfo structure specifies the hash encryption algorithm used.


Я дополнил ваш код получением подписанного сообщения:
Код:
DWORD dwSize;
BYTE rawData[] = { 0xFF, 0xAA };
CPPUNIT_ASSERT(CryptMsgUpdate(hMsg, rawData, sizeof(rawData), TRUE));
std::vector<BYTE> encodedMessage;
CPPUNIT_ASSERT(CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, &dwSize));
encodedMessage.resize(dwSize);
CPPUNIT_ASSERT(CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, &encodedMessage[0], &dwSize));
encodedMessage.resize(dwSize);

KeyId задал так:
Код:
BYTE arr[] = { 0x01, 0x02 };
CRYPT_HASH_BLOB keyID = { sizeof(arr), arr };


Получил следующие сообщения после декодирования в asn1js:
Windows (считаем эту реализацию эталонной):
Цитата:
ContentInfo SEQUENCE (2 elem)
contentType ContentType OBJECT IDENTIFIER 1.2.840.113549.1.7.2 signedData (PKCS #7)
content [0] (1 elem)
SignedData SEQUENCE (4 elem)
version CMSVersion INTEGER 3
digestAlgorithms DigestAlgorithmIdentifiers SET (1 elem)
DigestAlgorithmIdentifier SEQUENCE (2 elem)
algorithm OBJECT IDENTIFIER 1.2.643.7.1.1.2.2 gost2012Digest256 (GOST R 34.11-2012 256 bit digest)
parameters ANY NULL
encapContentInfo EncapsulatedContentInfo SEQUENCE (1 elem)
eContentType ContentType OBJECT IDENTIFIER 1.2.840.113549.1.7.1 data (PKCS #7)
signerInfos SignerInfos SET (1 elem)
SignerInfo SEQUENCE (5 elem)
version CMSVersion INTEGER 3
subjectKeyIdentifier SignerIdentifier [0] (2 byte) 0102
digestAlgorithm DigestAlgorithmIdentifier SEQUENCE (2 elem)
algorithm OBJECT IDENTIFIER 1.2.643.7.1.1.2.2 gost2012Digest256 (GOST R 34.11-2012 256 bit digest)
parameters ANY NULL
signatureAlgorithm SignatureAlgorithmIdentifier SEQUENCE (1 elem)
algorithm OBJECT IDENTIFIER 1.2.643.7.1.1.1.1 gost2012PublicKey256 (GOST R 34.10-2012 256 bit public key)
signature SignatureValue OCTET STRING (64 byte) 38564247D9A664A4D9ECF5EBDE7E7A6E528DA62C3A3D46BE4DDD2810E10AFB38D4F39D…

*nix:
Цитата:
ContentInfo SEQUENCE (2 elem)
contentType ContentType OBJECT IDENTIFIER 1.2.840.113549.1.7.2 signedData (PKCS #7)
content [0] (1 elem)
SignedData SEQUENCE (4 elem)
version CMSVersion INTEGER 1
digestAlgorithms DigestAlgorithmIdentifiers SET (1 elem)
DigestAlgorithmIdentifier SEQUENCE (1 elem)
algorithm OBJECT IDENTIFIER 1.2.643.2.2.9 gostDigest (GOST R 34.11-94 digest)
encapContentInfo EncapsulatedContentInfo SEQUENCE (1 elem)
eContentType ContentType OBJECT IDENTIFIER 1.2.840.113549.1.7.1 data (PKCS #7)
signerInfos SignerInfos SET (1 elem)
SignerInfo SEQUENCE (5 elem)
version CMSVersion INTEGER 1
subjectKeyIdentifier SignerIdentifier [0] (2 byte) 0102
digestAlgorithm DigestAlgorithmIdentifier SEQUENCE (1 elem)
algorithm OBJECT IDENTIFIER 1.2.643.2.2.9 gostDigest (GOST R 34.11-94 digest)
signatureAlgorithm SignatureAlgorithmIdentifier SEQUENCE (2 elem)
algorithm OBJECT IDENTIFIER 1.2.643.2.2.19 gostPublicKey (GOST R 34.10-2001 (ECC) public key)
parameters ANY NULL
signature SignatureValue OCTET STRING (64 byte) 785B28CE0DFB863551E69E37D36654E25969048A1DC67A69CD34B02607C5A6A3CBF1CB…

Собственно, отсюда вопрос: а что вас смутило в этих подписях?
SignerInfo SEQUENCE (5 elem)
subjectKeyIdentifier SignerIdentifier [0] (2 byte) 0102
Это ли не то, чего вы хотели? Серийного номера, издателя не видать. То, что явно было передано, видно. Или я что-то проглядел?
Техническую поддержку оказываем тут
Наша база знаний
Offline pavelsh  
#3 Оставлено : 21 мая 2025 г. 16:09:24(UTC)
pavelsh

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.12.2014(UTC)
Сообщений: 5

Поблагодарили: 3 раз в 3 постах
смутило то что в Ваших дампах
для Windows

version CMSVersion INTEGER 3

для *nix:

version CMSVersion INTEGER 1

и SKI для разных версий SignerInfo как я понял имет разное место расположения
(rDN, подписанные атрибуты, SignerInfo.SignerId (если задан SignerInfo.SignerId.dwIdChoise версия должна быть version CMSVersion INTEGER 3))




csp 5 r3 Astralinux 1.7se получаем дамп:
0 166: SEQUENCE {
3 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
14 152: [0] {
17 149: SEQUENCE {
20 1: INTEGER 1
23 12: SET {
25 10: SEQUENCE {
27 8: OBJECT IDENTIFIER gost2012Digest256 (1 2 643 7 1 1 2 2)
: }
: }
37 11: SEQUENCE {
39 9: OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
: }
50 117: SET {
52 115: SEQUENCE {
54 1: INTEGER 1
57 20: [0]
: 66 A5 C6 4C 7B 3C DC 50 A1 04 7A 7E 14 A0 18 14
: 00 3C 3C DC
79 10: SEQUENCE {
81 8: OBJECT IDENTIFIER gost2012Digest256 (1 2 643 7 1 1 2 2)
: }
91 10: SEQUENCE {
93 8: OBJECT IDENTIFIER gost2012PublicKey256 (1 2 643 7 1 1 1 1)
: }
103 64: OCTET STRING
: 69 54 68 06 43 CF F3 2B 4C C4 CD 08 5F CA 2D D4
: AD F8 A9 15 C3 54 3C 22 7C 73 4C 11 BB BC A6 85
: 65 B9 75 C8 EA 00 22 26 A0 57 43 68 05 3E C3 60
: E4 67 B6 2B DB 3F 47 AA E3 DA 33 42 91 79 A1 EA
: }
: }
: }
: }
: }

как получить из сформированной структуры SKI
57 20: [0]
: 66 A5 C6 4C 7B 3C DC 50 A1 04 7A 7E 14 A0 18 14
: 00 3C 3C DC
используя функции capilite из состава libcapi2.0.so

Отредактировано пользователем 21 мая 2025 г. 16:32:46(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил pavelsh за этот пост.
Зубов Иван оставлено 21.05.2025(UTC)
Offline Зубов Иван  
#4 Оставлено : 21 мая 2025 г. 16:35:34(UTC)
Зубов Иван

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 02.11.2017(UTC)
Сообщений: 60
Мужчина

Сказал «Спасибо»: 12 раз
Поблагодарили: 25 раз в 23 постах
Касательно версий: кажется, это уже другой вопрос, довольно независимый от первого.

Спасибо большое, что обратили внимание! Похоже, это наша ошибка. Написал запрос CPCSP-15140 в трекер задач.

Тем не менее, ваши прикладные сценарии вполне могут работать уже сейчас, до каких-либо исправлений. Об этом написано и в RFC:
Цитата:
1.3. Version Numbers
Each of the major data structures includes a version number as the
first item in the data structure. The version numbers are intended
to avoid ASN.1 decode errors. Some implementations do not check the
version number prior to attempting a decode, and if a decode error
occurs, then the version number is checked as part of the error
handling routine. This is a reasonable approach; it places error
processing outside of the fast path. This approach is also forgiving
when an incorrect version number is used by the sender
Техническую поддержку оказываем тут
Наша база знаний
Offline Зубов Иван  
#5 Оставлено : 21 мая 2025 г. 16:55:54(UTC)
Зубов Иван

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 02.11.2017(UTC)
Сообщений: 60
Мужчина

Сказал «Спасибо»: 12 раз
Поблагодарили: 25 раз в 23 постах
Отвечая на ваш третий вопрос:
Цитата:
как получить из сформированной структуры SKI
57 20: [0]
: 66 A5 C6 4C 7B 3C DC 50 A1 04 7A 7E 14 A0 18 14
: 00 3C 3C DC
используя функции capilite из состава libcapi2.0.so


Так:
Код:
    std::vector<BYTE> buffer;
    CPPUNIT_ASSERT(!m_args.ReadFromFile(&buffer, _TEXT("unix.sgn")));

    HCRYPTMSG hMsg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0, NULL, NULL);
    CPPUNIT_ASSERT(hMsg);

    CPPUNIT_ASSERT(CryptMsgUpdate(hMsg, &buffer[0], (DWORD)buffer.size(), TRUE));

    BYTE rawData[] = { 0xFF, 0xAA };
    CPPUNIT_ASSERT(CryptMsgUpdate(hMsg, rawData, sizeof(rawData), TRUE));

    DWORD dwSize;
    std::vector<BYTE> encodedMessage;
    CPPUNIT_ASSERT(CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 0, NULL, &dwSize));
    encodedMessage.resize(dwSize);
    CPPUNIT_ASSERT(CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 0, &encodedMessage[0], &dwSize));
    encodedMessage.resize(dwSize);
    CERT_ID *pCertId = (CERT_ID *)&encodedMessage[0];
    UNUSED(pCertId);
Техническую поддержку оказываем тут
Наша база знаний
Offline pavelsh  
#6 Оставлено : 21 мая 2025 г. 16:55:56(UTC)
pavelsh

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.12.2014(UTC)
Сообщений: 5

Поблагодарили: 3 раз в 3 постах
возможно связь есть
если для Astra linux 17 (при использовании libcapi2.0.so из состава csp5r3)
в случае когда при формировании раздельной подписи указано SignerInfo.SignerId.dwIdChoise
формировалась подпись с version CMSVersion INTEGER 3 то тогда при разборе подписи была бы
возможность получить SKI стандартным способом, а так
получаю пустые значения
pSignerInfobuf->SignerId.f_name.HashId
pSignerInfobuf->SignerId.f_name.IssuerSerialNumber
pSignerInfobuf->SignerId.f_name.KeyId

и это вроде как ожидаемо, так как pSignerInfobuf->dwVersion = 1
поэтому приходится к сожалению доставать SKI из подписи вручную
thanks 1 пользователь поблагодарил pavelsh за этот пост.
Зубов Иван оставлено 21.05.2025(UTC)
Offline Зубов Иван  
#7 Оставлено : 21 мая 2025 г. 17:08:25(UTC)
Зубов Иван

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 02.11.2017(UTC)
Сообщений: 60
Мужчина

Сказал «Спасибо»: 12 раз
Поблагодарили: 25 раз в 23 постах
Подтверждаю, что есть ошибка в этом месте сейчас на *nix. И при разборе подписей, сделанных на *nix с неверной версией CMS, и при разборе сделанных на Windows с верной версией. Спасибо большое вам, что сообщили. Внёс в трекер ошибок как тикет CPCSP-15141.

Обойти на уровне API можно так, как я написал в предыдущем сообщении. Я не проверял на R3, я проверял на последней сборке из репозитория, но предположительно на вашей сборке всё будет аналогично.
Техническую поддержку оказываем тут
Наша база знаний
Offline pavelsh  
#8 Оставлено : 21 мая 2025 г. 23:33:21(UTC)
pavelsh

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.12.2014(UTC)
Сообщений: 5

Поблагодарили: 3 раз в 3 постах
может я чтото не понимаю, но к сожалению предложенный Вами вариант с CMSG_SIGNER_CERT_ID_PARAM у меня не работает.
и нужно использовать сертифицированную версию CSP 5.0 r3
Offline pavelsh  
#9 Оставлено : 21 мая 2025 г. 23:39:54(UTC)
pavelsh

Статус: Новичок

Группы: Участники
Зарегистрирован: 23.12.2014(UTC)
Сообщений: 5

Поблагодарили: 3 раз в 3 постах
datasigncmsid.zip (1kb) загружен 3 раз(а).
Offline Зубов Иван  
#10 Оставлено : 22 мая 2025 г. 13:43:11(UTC)
Зубов Иван

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 02.11.2017(UTC)
Сообщений: 60
Мужчина

Сказал «Спасибо»: 12 раз
Поблагодарили: 25 раз в 23 постах
Проверил на сертифицированной R3 с сайта. Не подтверждаю, у меня работает на Linux. Код вот такой:
Код:
    std::vector<BYTE> buffer;
    CPPUNIT_ASSERT(!m_args.ReadFromFile(&buffer, _TEXT("client.sgn")));

    HCRYPTMSG hMsg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, 0, 0, NULL, NULL);
    CPPUNIT_ASSERT(hMsg);

    CPPUNIT_ASSERT(CryptMsgUpdate(hMsg, &buffer[0], (DWORD)buffer.size(), TRUE));

    BYTE rawData[] = { 0xFF, 0xAA };
    CPPUNIT_ASSERT(CryptMsgUpdate(hMsg, rawData, sizeof(rawData), TRUE));

    DWORD dwSize;
    std::vector<BYTE> encodedMessage;
    CPPUNIT_ASSERT(CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 0, NULL, &dwSize));
    encodedMessage.resize(dwSize);
    CPPUNIT_ASSERT(CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 0, &encodedMessage[0], &dwSize));
    encodedMessage.resize(dwSize);
    CERT_ID *pCertId = (CERT_ID *)&encodedMessage[0];
    UNUSED(pCertId);

client.sgn -- подпись из архива, что вы передали. После выполнения такого кода в pCertId находится желаемый идентификатор:
Цитата:
(gdb) p *pCertId
$2 = {dwIdChoice = 2, f_name = {IssuerSerialNumber = {Issuer = {cbData = 20, pbData = 0x13f4a88 "f\245\306L{<\334P\241\004z~\024\240\030\024"}, SerialNumber = {cbData = 20925024,
pbData = 0x138b300 "\360\341\070\001"}}, KeyId = {cbData = 20, pbData = 0x13f4a88 "f\245\306L{<\334P\241\004z~\024\240\030\024"}, HashId = {cbData = 20,
pbData = 0x13f4a88 "f\245\306L{<\334P\241\004z~\024\240\030\024"}}}
(gdb) x/20x pCertId->f_name.KeyId.pbData
0x13f4a88: 0x66 0xa5 0xc6 0x4c 0x7b 0x3c 0xdc 0x50
0x13f4a90: 0xa1 0x04 0x7a 0x7e 0x14 0xa0 0x18 0x14
0x13f4a98: 0x00 0x3c 0x3c 0xdc

Надеюсь, это поможет. Если нет, то опишите, пожалуйста, более подробно, какой у вас код и что именно не работает: какой вызов возвращает ошибку, какое значение после непрошедшего вызова возвращает GetLastError(), или же, если все вызовы возвращают успех, то какая структура имеет неожиданные значения внутри, какие именно это неожиданные значения, какие значения вместо них вы ожидали увидеть.
Техническую поддержку оказываем тут
Наша база знаний
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.