Atom Лента - Форум КриптоПро - Тема:Почему CryptSignHash всегда false? - 10Форум КриптоПро - Atom Лентаurn:https:--www-cryptopro-ru:AtomLenta:ForumKriptoPro:Tema:PochemuCryptSignHashvsegdafalse?-10:1Copyright 2024 Форум КриптоПро2024-03-29T14:47:32Zhttps://www.cryptopro.ru/forum2/Images/YAFLogo.pngForum Adminhttps://www.cryptopro.ruforum@cryptopro.ruAANNTTOONNhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=53446&name=AANNTTOONNAANNTTOONNhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=53446&name=AANNTTOONNtwo_oceanshttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=36490&name=two_oceansАндрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Андрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *AANNTTOONNhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=53446&name=AANNTTOONNAANNTTOONNhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=53446&name=AANNTTOONNАндрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *Андрей *https://www.cryptopro.ru/forum2/default.aspx?g=profile&u=15008&name=Андрей *AANNTTOONNhttps://www.cryptopro.ru/forum2/default.aspx?g=profile&u=53446&name=AANNTTOONNYetAnotherForum.NETurn:https:--www-cryptopro-ru:ftPosts:st1:meid105069:1Почему CryptSignHash всегда false?<table class="content postContainer_Alt" width="100%"><tr><td>спасибо. решил противоречие перезаказом сертификата и изменением сигнатуры метода.</td></tr></table>2019-07-17T22:42:20+03:002019-07-17T22:42:20+03:00AANNTTOONN<table class="content postContainer_Alt" width="100%"><tr><td>спасибо. решил противоречие перезаказом сертификата и изменением сигнатуры метода.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid105001:1Почему CryptSignHash всегда false?<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>2) CryptoAPI.CryptSignHash(handle, 0, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen) - если вместо CryptoAPI.AT_KEYEXCHANGE - 0, или CryptoAPI.AT_SIGNATURE - ничего не меняется: false</div></div>Прочитайте пожалуйста справку внимательно, <strong>в Вашем коде уже получено функцией CryptAcquireCertificatePrivateKey значение pdwKeySpec</strong> связанное с ключом выбранного сертификата. Его и нужно передать в CryptSignHash вместо жестко прописанного AT_KEYEXCHANGE или AT_SIGNATURE.<br /><br />Смысл в том, что хотя на практике гост это почти не встречается, но в одном контейнере может быть 2 ключа и соответственно к контейнеру можно привязать 2 сертификата. Если в такой ситуации выбирать dwKeySpec наугад, то неизвестно подпишите ли тем сертификатом, что выбрали из хранилища. Маловероятная ситуация, но лучше сразу прикрыть слабое место программы.<br /><br />Подбирать может потребоваться только если сначала получали имя контейнера для сертификата (тут dwKeySpec насколько помню не возвращается), затем получали контейнер по имени. При переборе желательно сверить открытый ключ из контейнера и из сертификата на соответствие. В Вашем случае (получение контейнера через CryptAcquireCertificatePrivateKey) перебор не нужен, dwKeySpec известно, открытый ключ сверяется внутри функции CryptAcquireCertificatePrivateKey при указании соответствующего флага.<br /><br /><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>GetLastError выдает ахинею типа "0"</div></div>По ошибке: для получения длины нужно передать вместо pbSignature пустой указатель IntPtr.Zero (то есть null), иначе функция CryptSignHash будет трактовать длину как уже указанную Вами, проверять указатель на буфер через IsBadWritePtr и споткнется на значении длины 0. Не то чтобы я смотрел код самой функции, но это базовая логика во всех WinApi функциях связанных с получением значений/длины. Передаете вместо буфера null в случае успеха записывается требуемая длина буфер, передаете буфер и длину буфера - записывается использованная длина буфера.<br /><br />Предположительно при этом внутренний вызов IsBadWritePtr с нулевой длиной буфера перезапишет код ошибки нулем. Заметьте: если Вы запросите длину, а потом подпишите, то у пользователя дважды запросит пин-код на контейнер (один раз для запроса длины, второй раз для собственно подписи).<br /><br />Либо ставьте предопределенную для алгоритма длину сразу (без дополнительного запроса длины), 130 байтов достаточно для гост-2001 и гост-2012 256 бит - тогда пользователя не будет дважды спрашивать пин-код. В моей программе используется такое решение, потому что немного странно запрашивать пин-код чтобы узнать длину фиксированную для алгоритмов гост.</td></tr></table>2019-07-17T08:12:24+03:002019-07-17T08:12:24+03:00two_oceans<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>2) CryptoAPI.CryptSignHash(handle, 0, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen) - если вместо CryptoAPI.AT_KEYEXCHANGE - 0, или CryptoAPI.AT_SIGNATURE - ничего не меняется: false</div></div>Прочитайте пожалуйста справку внимательно, <strong>в Вашем коде уже получено функцией CryptAcquireCertificatePrivateKey значение pdwKeySpec</strong> связанное с ключом выбранного сертификата. Его и нужно передать в CryptSignHash вместо жестко прописанного AT_KEYEXCHANGE или AT_SIGNATURE.<br /><br />Смысл в том, что хотя на практике гост это почти не встречается, но в одном контейнере может быть 2 ключа и соответственно к контейнеру можно привязать 2 сертификата. Если в такой ситуации выбирать dwKeySpec наугад, то неизвестно подпишите ли тем сертификатом, что выбрали из хранилища. Маловероятная ситуация, но лучше сразу прикрыть слабое место программы.<br /><br />Подбирать может потребоваться только если сначала получали имя контейнера для сертификата (тут dwKeySpec насколько помню не возвращается), затем получали контейнер по имени. При переборе желательно сверить открытый ключ из контейнера и из сертификата на соответствие. В Вашем случае (получение контейнера через CryptAcquireCertificatePrivateKey) перебор не нужен, dwKeySpec известно, открытый ключ сверяется внутри функции CryptAcquireCertificatePrivateKey при указании соответствующего флага.<br /><br /><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>GetLastError выдает ахинею типа "0"</div></div>По ошибке: для получения длины нужно передать вместо pbSignature пустой указатель IntPtr.Zero (то есть null), иначе функция CryptSignHash будет трактовать длину как уже указанную Вами, проверять указатель на буфер через IsBadWritePtr и споткнется на значении длины 0. Не то чтобы я смотрел код самой функции, но это базовая логика во всех WinApi функциях связанных с получением значений/длины. Передаете вместо буфера null в случае успеха записывается требуемая длина буфер, передаете буфер и длину буфера - записывается использованная длина буфера.<br /><br />Предположительно при этом внутренний вызов IsBadWritePtr с нулевой длиной буфера перезапишет код ошибки нулем. Заметьте: если Вы запросите длину, а потом подпишите, то у пользователя дважды запросит пин-код на контейнер (один раз для запроса длины, второй раз для собственно подписи).<br /><br />Либо ставьте предопределенную для алгоритма длину сразу (без дополнительного запроса длины), 130 байтов достаточно для гост-2001 и гост-2012 256 бит - тогда пользователя не будет дважды спрашивать пин-код. В моей программе используется такое решение, потому что немного странно запрашивать пин-код чтобы узнать длину фиксированную для алгоритмов гост.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104997:1Почему CryptSignHash всегда false?<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>1) Тестовый сертификат: CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru</div></div><br /><br />Это сертфикат тестового УЦ.<br />Где клиентский сертификат?<br /><br /></td></tr></table>2019-07-16T21:06:28+03:002019-07-16T21:06:28+03:00Андрей *<table class="content postContainer_Alt" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>1) Тестовый сертификат: CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru</div></div><br /><br />Это сертфикат тестового УЦ.<br />Где клиентский сертификат?<br /><br /></td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104996:1Почему CryptSignHash всегда false?<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>1) Тестовый сертификат: CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru<br />2) CryptoAPI.CryptSignHash(handle, 0, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen) - если вместо CryptoAPI.AT_KEYEXCHANGE - 0, или CryptoAPI.AT_SIGNATURE - ничего не меняется: false</div></div><br /><br />КриптоПРО CSP\Сервис\Протестировать\По сертификату<br /><br />Алгоритм у сертификата ГОСТ-2001?<br />Ошибок нет? <br /><br />Если всё нормально - смотрим внимательно код и описание функций.</td></tr></table>2019-07-16T21:05:43+03:002019-07-16T21:05:43+03:00Андрей *<table class="content postContainer" width="100%"><tr><td><div class="quote"><span class="quotetitle">Автор: AANNTTOONN <a href="/forum2/default.aspx?g=posts&m=104995#post104995"><img src="/forum2/Themes/soclean/icon_latest_reply.gif" title="Перейти к цитате" alt="Перейти к цитате" /></a></span><blockquote>1) Тестовый сертификат: CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru<br />2) CryptoAPI.CryptSignHash(handle, 0, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen) - если вместо CryptoAPI.AT_KEYEXCHANGE - 0, или CryptoAPI.AT_SIGNATURE - ничего не меняется: false</div></div><br /><br />КриптоПРО CSP\Сервис\Протестировать\По сертификату<br /><br />Алгоритм у сертификата ГОСТ-2001?<br />Ошибок нет? <br /><br />Если всё нормально - смотрим внимательно код и описание функций.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104995:1Почему CryptSignHash всегда false?<table class="content postContainer_Alt" width="100%"><tr><td>1) Тестовый сертификат: CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru<br />2) CryptoAPI.CryptSignHash(handle, 0, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen) - если вместо CryptoAPI.AT_KEYEXCHANGE - 0, или CryptoAPI.AT_SIGNATURE - ничего не меняется: false</td></tr></table>2019-07-16T20:10:40+03:002019-07-16T20:10:40+03:00AANNTTOONN<table class="content postContainer_Alt" width="100%"><tr><td>1) Тестовый сертификат: CN=CRYPTO-PRO Test Center 2, O=CRYPTO-PRO LLC, L=Moscow, C=RU, E=support@cryptopro.ru<br />2) CryptoAPI.CryptSignHash(handle, 0, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen) - если вместо CryptoAPI.AT_KEYEXCHANGE - 0, или CryptoAPI.AT_SIGNATURE - ничего не меняется: false</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104994:1Почему CryptSignHash всегда false?<table class="content postContainer" width="100%"><tr><td>По сути молчит. Может я неверно настроил маршаллинг, но GetLastError выдает ахинею типа "0" - вот мое исполнение:<br />[DllImport("kernel32.dll", EntryPoint = "GetLastError")]<br />public static extern uint GetLastError();</td></tr></table>2019-07-16T20:02:41+03:002019-07-16T20:02:41+03:00AANNTTOONN<table class="content postContainer" width="100%"><tr><td>По сути молчит. Может я неверно настроил маршаллинг, но GetLastError выдает ахинею типа "0" - вот мое исполнение:<br />[DllImport("kernel32.dll", EntryPoint = "GetLastError")]<br />public static extern uint GetLastError();</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104993:1Почему CryptSignHash всегда false?<table class="content postContainer_Alt" width="100%"><tr><td>pSignerCert и 32798 /*CALG_GR3411*/ <br /><br />соответствуют действительности или сертификат с ГОСТ-2012?<br /><br />CryptoAPI.AT_KEYEXCHANGE - а если его не будет? Необходимо либо требовать такое условие работы кода, либо в коде обращаться и к ключу подписи, если ключа обмена нет.</td></tr></table>2019-07-16T20:02:10+03:002019-07-16T20:02:10+03:00Андрей *<table class="content postContainer_Alt" width="100%"><tr><td>pSignerCert и 32798 /*CALG_GR3411*/ <br /><br />соответствуют действительности или сертификат с ГОСТ-2012?<br /><br />CryptoAPI.AT_KEYEXCHANGE - а если его не будет? Необходимо либо требовать такое условие работы кода, либо в коде обращаться и к ключу подписи, если ключа обмена нет.</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104992:1Почему CryptSignHash всегда false?<table class="content postContainer" width="100%"><tr><td>Здравствуйте.<br /><br />GetLastError молчит?</td></tr></table>2019-07-16T19:50:35+03:002019-07-16T19:50:35+03:00Андрей *<table class="content postContainer" width="100%"><tr><td>Здравствуйте.<br /><br />GetLastError молчит?</td></tr></table>urn:https:--www-cryptopro-ru:ftPosts:st1:meid104988:1Почему CryptSignHash всегда false?<table class="content postContainer_Alt" width="100%"><tr><td>Добрый день!<br /><br />Проект на C#. Использую pinvoke. Привожу код, в котором CryptSignHash всегда false. Прошу подсказать в чем проблема.<br /><br /><div class="quote"><span class="quotetitle">Цитата:</span><blockquote><br /> // Открываем хранилище сертификатов <br /> var hStoreHandle = CryptoAPI.CertOpenStore(CryptoAPI.CERT_STORE_PROV_SYSTEM, 0, (IntPtr)0, CryptoAPI.CERT_SYSTEM_STORE_CURRENT_USER, "MY");<br /> if (hStoreHandle != null)<br /> {<br /> Console.WriteLine($"Хендл хранилища сертификатов: {hStoreHandle.ToString()}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /><br /> //получаем указатель на сертификат<br /> var pSignerCert = CryptoAPI.CertFindCertificateInStore(hStoreHandle, CryptoAPI.MY_TYPE, 0, CryptoAPI.CERT_FIND_SUBJECT_STR, null, (IntPtr)0);<br /> if (pSignerCert != null)<br /> {<br /> <br /> Console.WriteLine($"Хендл сертификата: {pSignerCert}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /><br /> // через функцию CryptAcquireCertificatePrivateKey получаем доступ к CSP<br /> IntPtr phCryptProv = (IntPtr)0;<br /> Int32 pdwKeySpec = 0;<br /> bool pfCallerFreeProv = false;<br /> if (CryptoAPI.CryptAcquireCertificatePrivateKey(pSignerCert, 0, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerFreeProv))<br /> {<br /> Console.WriteLine($"Дескриптор: {phCryptProv.ToString()}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /> // сообщение<br /> string massage = "тут у нас исходный текст подписанного сообщения";<br /> byte[] pbMessage = System.Text.Encoding.UTF8.GetBytes(massage);<br /> Int32 cbMessage = pbMessage.Length;<br /> // base64 подписанного сообщения <br /> string massage_sign = "MIICOQYJKoZIhvcNAQcCoIICKjCCAiYCAQExDDAKBgYqhQMCAgkFADALBgkqhkiG9w0BBwExggIEMIICAAIBATBzMGUxIDAeBgkqhkiG9w0BCQEWEWluZm9AY3J5cHRvcHJvLnJ1MQswCQYDVQQGEwJSVTETMBEGA1UEChMKQ1JZUFRPLVBSTzEfMB0GA1UEAxMWVGVzdCBDZW50ZXIgQ1JZUFRPLVBSTwIKZTIq5AACAAQ+1DAKBgYqhQMCAgkFAKCCASowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTMwNTIxMDY0NTQ4WjAvBgkqhkiG9w0BCQQxIgQgjw/LhkSZj8f2gna5q4fu4mAPjGwX7jUSfjYbO8Sm4Dwwgb4GCyqGSIb3DQEJEAIvMYGuMIGrMIGoMIGlMAgGBiqFAwICCQQgoWW4uwCURIWOSFtKX308YR7jXyGHH/1y2MDECzxn7FIwdzBppGcwZTEgMB4GCSqGSIb3DQEJARYRaW5mb0BjcnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMRMwEQYDVQQKEwpDUllQVE8tUFJPMR8wHQYDVQQDExZUZXN0IENlbnRlciBDUllQVE8tUFJPAgplMirkAAIABD7UMAoGBiqFAwICEwUABECTQoUA/SuSEEh7h+KudbAQKKMmrzvXDp62N79u42WcvxYqB272qg5SIz7Y+OZ1mcQSQeDCYX3aAhKJBtrL9qYX";<br /> byte[] pbArray = Convert.FromBase64String(massage_sign);<br /> Int32 cbArray = pbArray.Length;<br /><br /> //создаем пустой hash объект<br /> IntPtr handle = IntPtr.Zero;<br /> if (CryptoAPI.CryptCreateHash(phCryptProv, 32798 /*CALG_GR3411*/, IntPtr.Zero, 0, ref handle))<br /> {<br /> Console.WriteLine($"Пустой hash: {handle.ToString()}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /> // Вычисляем hash для нашего сообщения<br /> if (CryptoAPI.CryptHashData(handle, pbMessage, (int)pbMessage.Length, 0))<br /> {<br /> int i = 0;<br /> foreach (var el in pbMessage)<br /> {<br /> Console.WriteLine($"Hash c данными: {i} - {el.ToString()}");<br /> i++;<br /> }<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /> // Переменные для указателя и длины подписи<br /> uint pdwSigLen = 0;<br /> byte[] pbSignature = new byte[pdwSigLen];<br /> <br /> if (CryptoAPI.CryptSignHash(handle, CryptoAPI.AT_KEYEXCHANGE, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen))<br /> {<br /> Console.WriteLine($"Длина подписи: {pdwSigLen}");<br /> }<br /> else<br /> { <br /> Console.WriteLine(CryptoAPI.GetLastError().ToString());<br /> }<br /></div></div><br /><br />Уж рядил и так и сяк, а CryptSignHash всегда false. В чем дело?</td></tr></table>2019-07-16T19:04:59+03:002019-07-16T19:04:59+03:00AANNTTOONN<table class="content postContainer_Alt" width="100%"><tr><td>Добрый день!<br /><br />Проект на C#. Использую pinvoke. Привожу код, в котором CryptSignHash всегда false. Прошу подсказать в чем проблема.<br /><br /><div class="quote"><span class="quotetitle">Цитата:</span><blockquote><br /> // Открываем хранилище сертификатов <br /> var hStoreHandle = CryptoAPI.CertOpenStore(CryptoAPI.CERT_STORE_PROV_SYSTEM, 0, (IntPtr)0, CryptoAPI.CERT_SYSTEM_STORE_CURRENT_USER, "MY");<br /> if (hStoreHandle != null)<br /> {<br /> Console.WriteLine($"Хендл хранилища сертификатов: {hStoreHandle.ToString()}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /><br /> //получаем указатель на сертификат<br /> var pSignerCert = CryptoAPI.CertFindCertificateInStore(hStoreHandle, CryptoAPI.MY_TYPE, 0, CryptoAPI.CERT_FIND_SUBJECT_STR, null, (IntPtr)0);<br /> if (pSignerCert != null)<br /> {<br /> <br /> Console.WriteLine($"Хендл сертификата: {pSignerCert}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /><br /> // через функцию CryptAcquireCertificatePrivateKey получаем доступ к CSP<br /> IntPtr phCryptProv = (IntPtr)0;<br /> Int32 pdwKeySpec = 0;<br /> bool pfCallerFreeProv = false;<br /> if (CryptoAPI.CryptAcquireCertificatePrivateKey(pSignerCert, 0, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerFreeProv))<br /> {<br /> Console.WriteLine($"Дескриптор: {phCryptProv.ToString()}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /> // сообщение<br /> string massage = "тут у нас исходный текст подписанного сообщения";<br /> byte[] pbMessage = System.Text.Encoding.UTF8.GetBytes(massage);<br /> Int32 cbMessage = pbMessage.Length;<br /> // base64 подписанного сообщения <br /> string massage_sign = "MIICOQYJKoZIhvcNAQcCoIICKjCCAiYCAQExDDAKBgYqhQMCAgkFADALBgkqhkiG9w0BBwExggIEMIICAAIBATBzMGUxIDAeBgkqhkiG9w0BCQEWEWluZm9AY3J5cHRvcHJvLnJ1MQswCQYDVQQGEwJSVTETMBEGA1UEChMKQ1JZUFRPLVBSTzEfMB0GA1UEAxMWVGVzdCBDZW50ZXIgQ1JZUFRPLVBSTwIKZTIq5AACAAQ+1DAKBgYqhQMCAgkFAKCCASowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTMwNTIxMDY0NTQ4WjAvBgkqhkiG9w0BCQQxIgQgjw/LhkSZj8f2gna5q4fu4mAPjGwX7jUSfjYbO8Sm4Dwwgb4GCyqGSIb3DQEJEAIvMYGuMIGrMIGoMIGlMAgGBiqFAwICCQQgoWW4uwCURIWOSFtKX308YR7jXyGHH/1y2MDECzxn7FIwdzBppGcwZTEgMB4GCSqGSIb3DQEJARYRaW5mb0BjcnlwdG9wcm8ucnUxCzAJBgNVBAYTAlJVMRMwEQYDVQQKEwpDUllQVE8tUFJPMR8wHQYDVQQDExZUZXN0IENlbnRlciBDUllQVE8tUFJPAgplMirkAAIABD7UMAoGBiqFAwICEwUABECTQoUA/SuSEEh7h+KudbAQKKMmrzvXDp62N79u42WcvxYqB272qg5SIz7Y+OZ1mcQSQeDCYX3aAhKJBtrL9qYX";<br /> byte[] pbArray = Convert.FromBase64String(massage_sign);<br /> Int32 cbArray = pbArray.Length;<br /><br /> //создаем пустой hash объект<br /> IntPtr handle = IntPtr.Zero;<br /> if (CryptoAPI.CryptCreateHash(phCryptProv, 32798 /*CALG_GR3411*/, IntPtr.Zero, 0, ref handle))<br /> {<br /> Console.WriteLine($"Пустой hash: {handle.ToString()}");<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /> // Вычисляем hash для нашего сообщения<br /> if (CryptoAPI.CryptHashData(handle, pbMessage, (int)pbMessage.Length, 0))<br /> {<br /> int i = 0;<br /> foreach (var el in pbMessage)<br /> {<br /> Console.WriteLine($"Hash c данными: {i} - {el.ToString()}");<br /> i++;<br /> }<br /> }<br /> else<br /> {<br /> var er = CryptoAPI.GetLastError();<br /> Console.WriteLine(er.ToString());<br /> }<br /> // Переменные для указателя и длины подписи<br /> uint pdwSigLen = 0;<br /> byte[] pbSignature = new byte[pdwSigLen];<br /> <br /> if (CryptoAPI.CryptSignHash(handle, CryptoAPI.AT_KEYEXCHANGE, IntPtr.Zero, 0, ref pbSignature, ref pdwSigLen))<br /> {<br /> Console.WriteLine($"Длина подписи: {pdwSigLen}");<br /> }<br /> else<br /> { <br /> Console.WriteLine(CryptoAPI.GetLastError().ToString());<br /> }<br /></div></div><br /><br />Уж рядил и так и сяк, а CryptSignHash всегда false. В чем дело?</td></tr></table>