Статус: Новичок
Группы: Участники
Зарегистрирован: 23.11.2014(UTC) Сообщений: 4 
|
У меня есть вот такой нехитрый работающий пример подписи строки на C#: Код:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
namespace Test1
{
class Program
{
[StructLayout(LayoutKind.Sequential)]
struct CRYPTOAPI_BLOB
{
public Int32 cbData;
public IntPtr pbData;
}
[StructLayout(LayoutKind.Sequential)]
struct CRYPT_ALGORITHM_IDENTIFIER
{
[MarshalAs(UnmanagedType.LPStr)]
public String pszObjId;
public CRYPTOAPI_BLOB Parameters;
}
[StructLayout(LayoutKind.Sequential)]
struct CRYPT_SIGN_MESSAGE_PARA
{
public Int32 cbSize;
public Int32 dwMsgEncodingType;
public IntPtr pSigningCert;
public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
public IntPtr pvHashAuxInfo;
public Int32 cMsgCert;
public IntPtr rgpMsgCert;
public Int32 cMsgCrl;
public IntPtr rgpMsgCrl;
public Int32 cAuthAttr;
public IntPtr rgAuthAttr;
public Int32 cUnauthAttr;
public IntPtr rgUnauthAttr;
public Int32 dwFlags;
public Int32 dwInnerContentType;
}
[DllImport("Crypt32.dll", SetLastError = true)]
static extern Boolean CryptSignMessage(
ref CRYPT_SIGN_MESSAGE_PARA pSignPara,
Boolean fDetachedSignature,
Int32 cToBeSigned,
IntPtr[] rgpbToBeSigned,
Int32[] rgcbToBeSigned,
Byte[] pbSignedBlob,
ref Int32 pcbSignedBlob
);
const Int32 X509_ASN_ENCODING = 0x00000001;
const Int32 PKCS_7_ASN_ENCODING = 0x00010000;
const string szOID_CP_GOST_R3411 = "1.2.643.2.2.9";
//Отпечаток известного нам сертификата
const string CertThumbprint = "D55E8BC8037937D1A836F8A0524E56B1C49AD281";
const string StringForSign = "Some Data"; //Данные для подписи
static void Main()
{
X509Store MyStore = new X509Store(StoreLocation.CurrentUser);
MyStore.Open(OpenFlags.ReadOnly);
try
{
foreach (X509Certificate2 MyCert in MyStore.Certificates)
{
if (MyCert.Thumbprint == CertThumbprint) //Нашли нужный
{
CRYPT_SIGN_MESSAGE_PARA MySignContext = new CRYPT_SIGN_MESSAGE_PARA();
MySignContext.cbSize = Marshal.SizeOf(typeof(CRYPT_SIGN_MESSAGE_PARA));
MySignContext.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
MySignContext.pSigningCert = MyCert.Handle;
MySignContext.HashAlgorithm.pszObjId = szOID_CP_GOST_R3411;
IntPtr[] BuffToSign = new IntPtr[1] { Marshal.StringToHGlobalAnsi(StringForSign) };
try
{
int SignedLen = 4096;
byte[] Result = new byte[SignedLen];
int[] bufferLen = new int[1] { StringForSign.Length };
if (CryptSignMessage(ref MySignContext, true, 1, BuffToSign, bufferLen, Result, ref SignedLen))
{
Array.Resize(ref Result, SignedLen);
for (int i = 0; i < Result.Length; i++)
{
Console.Write("{0:X2} ", Result[i]);
if ((i+1) % 26 == 0)
Console.WriteLine();
}
Console.Write("\nLength = {0}", Result.Length);
Console.Write("\nPress any key to exit: ");
Console.ReadKey();
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
Marshal.FreeHGlobal(BuffToSign[0]);
}
break;
}
}
}
finally
{
MyStore.Close();
}
}
}
}
Подскажите, как повторить это средствами браузерного плагина (интересует коротенький примерчик на JavaScript). Главное, чтобы совпало значение подписи, преобразования в BASE64 и т.д. если нужно это понятно. На основе примеров, тех что в документации, не могу добиться совпадения. Вероятно, чего-то недопонимаю. Вложение(я):  Program.cs.zip (2kb) загружен 9 раз(а).У Вас нет прав для просмотра или загрузки вложений. Попробуйте зарегистрироваться.
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,190   Сказал «Спасибо»: 621 раз Поблагодарили: 2397 раз в 1886 постах
|
|
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 14,190   Сказал «Спасибо»: 621 раз Поблагодарили: 2397 раз в 1886 постах
|
За такое ... Код: int SignedLen = 4096;
byte[] Result = new byte[SignedLen];
Позвольте поинтересоваться, где "такому" учат? |
|
|
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.11.2014(UTC) Сообщений: 4 
|
> Так и должно быть, так как в создании ЭЦП по алгоритму ГОСТ Р 34.11/34.10-2001 используется случайное число. Вопрос не в том, что результат какждый раз разный. А в том, что при проверке подписи результаты не бьются. Я наверно не правильно выразился. > Позвольте поинтересоваться, где "такому" учат? А в чём криминал? Выделяем заведомо бОльший буфер, реальная длина которого затем пересчитывается в вызове CryptSignMessage(), после чего обрезаем лишнее. Да, можно было бы сначала тем же вызовом спросить нужную длину, и её выделить. Но вопрос же не об этом совсем (было бы 2 вызова с обращением к носителю, а это ничуть не быстрее).
|
|
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.11.2014(UTC) Сообщений: 4 
|
Народ, я понимаю, что видимо сильно туплю. Но подскажите хоть направление какое-то. Вот делаю к примеру так: Код:
function TestClick() {
var CADESCOM_HASH_ALGORITHM_CP_GOST_3411 = 100;
var CADESCOM_BASE64_TO_BINARY = 1;
var CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
var CADES_BES = 1;
var CADESCOM_CADES_DEFAULT = 0;
var oSigner = CreateObject("CAdESCOM.CPSigner");
oSigner.Options = 0;
var oSignedData = CreateObject("CAdESCOM.CadesSignedData");
oSignedData.Content = "Some Data";
var sSignedData = oSignedData.SignCades(oSigner, CADES_BES);
document.getElementById("EpText").value = sSignedData;
}
Получается какой-то результат. Когда я его декодирую из BASE64, то длина у него 2881 байт. А в том моём примере 1044 байта - понятно, что верификация подписи не сойдётся в таком случае никак, это что-то совсем разное. Что и как мне правильно вызвать?
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 25.12.2007(UTC) Сообщений: 1,733  Откуда: КРИПТО-ПРО Поблагодарили: 177 раз в 168 постах
|
Цитата:Получается какой-то результат. Когда я его декодирую из BASE64, то длина у него 2881 байт. А в том моём примере 1044 байта - понятно, что верификация подписи не сойдётся в таком случае никак, это что-то совсем разное. Что и как мне правильно вызвать? При вызове плагина в подпись автоматически добавляется сертификат подписанта, в случае же вызова CryptSignMessage надо правильно заполнить CRYPT_SIGN_MESSAGE_PARA:rgpMsgCert. Это и дает разницу в размере, но не является причиной того, что подпись не проверяется. |
|
|
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 23.11.2014(UTC) Сообщений: 4 
|
Т.е. верно ли я понимаю из ваших слов, что применительно к моему примеру, первые 1044 байта это будет подпись, а следом идёт что-то вроде аналога свойства RawData для объекта класса X509Certificate2 ? Или там какая-то другая структура будет в том массиве, что возвращается? (содержимое сертификата подписанта мне как раз тоже понадобится, теперь только бы правильно отделить одно от другого...)
|
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 25.12.2007(UTC) Сообщений: 1,733  Откуда: КРИПТО-ПРО Поблагодарили: 177 раз в 168 постах
|
Цитата:Т.е. верно ли я понимаю из ваших слов, что применительно к моему примеру, первые 1044 байта это будет подпись, а следом идёт что-то вроде аналога свойства RawData для объекта класса X509Certificate2 ? Или там какая-то другая структура будет в том массиве, что возвращается? (содержимое сертификата подписанта мне как раз тоже понадобится, теперь только бы правильно отделить одно от другого...) Другая структура. |
|
|
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close