Статус: Участник
Группы: Участники
Зарегистрирован: 11.12.2024(UTC) Сообщений: 10  Откуда: Москва
|
Коллеги добрый день. Помогите разобраться как установить комбинированный алгоритм подписи в параметр HashEncryptionAlgorithm. Пытаюсь установить следующим образом, но алгоритм на выходе почему то всегда берётся из публичного ключа. Код:EncodedTime signTime = getCurrentEncodedTime();
result.date = signTime.localTime;
CRYPT_ATTR_BLOB attrBlob;
CRYPT_ATTRIBUTE attr;
attrBlob.cbData = signTime.asn1Data.size();
attrBlob.pbData = signTime.asn1Data.data();
attr.pszObjId = (LPSTR)szOID_RSA_signingTime;
attr.cValue = 1;
attr.rgValue = &attrBlob;
CRYPT_SIGN_MESSAGE_PARA stSignMessagePara;
DWORD MessageSizeArray[1];
const BYTE* MessageArray[1];
CRYPT_OBJID_BLOB hashParam;
hashParam.cbData = 0;
hashParam.pbData = nullptr;
CRYPT_ALGORITHM_IDENTIFIER hashAlgo;
CRYPT_ALGORITHM_IDENTIFIER signAlgo;
hashAlgo.pszObjId = (LPSTR)szOID_CP_GOST_R3411_12_512;
signAlgo.pszObjId = (LPSTR)szOID_CP_GOST_R3411_12_512_R3410;
hashAlgo.Parameters = hashParam;
signAlgo.Parameters = hashParam;
ZeroMemory(&stSignMessagePara, sizeof(CRYPT_SIGN_MESSAGE_PARA));
stSignMessagePara.cbSize = sizeof(stSignMessagePara);
stSignMessagePara.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
stSignMessagePara.pSigningCert = pCertCtx_;
stSignMessagePara.HashAlgorithm= hashAlgo;
stSignMessagePara.pvHashAuxInfo = nullptr;
stSignMessagePara.HashEncryptionAlgorithm = signAlgo;
stSignMessagePara.pvHashEncryptionAuxInfo = nullptr;
stSignMessagePara.rgpMsgCert = &pCertCtx_;
stSignMessagePara.cMsgCert = 1;
stSignMessagePara.cAuthAttr = 1;
stSignMessagePara.rgAuthAttr = &attr;
MessageArray[0] = (const BYTE*)datatosing.bytes();
MessageSizeArray[0] = datatosing.length;
CryptSignMessage(
&stSignMessagePara,
TRUE,
1,
MessageArray,
MessageSizeArray,
NULL,
&dwSignatureSize)
Пробовал сделать тоже самое через CryptMsgOpenToEncode и структуру CMSG_SIGNER_ENCODE_INFO но результат оказался таким же. А алгоритм поменять нужно так как при последующей проверке на другой системе, где используется JCP получаю ошибку вида: java.security.NoSuchAlgorithmException: no such algorithm: 1.2.643.7.1.1.1.2 for provider JCSPИмел опыт только с JCP там можно задавать параметры digest и sign (JCP.GOST_DIGEST_2012_512_OID и JCP.GOST_SIGN_2012_512_OID), а как сделать тоже самое в cpapilite разобраться не могу... Отредактировано пользователем 8 октября 2025 г. 15:38:38(UTC)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 13,961   Сказал «Спасибо»: 602 раз Поблагодарили: 2342 раз в 1839 постах
|
Здравствуйте.
В сертификате указано и из него должно использоваться.
1.2.643.7.1.1.1.1 - алгоритм подписи ГОСТ Р 34.10-2012 с ключом 256 - в квал.сертификатах 1.2.643.7.1.1.1.2 - алгоритм подписи ГОСТ Р 34.10-2012 с ключом 512
Почему потребовался ключ 512?
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 11.12.2024(UTC) Сообщений: 10  Откуда: Москва
|
Началось с того что при проверки подписи на другой системе где используется JCSP и проверка проходит через java.security.signature получаю ошибку: java.security.NoSuchAlgorithmException: no such algorithm: 1.2.643.7.1.1.1.2 for provider JCSP. Она происходит в тот момент когда Signature обращается к JCSP и не находит там алгоритма 1.2.643.7.1.1.1.2. В этот момент я пошел посмотреть как реализован выбор алгоритма на других системах, от которых данная проверка проходит успешно и нашел там следующую java реализацию: Код:
switch (keyAlgoritm) {
case JCP.GOST_EL_2012_512_NAME:
case JCP.GOST_DH_2012_512_NAME:
signAlg = JCP.GOST_SIGN_2012_512_NAME;
digestOidValue = JCP.GOST_DIGEST_2012_512_OID;
signOidValue = JCP.GOST_SIGN_2012_512_OID;
digestAlg = JCP.GOST_DIGEST_2012_512_NAME;
break;
case JCP.GOST_EL_2012_256_NAME:
case JCP.GOST_DH_2012_256_NAME:
signAlg = JCP.GOST_SIGN_2012_256_NAME;
digestOidValue = JCP.GOST_DIGEST_2012_256_OID;
digestAlg = JCP.GOST_DIGEST_2012_256_NAME;
signOidValue = JCP.GOST_SIGN_2012_256_OID;
break;
case JCP.GOST_EL_SIGN_NAME:
case JCP.GOST_DHEL_SIGN_NAME:
signAlg = JCP.GOST_EL_SIGN_NAME;
digestOidValue = JCP.GOST_DIGEST_OID;
signOidValue = JCP.GOST_EL_SIGN_OID;
break;
}
}
И если я правильно понимаю провайдер JCSP ожидает алгоритм 1.2.643.7.1.1.3.3 а не 1.2.643.7.1.1.1.2 в поле алгоритма подписи. Отредактировано пользователем 8 октября 2025 г. 20:01:37(UTC)
| Причина: Не указана
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 11.12.2024(UTC) Сообщений: 10  Откуда: Москва
|
Автор: Андрей *  Здравствуйте.
В сертификате указано и из него должно использоваться.
1.2.643.7.1.1.1.1 - алгоритм подписи ГОСТ Р 34.10-2012 с ключом 256 - в квал.сертификатах 1.2.643.7.1.1.1.2 - алгоритм подписи ГОСТ Р 34.10-2012 с ключом 512
Почему потребовался ключ 512?
Здравствуйте. Такие ключи выпускает наш уц. Есть какие то соображение по проблеме? я так понимаю что jcsp ищет алгоритм подписи (1.2.643.7.1.1.3.3), но находит в нужном месте алгоритм ключа вместо него и дальше выкидывает ошибку. А как с помощью cpapilite установить нужный алгоритм подписи я не разобрался к сожалению. Отредактировано пользователем 10 октября 2025 г. 12:44:01(UTC)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,061  Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 738 раз в 696 постах
|
Добрый день. Приведите, пожалуйста, пример, что делаете и стек ошибки, которая возникает. |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 11.12.2024(UTC) Сообщений: 10  Откуда: Москва
|
Автор: Евгений Афанасьев  Добрый день. Приведите, пожалуйста, пример, что делаете и стек ошибки, которая возникает. Подпись выполняю следующим образом: Код: EncodedTime signTime = getCurrentEncodedTime();
result.date = signTime.localTime;
CRYPT_ATTR_BLOB attrBlob{};
CRYPT_ATTRIBUTE attr{};
attrBlob.cbData = signTime.asn1Data.size();
attrBlob.pbData = signTime.asn1Data.data();
attr.pszObjId = (LPSTR)szOID_RSA_signingTime;
attr.cValue = 1;
attr.rgValue = &attrBlob;
CRYPT_OBJID_BLOB emptyParam;
emptyParam.cbData = 0;
emptyParam.pbData = nullptr;
CRYPT_ALGORITHM_IDENTIFIER hashAlgo{};
CRYPT_ALGORITHM_IDENTIFIER signAlgo{};
[b]hashAlgo.pszObjId = (LPSTR)szOID_CP_GOST_R3411_12_512;
signAlgo.pszObjId = (LPSTR)szOID_CP_GOST_R3411_12_512_R3410[/b];
signAlgo.Parameters = emptyParam;
hashAlgo.Parameters = emptyParam;
CMSG_SIGNER_ENCODE_INFO signer{};
signer.cbSize = sizeof(signer);
signer.pCertInfo = pCertCtx_->pCertInfo;
signer.hCryptProv = hProv;
signer.dwKeySpec = dwKeySpec;
signer.HashAlgorithm = hashAlgo;
signer.HashEncryptionAlgorithm = signAlgo;
signer.pvHashAuxInfo = nullptr;
signer.pvHashEncryptionAuxInfo = nullptr;
signer.cAuthAttr = 1;
signer.rgAuthAttr = &attr;
CMSG_SIGNED_ENCODE_INFO signedInfo{};
signedInfo.cbSize = sizeof(signedInfo);
signedInfo.cSigners = 1;
signedInfo.rgSigners = &signer;
signedInfo.cCertEncoded = 0;
signedInfo.rgCertEncoded = NULL;
hMsg = CryptMsgOpenToEncode(
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
CMSG_DETACHED_FLAG,
CMSG_SIGNED,
&signedInfo,
NULL,
NULL
);
CryptMsgUpdate(hMsg, reinterpret_cast<const BYTE*>(dataToSign.bytes()), dataToSign.length, TRUE)
Дальше проверка подписи выполняется на другой системе с помощью JCSP: Код:Asn1BerDecodeBuffer asnBuf = new Asn1BerDecodeBuffer(signature);
ContentInfo all = new ContentInfo();
all.decode(asnBuf);
if (!new OID(CmsSigner.STR_CMS_OID_SIG).eq(all.contentType.value)) {
throw new Exception("Not supported");
}
SignedData cms = (SignedData) all.content;
if (document == null) {
throw new Exception("No content for verify");
}
if (cms.certificates != null) {
Asn1BerEncodeBuffer encBuf = new Asn1BerEncodeBuffer();
cms.certificates.elements[0].encode(encBuf);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(encBuf.getInputStream());
com.objsys.asn1j.pkcs7.SignerInfo info = cms.signerInfos.elements[0];
OID sigOid = new OID(info.signatureAlgorithm.algorithm.value);
java.security.Signature signature = Signature.getInstance(sigOid.toString(), JCSP.PROVIDER_NAME);
signature.initVerify(certificate);
signature.update(data);
на моменте Signature.getInstance получаю ошибку java.security.NoSuchAlgorithmException: no such algorithm: 1.2.643.7.1.1.1.2 for provider JCSPЕсли посмотреть что попало в подпись следующим способом: Код:HCRYPTMSG hMsg = CryptMsgOpenToDecode( PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
CryptMsgUpdate(hMsg, signature.data(), signature.size(), TRUE);
DWORD cbData = 0;
CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &cbData);
std::vector<BYTE> buffer(cbData);
CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, buffer.data(), &cbData);
CMSG_SIGNER_INFO* pInfo = (CMSG_SIGNER_INFO*)buffer.data();
std::cout << "Signature Algorithm OID: "
<< pInfo->HashEncryptionAlgorithm.pszObjId << std::endl;
CryptMsgClose(hMsg);
Получаю тот же алгоритм ключа 1.2.643.7.1.1.1.2 вместо алгоритма подписи. Отредактировано пользователем 10 октября 2025 г. 13:39:00(UTC)
| Причина: Не указана
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 11.12.2024(UTC) Сообщений: 10  Откуда: Москва
|
Автор: Евгений Афанасьев  Добрый день. Приведите, пожалуйста, пример, что делаете и стек ошибки, которая возникает. Основная проблема в том что алгоритм 1.2.643.7.1.1.1.2 не алгоритм подписи. А в итоговой открепленной подписи он оказывается на месте алгоритма подписи. как сказано в вашем комментарии в заголовочном файле CSP_wincrypt.h: Цитата:If HashEncryptionAlgorithm is present and not NULL its used instead of the SigningCert's PublicKeyInfo.Algorithm. Но при этом если мы даже задаем алгоритм подписи в HashEncryptionAlgorithm то это поле все равно игнорируется и подставляется алгоритм ключа.
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 13,961   Сказал «Спасибо»: 602 раз Поблагодарили: 2342 раз в 1839 постах
|
Автор: Хемуль Хемулевский  Автор: Евгений Афанасьев  Добрый день. Приведите, пожалуйста, пример, что делаете и стек ошибки, которая возникает. Основная проблема в том что алгоритм 1.2.643.7.1.1.1.2 не алгоритм подписи. А в итоговой открепленной подписи он оказывается на месте алгоритма подписи. как сказано в вашем комментарии в заголовочном файле CSP_wincrypt.h: Цитата:If HashEncryptionAlgorithm is present and not NULL its used instead of the SigningCert's PublicKeyInfo.Algorithm. Но при этом если мы даже задаем алгоритм подписи в HashEncryptionAlgorithm то это поле все равно игнорируется и подставляется алгоритм ключа. 1.2.643.7.1.1.1.2 id-tc26-gost3410-12-512 алгоритм подписи ГОСТ Р 34.10-2012 с ключом 512 |
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,061  Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 738 раз в 696 постах
|
OID алгоритма подписи с хэшом 1.2.643.7.1.1.3.2 или 1.2.643.7.1.1.3.2 указывается в сертификате. В CMS подписи задается OID открытого ключа, т.е. для CMS надо digestOid.toString() + "WITH" + sigOid.toString(), а не просто sigOid.toString(). |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 11.12.2024(UTC) Сообщений: 10  Откуда: Москва
|
Автор: Евгений Афанасьев  OID алгоритма подписи с хэшом 1.2.643.7.1.1.3.2 или 1.2.643.7.1.1.3.2 указывается в сертификате. В CMS подписи задается OID открытого ключа, т.е. для CMS надо digestOid.toString() + "WITH" + sigOid.toString(), а не просто sigOid.toString(). Евгений, понял вас. Но может есть вариант задать алгоритм подписи, как например в java? Очень будет тяжело менять уже реализованную валидацию в другой системе, я бы даже сказал не возможно) В заголовочном файле csp_wincrypt сказано: Цитата:If HashEncryptionAlgorithm is present and not NULL its used instead of the SigningCert's PublicKeyInfo.Algorithm. Но я правильно понимаю что это осталось от Windows CryptoAPI но не реализовано? Вот как в java задавали алгоритм подписи в CMS, до перехода на С++: Код:
digestOidValue = JCP.GOST_DIGEST_2012_512_OID;
signOidValue = JCP.GOST_SIGN_2012_512_OID;
final SignedData cms = new SignedData();
cms.signerInfos.elements[0].digestAlgorithm = new DigestAlgorithmIdentifier(new OID(digestOidValue).value);
cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signatureAlgorithm = new SignatureAlgorithmIdentifier(new OID(signOidValue).value);
cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
final Asn1Type messageDigest = new Asn1OctetString(messageDigestBlob);
cms.signerInfos.elements[0].signedAttrs.elements[1].values.elements[0] = messageDigest;
// signature
Asn1BerEncodeBuffer encBufSignedAttr = new Asn1BerEncodeBuffer();
cms.signerInfos.elements[0].signedAttrs.encode(encBufSignedAttr);
final java.security.Signature signature = java.security.Signature.getInstance(signAlg, providerName);
byte[] sign;
final byte[] hSign = encBufSignedAttr.getMsgCopy();
signature.initSign(pk);
signature.update(hSign);
sign = signature.sign();
cms.signerInfos.elements[0].signature = new SignatureValue(sign);
// encode
final Asn1BerEncodeBuffer asn1Buf = new Asn1BerEncodeBuffer();
all.encode(asn1Buf, true);
Отредактировано пользователем 11 октября 2025 г. 0:04:17(UTC)
| Причина: Не указана
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close