Atom Лента - Форум КриптоПро - Тема:Добавление второй подписи CAdES-BES в уже подписаный фаил на C++ - 10Форум КриптоПро - Atom Лентаurn:https:--www-cryptopro-ru:AtomLenta:ForumKriptoPro:Tema:DobavlenievtorojjpodpisiCAdES-BESvuzhepodpisanyjjfailnaC++-10:1Copyright 2024 Форум КриптоПро2024-03-28T18:39:13Zhttps://www.cryptopro.ru/forum2/Images/YAFLogo.pngForum Adminhttps://www.cryptopro.ruforum@cryptopro.ruАндрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Андрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Depishhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59782&name=Depishtwo_oceanshttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=36490&name=two_oceansDepishhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59782&name=DepishDepishhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59782&name=DepishАндрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Depishhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59782&name=DepishАндрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Андрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Андрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *YetAnotherForum.NETurn:https:--www-cryptopro-ru:ftPosts:st1:meid128143:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer_Alt" width="100%"><tr><td>там, где 1 подпись - хеш правильный, но не вложен сертификат,<br />где 2 подписи - вложен сертификат для второй подписи, но хеш не тот.<br /><br />[attach]10051[/attach]</td></tr></table>2021-10-19T21:09:39+03:002021-10-19T21:09:39+03:00Андрей *<table class="content postContainer_Alt" width="100%"><tr><td>там, где 1 подпись - хеш правильный, но не вложен сертификат,<br />где 2 подписи - вложен сертификат для второй подписи, но хеш не тот.<br /><br />[attach]10051[/attach]</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128142:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: two_oceans <a href="/forum2/default.aspx?g=posts&m=128137#post128137"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Добрый день. Вот так интересно дополнили пример, что даже функция стала другой. Лично мне не совсем понятна эта строка:<div class="quote"><span class="quotetitle">Цитата:</span><blockquote>signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);</div></div>Позвольте тоже построить дикую теорию на этом. Смысл в том, что вероятно эта функция вернула гост-2001 вместо гост-2012. Тогда хэш был посчитан по другому алгоритму и должна была быть ошибка о несогласованности алгоритма хэша и алгоритма ключа. Однако если хэш был сохранен как значение, то длина у гост-2001 и гост-2012 256 бит одинакова, то есть значение одного можно загрузить в другой и подписать, тогда ошибки не будет, но хэш при проверке покажется неверным. Можете указать что возвратила эта функция и для ясности еще и посчитать хеши подписываемых данных утилитой<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">cpverify.exe -mk -alg GR3411 filename.txt -inverted_halfbytes 0
cpverify.exe -mk -alg GR3411_2012_256 filename.txt -inverted_halfbytes 0</code></pre>
</div></div></div></div><br /><br />Доброго времени суток!<br /><br />Вот вывод утилиты: <br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
>cpverify.exe -mk -alg GR3411 testdoc.docx -inverted_halfbytes 0
EF41B84C17DF4166CFF80C01E38707E541BA347081404A8B1771BC37170D4DD5
>cpverify.exe -mk -alg GR3411_2012_256 testdoc.docx -inverted_halfbytes 0
178A4F63943C8F6D11BA682F2E608029AFBD00424E36313AAA77421AD4FECBEB
</code></pre>
</div></div><br /><br />Тело функции:<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
const char* GetHashOid(PCCERT_CONTEXT pCert) {
const char* pKeyAlg = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
if (strcmp(pKeyAlg, szOID_CP_GOST_R3410EL) == 0) {
return szOID_CP_GOST_R3411;
} else if (strcmp(pKeyAlg, szOID_CP_GOST_R3410_12_256) == 0) {
return szOID_CP_GOST_R3411_12_256;
}
else if (strcmp(pKeyAlg, szOID_CP_GOST_R3410_12_512) == 0) {
return szOID_CP_GOST_R3411_12_512;
}
return NULL;
}
</code></pre>
</div></div><br /><br />C моими сертификатами возвращается szOID_CP_GOST_R3411_12_256 т.е. "1.2.643.7.1.1.2.2'<br /><br />Заменил<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
if (!CadesMsgAddEnhancedSignature(hMsg, &cosignPara)) {
</code></pre>
</div></div><br />На<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &signer);
CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &coSignerBlob);
</code></pre>
</div></div><br />Но ничего не поменялось, так же создаются две подписи с неверным хешом.<br /><br />Файлы с подписями:<br />[attach]10050[/attach]<br /><br /></td></tr></table>2021-10-19T20:20:45+03:002021-10-19T20:20:45+03:00Depish<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: two_oceans <a href="/forum2/default.aspx?g=posts&m=128137#post128137"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Добрый день. Вот так интересно дополнили пример, что даже функция стала другой. Лично мне не совсем понятна эта строка:<div class="quote"><span class="quotetitle">Цитата:</span><blockquote>signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);</div></div>Позвольте тоже построить дикую теорию на этом. Смысл в том, что вероятно эта функция вернула гост-2001 вместо гост-2012. Тогда хэш был посчитан по другому алгоритму и должна была быть ошибка о несогласованности алгоритма хэша и алгоритма ключа. Однако если хэш был сохранен как значение, то длина у гост-2001 и гост-2012 256 бит одинакова, то есть значение одного можно загрузить в другой и подписать, тогда ошибки не будет, но хэш при проверке покажется неверным. Можете указать что возвратила эта функция и для ясности еще и посчитать хеши подписываемых данных утилитой<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">cpverify.exe -mk -alg GR3411 filename.txt -inverted_halfbytes 0
cpverify.exe -mk -alg GR3411_2012_256 filename.txt -inverted_halfbytes 0</code></pre>
</div></div></div></div><br /><br />Доброго времени суток!<br /><br />Вот вывод утилиты: <br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
>cpverify.exe -mk -alg GR3411 testdoc.docx -inverted_halfbytes 0
EF41B84C17DF4166CFF80C01E38707E541BA347081404A8B1771BC37170D4DD5
>cpverify.exe -mk -alg GR3411_2012_256 testdoc.docx -inverted_halfbytes 0
178A4F63943C8F6D11BA682F2E608029AFBD00424E36313AAA77421AD4FECBEB
</code></pre>
</div></div><br /><br />Тело функции:<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
const char* GetHashOid(PCCERT_CONTEXT pCert) {
const char* pKeyAlg = pCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
if (strcmp(pKeyAlg, szOID_CP_GOST_R3410EL) == 0) {
return szOID_CP_GOST_R3411;
} else if (strcmp(pKeyAlg, szOID_CP_GOST_R3410_12_256) == 0) {
return szOID_CP_GOST_R3411_12_256;
}
else if (strcmp(pKeyAlg, szOID_CP_GOST_R3410_12_512) == 0) {
return szOID_CP_GOST_R3411_12_512;
}
return NULL;
}
</code></pre>
</div></div><br /><br />C моими сертификатами возвращается szOID_CP_GOST_R3411_12_256 т.е. "1.2.643.7.1.1.2.2'<br /><br />Заменил<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
if (!CadesMsgAddEnhancedSignature(hMsg, &cosignPara)) {
</code></pre>
</div></div><br />На<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">
CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &signer);
CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &coSignerBlob);
</code></pre>
</div></div><br />Но ничего не поменялось, так же создаются две подписи с неверным хешом.<br /><br />Файлы с подписями:<br />[attach]10050[/attach]<br /><br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128137:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128013#post128013"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>p.s. <br />ошибка в 17 строке.</div></div>Спасибо порадовали. Ага, а убийца - дворецкий. Написано в теме где еще не было исходников.<br /><div class="quote"><span class="quotetitle">Автор: Depish <a href="/forum2/default.aspx?g=posts&m=128114#post128114"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128079#post128079"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>если подпись отсоединенная - то сначала её загружаем CryptMsgUpdate ( с true = целиком)<br /></div></div>Сделал как в примере но ошибка не исчезла, что я делаю не так?<br />Пример в спойлере<br />...<br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &signer);<br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &coSignerBlob);<br />...</div></div><div class="quote"><span class="quotetitle">Автор: Depish <a href="/forum2/default.aspx?g=posts&m=128116#post128116"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Проверки есть, просто я убрал их для краткости, ошибок нет и подпись создается, на выходе 2 файла что прикреплял выше<br /><br />Вот полный пример:<br />...<br /> if (!CadesMsgAddEnhancedSignature(hMsg, &cosignPara)) {<br />...<br /></div></div>Добрый день. Вот так интересно дополнили пример, что даже функция стала другой. Лично мне не совсем понятна эта строка:<div class="quote"><span class="quotetitle">Цитата:</span><blockquote>signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);</div></div>Позвольте тоже построить дикую теорию на этом. Смысл в том, что вероятно эта функция вернула гост-2001 вместо гост-2012. Тогда хэш был посчитан по другому алгоритму и должна была быть ошибка о несогласованности алгоритма хэша и алгоритма ключа. Однако если хэш был сохранен как значение, то длина у гост-2001 и гост-2012 256 бит одинакова, то есть значение одного можно загрузить в другой и подписать, тогда ошибки не будет, но хэш при проверке покажется неверным. Можете указать что возвратила эта функция и для ясности еще и посчитать хеши подписываемых данных утилитой<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">cpverify.exe -mk -alg GR3411 filename.txt -inverted_halfbytes 0
cpverify.exe -mk -alg GR3411_2012_256 filename.txt -inverted_halfbytes 0</code></pre>
</div></div></td></tr></table>2021-10-19T18:41:42+03:002021-10-19T18:41:42+03:00two_oceans<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128013#post128013"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>p.s. <br />ошибка в 17 строке.</div></div>Спасибо порадовали. Ага, а убийца - дворецкий. Написано в теме где еще не было исходников.<br /><div class="quote"><span class="quotetitle">Автор: Depish <a href="/forum2/default.aspx?g=posts&m=128114#post128114"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128079#post128079"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>если подпись отсоединенная - то сначала её загружаем CryptMsgUpdate ( с true = целиком)<br /></div></div>Сделал как в примере но ошибка не исчезла, что я делаю не так?<br />Пример в спойлере<br />...<br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &signer);<br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &coSignerBlob);<br />...</div></div><div class="quote"><span class="quotetitle">Автор: Depish <a href="/forum2/default.aspx?g=posts&m=128116#post128116"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Проверки есть, просто я убрал их для краткости, ошибок нет и подпись создается, на выходе 2 файла что прикреплял выше<br /><br />Вот полный пример:<br />...<br /> if (!CadesMsgAddEnhancedSignature(hMsg, &cosignPara)) {<br />...<br /></div></div>Добрый день. Вот так интересно дополнили пример, что даже функция стала другой. Лично мне не совсем понятна эта строка:<div class="quote"><span class="quotetitle">Цитата:</span><blockquote>signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);</div></div>Позвольте тоже построить дикую теорию на этом. Смысл в том, что вероятно эта функция вернула гост-2001 вместо гост-2012. Тогда хэш был посчитан по другому алгоритму и должна была быть ошибка о несогласованности алгоритма хэша и алгоритма ключа. Однако если хэш был сохранен как значение, то длина у гост-2001 и гост-2012 256 бит одинакова, то есть значение одного можно загрузить в другой и подписать, тогда ошибки не будет, но хэш при проверке покажется неверным. Можете указать что возвратила эта функция и для ясности еще и посчитать хеши подписываемых данных утилитой<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-markup">cpverify.exe -mk -alg GR3411 filename.txt -inverted_halfbytes 0
cpverify.exe -mk -alg GR3411_2012_256 filename.txt -inverted_halfbytes 0</code></pre>
</div></div></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128120:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128115#post128115"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Первая ошибка - нет проверок результатов функций.<br /><br />Какая функция выдаёт отказ и какую ошибку?<br /></div></div><br /><br />ping</td></tr></table>2021-10-19T13:23:58+03:002021-10-19T13:23:58+03:00Depish<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128115#post128115"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>Первая ошибка - нет проверок результатов функций.<br /><br />Какая функция выдаёт отказ и какую ошибку?<br /></div></div><br /><br />ping</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128116:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++bool CoSignMessage(/* options &opt*/ ) {<br /> if (!FileExists(opt.file_in) || !DirExists(SplitFilename(opt.file_out).path)) {<br /> cout << "File or dir not exists check file_in and file_out parameters\n";<br /> return false;<br /> }<br /> if (opt.crt_serial.empty()) {<br /> cout << "Certificate Serial empty" << endl;<br /> return false;<br /> }<br /><br /> HCERTSTORE hStoreHandle = CertOpenSystemStore(0, _TEXT("MY"));<br /><br /> // Ищем сертификат в хранилище по серийному номеру<br /> PCCERT_CONTEXT context = FindCertificate(hStoreHandle, opt.crt_serial);<br /> if (context == NULL) {<br /> cout << "Certificate has not this Serial " << endl;<br /> return false;<br /> }<br /> // Если сертификат не найден, завершаем работу<br /> if (!context) {<br /> cout << "There is no certificate with a CERT_KEY_CONTEXT_PROP_ID " << endl<br /> << "property and an AT_KEYEXCHANGE private key available." << endl<br /> << "While the message could be sign, in this case, it could" << endl<br /> << "not be verify in this program." << endl<br /> << "For more information, read the documentation <a rel="nofollow" href="http://cpdn.cryptopro.ru/"" title="http://cpdn.cryptopro.ru/"">http://cpdn.cryptopro.ru/"</a> << endl;<br /> return false;<br /> }<br /><br /> int mustFree;<br /> DWORD dwKeySpec = 0;<br /> HCRYPTPROV hProv;<br /><br /> // Получаем ссылку на закрытый ключ сертификата и дестриптор криптопровайдера<br /> if (!CryptAcquireCertificatePrivateKey(context, 0, 0, &hProv, &dwKeySpec, &mustFree)) {<br /> cout << "CryptAcquireCertificatePrivateKey() failed" << "GetLastError() = " << GetLastError() << endl;<br /> CertFreeCertificateContext(context);<br /> return false;<br /> }<br /><br /> const auto encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;<br /> HCRYPTMSG hMsg = CryptMsgOpenToDecode(encodingType, (opt.detached ? CMSG_DETACHED_FLAG : 0), 0, 0, 0, 0);<br /><br /> // Формируем данные для подписания <br /> vector<unsigned char> data;<br /> if (ReadFileToVector(opt.file_in.c_str(), data)) {<br /> cout << "ReadFileToVector() failed" << endl;<br /> return false;<br /> }<br /><br /> // Добавляем подпись в сообщение<br /> if (!CryptMsgUpdate(hMsg, &data[0], (DWORD)data.size(), TRUE)) {<br /> if (mustFree)<br /> CryptReleaseContext(hProv, 0);<br /> CertFreeCertificateContext(context);<br /> CryptMsgClose(hMsg);<br /> cout << "CryptMsgUpdate() failed in " __FUNCTION__ << endl;<br /> return false;<br /> }<br /><br /> // Задаем параметры<br /> CMSG_SIGNER_ENCODE_INFO signer = { sizeof(CMSG_SIGNER_ENCODE_INFO) };<br /> signer.pCertInfo = context->pCertInfo; // Сертификат подписчика<br /> signer.hCryptProv = hProv; // Дескриптор криптопровайдера<br /> signer.dwKeySpec = dwKeySpec;<br /> signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);<br /><br /> CADES_SIGN_PARA signPara = { sizeof(signPara) };<br /> signPara.dwCadesType = CADES_BES;<br /><br /> CADES_COSIGN_PARA cosignPara = { sizeof(cosignPara) };<br /> cosignPara.pSigner = &signer;<br /> cosignPara.pCadesSignPara = &signPara;<br /><br /> if (!CadesMsgAddEnhancedSignature(hMsg, &cosignPara)) {<br /> CertFreeCertificateContext(context);<br /> CryptReleaseContext(hProv, 0);<br /> CryptMsgClose(hMsg);<br /> std::cout << "CadesMsgAddEnhanceSignature() failed" << std::endl;<br /> return false;<br /> }<br /><br /> DWORD cbCosignedMessageBlob = 0;<br /> std::vector<unsigned char> pbCosignedMessageBlob;<br /> if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, 0, &cbCosignedMessageBlob)) {<br /> cout << "The size for the encoded BLOB is " << cbCosignedMessageBlob << '\n';<br /> pbCosignedMessageBlob.resize(cbCosignedMessageBlob);<br /> } else {<br /> cout << "Sizing of cbSignerInfo failed.\n";<br /> }<br /><br /> // Get the cosigned message BLOB.<br /> if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, &(pbCosignedMessageBlob[0]), &cbCosignedMessageBlob)) {<br /> cout << "The message was cosigned successfully. \n";<br /> } else {<br /> cout << "Sizing of cbSignerInfo failed.\n";<br /> }<br /><br /> // Сохраняем результат в файл sign.dat<br /> if (SaveVectorToFile<unsigned char>((opt.file_out + ".cosign").c_str(), pbCosignedMessageBlob)) {<br /> cout << "Signature was not saved" << endl;<br /> return false;<br /> }<br /><br /> //CadesMsgUIDisplaySignature(hMsg, 0, NULL, _TEXT("Sign"));<br /><br /> // Освобождаем ресурсы<br /> if (context)<br /> CertFreeCertificateContext(context);<br /><br />// CryptReleaseContext(hProv, 0);<br />// CertFreeCertificateContext(context);<br /><br /> return true;<br />}2021-10-19T10:26:59+03:002021-10-19T10:26:59+03:00Depishbool CoSignMessage(/* options &opt*/ ) {<br /> if (!FileExists(opt.file_in) || !DirExists(SplitFilename(opt.file_out).path)) {<br /> cout << "File or dir not exists check file_in and file_out parameters\n";<br /> return false;<br /> }<br /> if (opt.crt_serial.empty()) {<br /> cout << "Certificate Serial empty" << endl;<br /> return false;<br /> }<br /><br /> HCERTSTORE hStoreHandle = CertOpenSystemStore(0, _TEXT("MY"));<br /><br /> // Ищем сертификат в хранилище по серийному номеру<br /> PCCERT_CONTEXT context = FindCertificate(hStoreHandle, opt.crt_serial);<br /> if (context == NULL) {<br /> cout << "Certificate has not this Serial " << endl;<br /> return false;<br /> }<br /> // Если сертификат не найден, завершаем работу<br /> if (!context) {<br /> cout << "There is no certificate with a CERT_KEY_CONTEXT_PROP_ID " << endl<br /> << "property and an AT_KEYEXCHANGE private key available." << endl<br /> << "While the message could be sign, in this case, it could" << endl<br /> << "not be verify in this program." << endl<br /> << "For more information, read the documentation <a rel="nofollow" href="http://cpdn.cryptopro.ru/"" title="http://cpdn.cryptopro.ru/"">http://cpdn.cryptopro.ru/"</a> << endl;<br /> return false;<br /> }<br /><br /> int mustFree;<br /> DWORD dwKeySpec = 0;<br /> HCRYPTPROV hProv;<br /><br /> // Получаем ссылку на закрытый ключ сертификата и дестриптор криптопровайдера<br /> if (!CryptAcquireCertificatePrivateKey(context, 0, 0, &hProv, &dwKeySpec, &mustFree)) {<br /> cout << "CryptAcquireCertificatePrivateKey() failed" << "GetLastError() = " << GetLastError() << endl;<br /> CertFreeCertificateContext(context);<br /> return false;<br /> }<br /><br /> const auto encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;<br /> HCRYPTMSG hMsg = CryptMsgOpenToDecode(encodingType, (opt.detached ? CMSG_DETACHED_FLAG : 0), 0, 0, 0, 0);<br /><br /> // Формируем данные для подписания <br /> vector<unsigned char> data;<br /> if (ReadFileToVector(opt.file_in.c_str(), data)) {<br /> cout << "ReadFileToVector() failed" << endl;<br /> return false;<br /> }<br /><br /> // Добавляем подпись в сообщение<br /> if (!CryptMsgUpdate(hMsg, &data[0], (DWORD)data.size(), TRUE)) {<br /> if (mustFree)<br /> CryptReleaseContext(hProv, 0);<br /> CertFreeCertificateContext(context);<br /> CryptMsgClose(hMsg);<br /> cout << "CryptMsgUpdate() failed in " __FUNCTION__ << endl;<br /> return false;<br /> }<br /><br /> // Задаем параметры<br /> CMSG_SIGNER_ENCODE_INFO signer = { sizeof(CMSG_SIGNER_ENCODE_INFO) };<br /> signer.pCertInfo = context->pCertInfo; // Сертификат подписчика<br /> signer.hCryptProv = hProv; // Дескриптор криптопровайдера<br /> signer.dwKeySpec = dwKeySpec;<br /> signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);<br /><br /> CADES_SIGN_PARA signPara = { sizeof(signPara) };<br /> signPara.dwCadesType = CADES_BES;<br /><br /> CADES_COSIGN_PARA cosignPara = { sizeof(cosignPara) };<br /> cosignPara.pSigner = &signer;<br /> cosignPara.pCadesSignPara = &signPara;<br /><br /> if (!CadesMsgAddEnhancedSignature(hMsg, &cosignPara)) {<br /> CertFreeCertificateContext(context);<br /> CryptReleaseContext(hProv, 0);<br /> CryptMsgClose(hMsg);<br /> std::cout << "CadesMsgAddEnhanceSignature() failed" << std::endl;<br /> return false;<br /> }<br /><br /> DWORD cbCosignedMessageBlob = 0;<br /> std::vector<unsigned char> pbCosignedMessageBlob;<br /> if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, 0, &cbCosignedMessageBlob)) {<br /> cout << "The size for the encoded BLOB is " << cbCosignedMessageBlob << '\n';<br /> pbCosignedMessageBlob.resize(cbCosignedMessageBlob);<br /> } else {<br /> cout << "Sizing of cbSignerInfo failed.\n";<br /> }<br /><br /> // Get the cosigned message BLOB.<br /> if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, &(pbCosignedMessageBlob[0]), &cbCosignedMessageBlob)) {<br /> cout << "The message was cosigned successfully. \n";<br /> } else {<br /> cout << "Sizing of cbSignerInfo failed.\n";<br /> }<br /><br /> // Сохраняем результат в файл sign.dat<br /> if (SaveVectorToFile<unsigned char>((opt.file_out + ".cosign").c_str(), pbCosignedMessageBlob)) {<br /> cout << "Signature was not saved" << endl;<br /> return false;<br /> }<br /><br /> //CadesMsgUIDisplaySignature(hMsg, 0, NULL, _TEXT("Sign"));<br /><br /> // Освобождаем ресурсы<br /> if (context)<br /> CertFreeCertificateContext(context);<br /><br />// CryptReleaseContext(hProv, 0);<br />// CertFreeCertificateContext(context);<br /><br /> return true;<br />}urn:https:--www-cryptopro-ru:ftPosts:st1:meid128115:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer" width="100%"><tr><td>Первая ошибка - нет проверок результатов функций.<br /><br />Какая функция выдаёт отказ и какую ошибку?<br /></td></tr></table>2021-10-19T10:19:27+03:002021-10-19T10:19:27+03:00Андрей *<table class="content postContainer" width="100%"><tr><td>Первая ошибка - нет проверок результатов функций.<br /><br />Какая функция выдаёт отказ и какую ошибку?<br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128114:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++bool CoSignMessage(/* options &opt */) {<br /><br /> HCERTSTORE hStoreHandle = CertOpenSystemStore(0, _TEXT("MY"));<br /><br /> // Ищем сертификат в хранилище по серийному номеру<br /> PCCERT_CONTEXT context = FindCertificate(*hStoreHandle, opt.crt_serial);<br /><br /> int mustFree;<br /> DWORD dwKeySpec = 0;<br /> HCRYPTPROV hProv;<br /><br /> // Получаем ссылку на закрытый ключ сертификата и дестриптор криптопровайдера<br /> if (!CryptAcquireCertificatePrivateKey(context, 0, 0, &hProv, &dwKeySpec, &mustFree)) {<br /> cout << "CryptAcquireCertificatePrivateKey() failed" << "GetLastError() = " << GetLastError() << endl;<br /> CertFreeCertificateContext(context);<br /> return false;<br /> }<br /><br /> const auto encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;<br /> HCRYPTMSG hMsg = CryptMsgOpenToDecode(encodingType, (opt.detached ? CMSG_DETACHED_FLAG : 0), 0, 0, 0, 0);<br /><br /> // Формируем данные для подписания <br /> vector<unsigned char> data;<br /> if (ReadFileToVector(opt.file_in.c_str(), data)) {<br /> cout << "ReadFileToVector() failed" << endl;<br /> return false;<br /> }<br /><br /> // Добавляем подпись в сообщение<br /> CryptMsgUpdate(hMsg, &data[0], (DWORD)data.size(), TRUE);<br /><br /> // Задаем параметры<br /> CMSG_SIGNER_ENCODE_INFO signer = { sizeof(CMSG_SIGNER_ENCODE_INFO) };<br /> signer.pCertInfo = context->pCertInfo; // Сертификат подписчика<br /> signer.hCryptProv = hProv; // Дескриптор криптопровайдера<br /> signer.dwKeySpec = dwKeySpec;<br /> signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);<br /><br /> CADES_SIGN_PARA signPara = { sizeof(signPara) };<br /> signPara.dwCadesType = CADES_BES;<br /><br /> CADES_COSIGN_PARA cosignPara = { sizeof(cosignPara) };<br /> cosignPara.pSigner = &signer;<br /> cosignPara.pCadesSignPara = &signPara;<br /><br /> CRYPT_DATA_BLOB coSignerBlob;<br /> coSignerBlob.cbData = context->cbCertEncoded;<br /> coSignerBlob.pbData = context->pbCertEncoded;<br /><br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &signer);<br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &coSignerBlob);<br /><br /> DWORD cbCosignedMessageBlob = 0;<br /> std::vector<unsigned char> pbCosignedMessageBlob;<br /> if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, 0, &cbCosignedMessageBlob)) <br /> pbCosignedMessageBlob.resize(cbCosignedMessageBlob);<br /> <br /> // Get the cosigned message BLOB.<br /> CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, &(pbCosignedMessageBlob[0]), &cbCosignedMessageBlob);<br /><br /> // Сохраняем результат в файл sign.dat<br /> if (SaveVectorToFile<unsigned char>(("cosign.dat").c_str(), pbCosignedMessageBlob)) {<br /> cout << "Signature was not saved" << endl;<br /> return false;<br /> }<br /><br /> // Освобождаем ресурсы<br /> return true;<br />}<br />2021-10-19T10:18:16+03:002021-10-19T10:18:16+03:00Depishbool CoSignMessage(/* options &opt */) {<br /><br /> HCERTSTORE hStoreHandle = CertOpenSystemStore(0, _TEXT("MY"));<br /><br /> // Ищем сертификат в хранилище по серийному номеру<br /> PCCERT_CONTEXT context = FindCertificate(*hStoreHandle, opt.crt_serial);<br /><br /> int mustFree;<br /> DWORD dwKeySpec = 0;<br /> HCRYPTPROV hProv;<br /><br /> // Получаем ссылку на закрытый ключ сертификата и дестриптор криптопровайдера<br /> if (!CryptAcquireCertificatePrivateKey(context, 0, 0, &hProv, &dwKeySpec, &mustFree)) {<br /> cout << "CryptAcquireCertificatePrivateKey() failed" << "GetLastError() = " << GetLastError() << endl;<br /> CertFreeCertificateContext(context);<br /> return false;<br /> }<br /><br /> const auto encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;<br /> HCRYPTMSG hMsg = CryptMsgOpenToDecode(encodingType, (opt.detached ? CMSG_DETACHED_FLAG : 0), 0, 0, 0, 0);<br /><br /> // Формируем данные для подписания <br /> vector<unsigned char> data;<br /> if (ReadFileToVector(opt.file_in.c_str(), data)) {<br /> cout << "ReadFileToVector() failed" << endl;<br /> return false;<br /> }<br /><br /> // Добавляем подпись в сообщение<br /> CryptMsgUpdate(hMsg, &data[0], (DWORD)data.size(), TRUE);<br /><br /> // Задаем параметры<br /> CMSG_SIGNER_ENCODE_INFO signer = { sizeof(CMSG_SIGNER_ENCODE_INFO) };<br /> signer.pCertInfo = context->pCertInfo; // Сертификат подписчика<br /> signer.hCryptProv = hProv; // Дескриптор криптопровайдера<br /> signer.dwKeySpec = dwKeySpec;<br /> signer.HashAlgorithm.pszObjId = (LPSTR)GetHashOid(context);<br /><br /> CADES_SIGN_PARA signPara = { sizeof(signPara) };<br /> signPara.dwCadesType = CADES_BES;<br /><br /> CADES_COSIGN_PARA cosignPara = { sizeof(cosignPara) };<br /> cosignPara.pSigner = &signer;<br /> cosignPara.pCadesSignPara = &signPara;<br /><br /> CRYPT_DATA_BLOB coSignerBlob;<br /> coSignerBlob.cbData = context->cbCertEncoded;<br /> coSignerBlob.pbData = context->pbCertEncoded;<br /><br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_SIGNER, &signer);<br /> CryptMsgControl(hMsg, 0, CMSG_CTRL_ADD_CERT, &coSignerBlob);<br /><br /> DWORD cbCosignedMessageBlob = 0;<br /> std::vector<unsigned char> pbCosignedMessageBlob;<br /> if (CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, 0, &cbCosignedMessageBlob)) <br /> pbCosignedMessageBlob.resize(cbCosignedMessageBlob);<br /> <br /> // Get the cosigned message BLOB.<br /> CryptMsgGetParam(hMsg, CMSG_ENCODED_MESSAGE, 0, &(pbCosignedMessageBlob[0]), &cbCosignedMessageBlob);<br /><br /> // Сохраняем результат в файл sign.dat<br /> if (SaveVectorToFile<unsigned char>(("cosign.dat").c_str(), pbCosignedMessageBlob)) {<br /> cout << "Signature was not saved" << endl;<br /> return false;<br /> }<br /><br /> // Освобождаем ресурсы<br /> return true;<br />}<br />urn:https:--www-cryptopro-ru:ftPosts:st1:meid128079:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer" width="100%"><tr><td>если подпись отсоединенная - то сначала её загружаем CryptMsgUpdate ( с true = целиком)<br /></td></tr></table>2021-10-18T10:57:49+03:002021-10-18T10:57:49+03:00Андрей *<table class="content postContainer" width="100%"><tr><td>если подпись отсоединенная - то сначала её загружаем CryptMsgUpdate ( с true = целиком)<br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128026:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Depish <a href="/forum2/default.aspx?g=posts&m=128023#post128023"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128022#post128022"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote><br />приложить файл, файл подписи (с двумя внутри) можете?</div></div><br /><br /><br />[attach]10024[/attach][attach]10025[/attach][attach]10026[/attach]<br /><br />фаил .dat это с одной подписью а .cosign с двумя</div></div><br /><br /><br />да, хеш у второй неправильный: 3F539A213E97C802CC229D474C6AA32A825A360B2A933A949FD925208D9CE1BB<br /><br />[attach]10027[/attach]<br />[attach]10028[/attach]</td></tr></table>2021-10-14T14:18:25+03:002021-10-14T14:18:25+03:00Андрей *<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Depish <a href="/forum2/default.aspx?g=posts&m=128023#post128023"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=128022#post128022"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote><br />приложить файл, файл подписи (с двумя внутри) можете?</div></div><br /><br /><br />[attach]10024[/attach][attach]10025[/attach][attach]10026[/attach]<br /><br />фаил .dat это с одной подписью а .cosign с двумя</div></div><br /><br /><br />да, хеш у второй неправильный: 3F539A213E97C802CC229D474C6AA32A825A360B2A933A949FD925208D9CE1BB<br /><br />[attach]10027[/attach]<br />[attach]10028[/attach]</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid128025:1Добавление второй подписи CAdES-BES в уже подписаный фаил на C++<table class="content postContainer" width="100%"><tr><td>Вот как пример.. исправляйте у себя.<br /><br /><br /><br /> </td></tr></table>2021-10-14T14:15:02+03:002021-10-14T14:15:02+03:00Андрей *<table class="content postContainer" width="100%"><tr><td>Вот как пример.. исправляйте у себя.<br /><br /><br /><br /> </td></tr></table>