Atom Лента - Форум КриптоПро - Тема:Получение приватного ключа и подписание данных через CryptoAPI - 10Форум КриптоПро - Atom Лентаurn:https:--www-cryptopro-ru:AtomLenta:ForumKriptoPro:Tema:PoluchenieprivatnogokljuchaipodpisaniedannykhcherezCryptoAPI-10:1Copyright 2024 Форум КриптоПро2024-03-29T14:25:32Zhttps://www.cryptopro.ru/forum2/Images/YAFLogo.pngForum Adminhttps://www.cryptopro.ruforum@cryptopro.rumafofhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59183&name=mafofmafofhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59183&name=mafofАндрей *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=Андрей *Андрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *mafofhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=59183&name=mafofYetAnotherForum.NETurn:https:--www-cryptopro-ru:ftPosts:st1:meid124263:1Получение приватного ключа и подписание данных через CryptoAPI<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=124260#post124260"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>И для какой задачи потребовалось вызывать низкоуровневые функции?<br /><br /><a rel="nofollow" href="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990" title="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990">Здесь</a> есть пример, цикл только убрать.</div></div><br /><br />Спасибо, буду пытаться вникать дальше, а нужно для создание пакета на Node.js в внутренний продукт.<br /><br /></td></tr></table>2021-04-17T19:58:40+03:002021-04-17T19:58:40+03:00mafof<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: Андрей * <a href="/forum2/default.aspx?g=posts&m=124260#post124260"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>И для какой задачи потребовалось вызывать низкоуровневые функции?<br /><br /><a rel="nofollow" href="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990" title="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990">Здесь</a> есть пример, цикл только убрать.</div></div><br /><br />Спасибо, буду пытаться вникать дальше, а нужно для создание пакета на Node.js в внутренний продукт.<br /><br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid124262:1Получение приватного ключа и подписание данных через CryptoAPI<table class="content postContainer" width="100%"><tr><td>SDK:<br />\samples\CSP\SignUtility\SignUtility.c готовый пример утилиты<br />(CryptSignMessage\CryptVerifyDetachedMessageSignature)<br /></td></tr></table>2021-04-17T19:41:33+03:002021-04-17T19:41:33+03:00Андрей *<table class="content postContainer" width="100%"><tr><td>SDK:<br />\samples\CSP\SignUtility\SignUtility.c готовый пример утилиты<br />(CryptSignMessage\CryptVerifyDetachedMessageSignature)<br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid124261:1Получение приватного ключа и подписание данных через CryptoAPI<table class="content postContainer_Alt" width="100%"><tr><td>SDK:<br />\samples\CSP\SigningHash\SigningHash.c<br /><br /></td></tr></table>2021-04-17T19:36:28+03:002021-04-17T19:36:28+03:00Андрей *<table class="content postContainer_Alt" width="100%"><tr><td>SDK:<br />\samples\CSP\SigningHash\SigningHash.c<br /><br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid124260:1Получение приватного ключа и подписание данных через CryptoAPI<table class="content postContainer" width="100%"><tr><td>И для какой задачи потребовалось вызывать низкоуровневые функции?<br /><br /><a rel="nofollow" href="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990" title="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990">Здесь</a> есть пример, цикл только убрать.</td></tr></table>2021-04-17T19:34:59+03:002021-04-17T19:34:59+03:00Андрей *<table class="content postContainer" width="100%"><tr><td>И для какой задачи потребовалось вызывать низкоуровневые функции?<br /><br /><a rel="nofollow" href="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990" title="https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=119990#post119990">Здесь</a> есть пример, цикл только убрать.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid124259:1Получение приватного ключа и подписание данных через CryptoAPI<table class="content postContainer_Alt" width="100%"><tr><td>Здравствуйте.<br /><br />Что мешает посмотреть в SDK\MSDN?<br /><br />CertSetCertificateContextProperty - не нужен<br /><br /><div class="quote"><span class="quotetitle">Цитата:</span><blockquote><br /> Меня немного смущает что программа не требует того что бы я воткнул в компьютер USB токен, и не ввел пин код...</div></div><br /><br />Нет необходимости - не вызывается функция для обращения к ЗК.</td></tr></table>2021-04-17T19:27:37+03:002021-04-17T19:27:37+03:00Андрей *<table class="content postContainer_Alt" width="100%"><tr><td>Здравствуйте.<br /><br />Что мешает посмотреть в SDK\MSDN?<br /><br />CertSetCertificateContextProperty - не нужен<br /><br /><div class="quote"><span class="quotetitle">Цитата:</span><blockquote><br /> Меня немного смущает что программа не требует того что бы я воткнул в компьютер USB токен, и не ввел пин код...</div></div><br /><br />Нет необходимости - не вызывается функция для обращения к ЗК.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid124258:1Получение приватного ключа и подписание данных через CryptoAPI<table class="content postContainer" width="100%"><tr><td>Всем привет, пытаюсь реализовать функционал подписание данных, но наткнулся на проблему где не понимаю как мне взять приватный ключ из сертификата установленного в сертификаты пользователя -> личные сертификаты. Насколько я понимаю для подписание данных мне нужно использовать метод <em>CryptHashData</em>, в 1-ом аргументе которого необходимо получить переменную типа <em>HCRYPTHASH</em>, которую можно получить через метод <em>CryptCreateHash</em> в 3-ем аргументе которого необходимо получить переменную заполненной структурой <em>HCRYPTKEY</em>, который как я понимаю является приватный ключ из сертификата.<br />На сколько я понимаю что, что бы получить приватный ключ, необходимо получить дескриптор сертификата и потом связать полученный дескриптор сертификата, с дескриптором криптопровайдера через метод <em>CertSetCertificateContextProperty</em>, и потом получить ключ через метод <em>CryptGetUserKey</em>... Но при попытке так сделать, я получаю ошибку <em>NTE_NO_KEY </em> от метода <em>CryptGetUserKey</em>, и не понимаю почему это так происходит...<br />Вот мой код:<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-cpp">
// Получаю дескриптор криптопровайдера =>
HCRYPTPROV phProv;
if (!CryptAcquireContext(&phProv, NULL, L"Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (NTE_KEYSET_NOT_DEF == GetLastError())
{
printf("provider is not found");
}
else {
std::cout << GetLastError();
}
return 1;
}
// Открываю системное хранилище сертификатов =>
HCERTSTORE hStoreHandle;
hStoreHandle = CertOpenSystemStore(phProv, L"MY");
if (hStoreHandle)
{
printf("The MY store is open. \n");
}
else
{
printf("Error getting store handle.");
}
// Получаю сертификат из списка сертификатов =>
PCCERT_CONTEXT pRecipientCert = NULL;
DWORD PropId = CERT_KEY_PROV_INFO_PROP_ID;
pRecipientCert = CertFindCertificateInStore(
hStoreHandle,
0,
0,
CERT_FIND_PROPERTY,
&PropId,
pRecipientCert
);
// Пробую получить дескриптор ключа из сертификата =>
HCRYPTKEY phUserKey;
if (CertSetCertificateContextProperty(
pRecipientCert,
CERT_SET_KEY_PROV_HANDLE_PROP_ID,
0,
&phProv
)
)
{
std::cout << "Success CertSetCertificateContextProperty" << std::endl;
}
if (CryptGetUserKey(phProv, AT_KEYEXCHANGE, &phUserKey))
{
std::cout << "Success CryptGetUserKey" << std::endl;
}
else
{
if(NTE_NO_KEY == GetLastError())
std::cout << "[ERROR] The key requested by the dwKeySpec parameter does not exist." << std::endl; // Тут я получаю эту ошибку...
}
// Дальше должен быть код где я использую методы CryptCreateHash, и CryptHashData...
</code></pre>
</div></div><br /><br />Я не могу понять почему мой код не работает.... Может быть у кого то есть пример кода как он подписывает данные, через ключ сертификата...<br /><br />P.S. Метод <em>CertFindCertificateInStore</em> точно возвращает нужный сертификат который содержит закрытый ключ для этого сертификата.<br /><br />P.S. Меня немного смущает что программа не требует того что бы я воткнул в компьютер USB токен, и не ввел пин код...</td></tr></table>2021-04-17T19:19:29+03:002021-04-17T19:19:29+03:00mafof<table class="content postContainer" width="100%"><tr><td>Всем привет, пытаюсь реализовать функционал подписание данных, но наткнулся на проблему где не понимаю как мне взять приватный ключ из сертификата установленного в сертификаты пользователя -> личные сертификаты. Насколько я понимаю для подписание данных мне нужно использовать метод <em>CryptHashData</em>, в 1-ом аргументе которого необходимо получить переменную типа <em>HCRYPTHASH</em>, которую можно получить через метод <em>CryptCreateHash</em> в 3-ем аргументе которого необходимо получить переменную заполненной структурой <em>HCRYPTKEY</em>, который как я понимаю является приватный ключ из сертификата.<br />На сколько я понимаю что, что бы получить приватный ключ, необходимо получить дескриптор сертификата и потом связать полученный дескриптор сертификата, с дескриптором криптопровайдера через метод <em>CertSetCertificateContextProperty</em>, и потом получить ключ через метод <em>CryptGetUserKey</em>... Но при попытке так сделать, я получаю ошибку <em>NTE_NO_KEY </em> от метода <em>CryptGetUserKey</em>, и не понимаю почему это так происходит...<br />Вот мой код:<br /><div class="code"><strong>Код:</strong><div class="innercode"><pre class="line-numbers"><code class="language-cpp">
// Получаю дескриптор криптопровайдера =>
HCRYPTPROV phProv;
if (!CryptAcquireContext(&phProv, NULL, L"Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider", PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (NTE_KEYSET_NOT_DEF == GetLastError())
{
printf("provider is not found");
}
else {
std::cout << GetLastError();
}
return 1;
}
// Открываю системное хранилище сертификатов =>
HCERTSTORE hStoreHandle;
hStoreHandle = CertOpenSystemStore(phProv, L"MY");
if (hStoreHandle)
{
printf("The MY store is open. \n");
}
else
{
printf("Error getting store handle.");
}
// Получаю сертификат из списка сертификатов =>
PCCERT_CONTEXT pRecipientCert = NULL;
DWORD PropId = CERT_KEY_PROV_INFO_PROP_ID;
pRecipientCert = CertFindCertificateInStore(
hStoreHandle,
0,
0,
CERT_FIND_PROPERTY,
&PropId,
pRecipientCert
);
// Пробую получить дескриптор ключа из сертификата =>
HCRYPTKEY phUserKey;
if (CertSetCertificateContextProperty(
pRecipientCert,
CERT_SET_KEY_PROV_HANDLE_PROP_ID,
0,
&phProv
)
)
{
std::cout << "Success CertSetCertificateContextProperty" << std::endl;
}
if (CryptGetUserKey(phProv, AT_KEYEXCHANGE, &phUserKey))
{
std::cout << "Success CryptGetUserKey" << std::endl;
}
else
{
if(NTE_NO_KEY == GetLastError())
std::cout << "[ERROR] The key requested by the dwKeySpec parameter does not exist." << std::endl; // Тут я получаю эту ошибку...
}
// Дальше должен быть код где я использую методы CryptCreateHash, и CryptHashData...
</code></pre>
</div></div><br /><br />Я не могу понять почему мой код не работает.... Может быть у кого то есть пример кода как он подписывает данные, через ключ сертификата...<br /><br />P.S. Метод <em>CertFindCertificateInStore</em> точно возвращает нужный сертификат который содержит закрытый ключ для этого сертификата.<br /><br />P.S. Меня немного смущает что программа не требует того что бы я воткнул в компьютер USB токен, и не ввел пин код...</td></tr></table>