powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Delphi + КриптоПро + ЭЦП
13 сообщений из 13, страница 1 из 1
Delphi + КриптоПро + ЭЦП
    #38776585
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый вечер!

Возникла необходимость реализации ЭЦП для части XML файла на Delphi с использованием КриптоПро и

Собственно суть, необходимо реализовать подпись в следующем виде :

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig">
	<ds:SignedInfo>
		<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
		<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/>
		<ds:Reference URI="#AppData">
			<ds:Transforms>
				<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
				<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
			</ds:Transforms>
			<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/>
			<ds:DigestValue>Значение хеша в Base64</ds:DigestValue>
		</ds:Reference>
	</ds:SignedInfo>
	<ds:SignatureValue>Значение подписи в Base64</ds:SignatureValue>
	<ds:KeyInfo>
		<ds:X509Data>
			<ds:X509Certificate>Cертификат X.509 в Base64</ds:X509Certificate>
		</ds:X509Data>
	</ds:KeyInfo>
</ds:Signature>



Где значения:
"Значение хеша в Base64" - Хеш от подписываемого куска XML рассчитанный в соответствии с ГОСТ Р 34.11-94

"Значение подписи в Base64" - Сформированная подпись по стандарту ГОСТ Р 34.10-2001

"Cертификат X.509 в Base64" - Открытый ключ подписи

Если я правильно понял после прочтения форма, алгоритм действий следующий:

Получаем список доступных контейнеров
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
procedure TfrmXmlSign.actVievAllContainerExecute(Sender: TObject);
var
  Prov: HCRYPTPROV;
  pbData: PBYTE;
  cbData: Cardinal;
  Flag: Cardinal;
begin
  if CryptAcquireContext(Prov, nil, CP_GR3410_2001_PROV_A, PROV_GOST_2001_DH , CRYPT_VERIFYCONTEXT) then
  begin
    Flag := CRYPT_FIRST;
    if CryptGetProvParam(Prov, PP_ENUMCONTAINERS, nil, cbData, Flag) then
    begin
      GetMem(pbData, cbData);
      try
        while CryptGetProvParam(Prov, PP_ENUMCONTAINERS, pbData, cbData, Flag) do
        begin
          Flag := CRYPT_NEXT;
          lstContainers.Items.Add(PAnsiChar(pbData));
        end;
      finally
        FreeMem(pbData, cbData);
      end;
    end;
    CryptReleaseContext(Prov, 0);
  end;
end;



По клику в lstContainers, имя контейнера записывается в глобальную переменную и все дальнейшие действия производим, с данным контейнером.

Получаем значение подписи, кусок кода найден на просторах интернета

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
procedure TfrmXmlSign.actSignExecute(Sender: TObject);
var
  prov: HCRYPTPROV;
  hash: HCRYPTHASH;
  hKey: HCRYPTKEY;
  Param: CRYPT_PIN_PARAM;
  PassStr, AContainerName: string;
  Source, Dest: TMemoryStream;
  Buffer, Signature: Pointer;
  cbHash, SourceBufLen, DestBufLen, dwBlobLen: DWORD;
  pbKeyBlob, pbHash: PBYTe;
begin
  Win32Check(CryptAcquireContext(Prov, PChar(FTokenName), CP_GR3410_2001_PROV_A, PROV_GOST_2001_DH, 0 ));

  if not CryptSetProvParam(Prov, PP_KEYEXCHANGE_PIN, nil, 0) then
    ShowMessage('CryptSetProvParam' + IntToStr(GetLastError));
// Получение ключа пользователя.
    if CryptGetUserKey(Prov, AT_KEYEXCHANGE, hKey) then
      ShowMessage('CryptGetUserKey succeeded.');
    // Экпорт открытого ключа.
    if CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil, dwBlobLen) then
        ShowMessage('Size of the BLOB for the public key determined.');
    // Распределение памяти под pbKeyBlob.
    GetMem(pbKeyBlob, dwBlobLen);
    // Сам экспорт в ключевой BLOB.
    if CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, Pointer(pbKeyBlob), dwBlobLen) then
      ShowMessage('Contents have been written to the BLOB.');
 // Создание объекта функции хеширования.
  try
    Win32Check(CryptCreateHash(Prov, CALG_GR3411, 0, 0, Hash));
  except
    on E: Exception do
      ShowMessage('CryptCreateHash ' + E.Message);
  end;


  // Передача параметра HP_OID объекта функции хеширования.
  // Определение размера BLOBа и распределение памяти.
  if CryptGetHashParam(Hash, HP_OID, nil, cbHash, 0) then
    ShowMessage('Size of the BLOB determined.');

  GetMem(pbHash, cbHash);
  // Копирование параметра HP_OID в pbHash.
  if CryptGetHashParam(Hash, HP_OID, Pointer(pbHash), &cbHash,0) then
    ShowMessage('Parameters have been written to the pbHash.');

  // Вычисление криптографического хеша буфера.
  Source := TMemoryStream.Create;
  try
    Source.LoadFromFile('c:\1.xml'); //некритичный момент в дальнейшем буду грузить из потока
      try
        Win32Check(CryptHashData(Hash, Source.Memory, Source.Size, 0))
      except
        on E: Exception do
          ShowMessage('CryptHashData ' + E.Message);
      end;
  finally
    Source.Free;
  end;
  // Определяем длину
  DestBufLen := 0;
  try
    Win32Check(CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, nil, DestBufLen));
  except
    on E: Exception do
      ShowMessage('CryptSignHash 1' + E.Message);
  end;
  if DestBufLen > 0 then
  begin
  // Распределение памяти под буфер подписи.
    GetMem(Signature, DestBufLen);
    try
      Win32Check(CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, signature, DestBufLen));
    except
      on E: Exception do
        ShowMessage('CryptSignHash 1' + E.Message);
    end;
    try
      Dest := TMemoryStream.Create;
      Dest.Position := 0;
      Dest.WriteBuffer(Signature^, DestBufLen);
      dest.SaveToFile('c:\2.xml'); 
      {запись хеша в сыром виде, тут вероятно мне надо будет побайтово преобразовать содержимое
       Signature в Base64 строку}                                     
    finally
      Dest.Free;
    end;
  end;
  CryptDestroyHash(Hash);
  CryptReleaseContext(Prov, 0);
end;



Вопросы:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
  if CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil, dwBlobLen) then  
    ShowMessage('Size of the BLOB for the public key determined.');
  // Распределение памяти под pbKeyBlob.
  GetMem(pbKeyBlob, dwBlobLen);
  // Сам экспорт в ключевой BLOB.
  if CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, Pointer(pbKeyBlob), dwBlobLen) then
    ShowMessage('Contents have been written to the BLOB.');


После выполнения такого вот кода я получается получаю интересующее меня значение открытого ключа и мне его требуется только достать из pbKeyBlob и преобразовать в base64 ?



Каким образом будет правильнее реализовать подпись полученного хеша, детально не прорабатывал вопрос, буду раз любым советам. Хотелось бы создать подпись в рамках этой же процедуры. А то будет не юзерфрендли спрашивать пароль на подсчет хеша и подпись отдельно.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38776587
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дополню использую JwaWinCrypt.pas для доступа до вызовов API
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38776702
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kloppik,

Для расчета хеша не нужен пароль, потому что не нужен и контейнер.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38777078
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql2012, спасибо за замечание, присмотрелся внимательнее заметил что действительно не нужен пароль для хеширования.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38777485
onyx2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kloppik,

сори за офтоп, случайно не в Океан'е работаешь?
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38777853
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
onyx2012, нет, но задачи видимо везде одни и те же, это обмен запросами со СМЭВом
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38786851
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Продолжу тут.

На текущий момент ситуация такова, у меня получилось реализовать вычисление хеша и его подпись.
Код получился приблизительно такой:


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
procedure TForm2.Button1Click(Sender: TObject);
var
  Prov : HCRYPTPROV;

  s: string;
  i: integer;
  size, KeySize, hashSize, signSize, DataSize , dwBlobLen: DWORD;
  hash: HCRYPTHASH;
  pbHash : PByte;
  pbSign, pbKeyBlob, pKeyInfo : PByte;
  alg: ALG_ID;
  outstr : String;
  hKey: HCRYPTKEY;
begin
  Memo1.Lines.Clear;
  
  try
    try
      Win32Check(CryptAcquireContext(Prov, PChar('test'), CP_GR3410_2001_PROV_A, PROV_GOST_2001_DH, 0 ));
    except
      on E: Exception do
        ShowMessage('CryptSignHash ' + E.Message);
    end; 
    
    try
      Win32Check(CryptGetUserKey(Prov, AT_KEYEXCHANGE, hKey))
    except
      on E: Exception do
        ShowMessage('Ошибка ключа ' + E.Message);
    end;

    try
      Win32Check(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil, dwBlobLen))
    except
      on E: Exception do
        ShowMessage('Ошибка получения длины ключа ' + E.Message);
    end;

    GetMem(pbKeyBlob, dwBlobLen);
        
    try
      Win32Check(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, Pointer(pbKeyBlob), dwBlobLen))
    except
      on E: Exception do
        ShowMessage('Ошибка экспорта ключа ' + E.Message);
    end;

    outstr := EncodeBase64(pbKeyBlob, dwBlobLen);

    Memo1.Lines.Add('Открытый ключ : ');
    Memo1.Lines.Add(StringReplace(outstr, #13#10, '', [rfReplaceAll]));
    Memo1.Lines.Add('');
    
    alg:=CALG_GR3411;

    try
      Win32Check(CryptCreateHash(Prov, alg, 0, 0, Hash));
    except
      on E: Exception do
        ShowMessage('CryptCreateHash ' + E.Message);
    end;

    s := '';
    size := Length(s);
    if not CryptHashData(hash, PByte(s), size, 0) then
      begin
        raise Exception.Create('Ошибка при хешировании');
      end;

    DataSize := SizeOf(DataSize);
    if not CryptGetHashParam(hash, HP_HASHSIZE, @hashSize, DataSize, 0) then
      begin
        raise Exception.Create('Ошибка при хешировании');
      end;
    GetMem(pbHash, hashSize);
    
    try
      if not CryptGetHashParam(hash, HP_HASHVAL, pbHash, hashSize, 0) then
        begin
          raise Exception.Create('Ошибка при хешировании');
        end;  
       outstr := EncodeBase64(pbHash, hashSize);
       Memo1.Lines.Add('Хеш : ');
       Memo1.Lines.Add(StringReplace(outstr, #13#10, '', [rfReplaceAll]));
       Memo1.Lines.Add('');
    finally
      FreeMem(pbHash);
    end; 

    signSize := 0;
    try
      Win32Check(CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, nil, signSize));
    except
      on E: Exception do
        ShowMessage('Ошибка получение длины подписи ' + E.Message);
    end;

    GetMem(pbSign, signSize);

    try
      Win32Check(CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, pbSign, signSize));
    except
      on E: Exception do
        ShowMessage('Ошибка получение подписи ' + E.Message);
    end;

    outstr := EncodeBase64(pbSign, signSize);
    Memo1.Lines.Add('Подпись хеша : ');
    Memo1.Lines.Add(StringReplace(outstr, #13#10, '', [rfReplaceAll]));
    if not CryptDestroyHash(hash) then
      begin
        raise Exception.Create('Ошибка при уничтожении хеша');
      end;

  finally
    CryptReleaseContext(Prov, 0);
  end;
end;




Вопрос такого плана, каким образом можно получить X.509 сертификат ключа использовавшегося для шифрования.

И общий вопрос звучит так, правильно ли я вообще подписываю, на данный момент я понимаю происходит следующее
1. Получаем контекст провайдера
2. Из провайдера дергаем ключевую пару, в моем случае это AT_KEYEXCHANGE
3. Делаем хеш, он от ключа как я понимаю не зависит, зависит тока от провайдера и поддерживаемых алгоритмов
4. Делаем CryptSignHash для полученного хеша с указанием ключевой пары, подпись будет открытым ключом или закрытым???
5. Экспортируем сертификат выбранной ключевой пары.

Достаточно ли будет данных о сертификате, хеша и подписи, для проверки не изменялись ли исходные данные?
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38786900
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Отвечу сам себе, возможно кому то пригодиться и сэкономит некоторое количество часов в жизни.

Код получился следующий:


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
procedure TForm2.Button1Click(Sender: TObject);
var
  Prov : HCRYPTPROV;

  s: string;
  i: integer;
  size, KeySize, hashSize, signSize, DataSize , dwBlobLen: DWORD;
  hash: HCRYPTHASH;
  pbHash : PByte;
  pbSign, pbKeyBlob, pKeyInfo : PByte;
  alg: ALG_ID;
  outstr : String;
  hKey: HCRYPTKEY;
  pbUserCert:PBYTE;
dwUserCertLength:DWORD;
begin
  Memo1.Lines.Clear;
  
  try
    try
      Win32Check(CryptAcquireContext(Prov, PChar('test'), CP_GR3410_2001_PROV_A, PROV_GOST_2001_DH, 0 ));
    except
      on E: Exception do
        ShowMessage('CryptSignHash ' + E.Message);
    end; 
    
    try
      Win32Check(CryptGetUserKey(Prov, AT_KEYEXCHANGE, hKey))
    except
      on E: Exception do
        ShowMessage('Ошибка ключа ' + E.Message);
    end;

    try
      Win32Check(CryptGetKeyParam(hKey,KP_CERTIFICATE ,nil,dwUserCertLength,0))
    except
      on E: Exception do
        ShowMessage('Ошибка получения длины сертификата ' + E.Message);
    end;

    GetMem(pbUserCert,dwUserCertLength);

    try
      Win32Check(CryptGetKeyParam(hKey,KP_CERTIFICATE ,pbUserCert,dwUserCertLength,0))
    except
      on E: Exception do
        ShowMessage('Ошибка получения сертификата ' + E.Message);
    end;

    outstr := EncodeBase64(pbUserCert, dwUserCertLength);

    Memo1.Lines.Add('Сертификат : ');
    Memo1.Lines.Add(outstr);
    Memo1.Lines.Add('');     

    try
      Win32Check(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, nil, dwBlobLen))
    except
      on E: Exception do
        ShowMessage('Ошибка получения длины ключа ' + E.Message);
    end;

    GetMem(pbKeyBlob, dwBlobLen);
        
    try
      Win32Check(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, Pointer(pbKeyBlob), dwBlobLen))
    except
      on E: Exception do
        ShowMessage('Ошибка экспорта ключа ' + E.Message);
    end;

    outstr := EncodeBase64(pbKeyBlob, dwBlobLen);

    Memo1.Lines.Add('Открытый ключ : ');
    Memo1.Lines.Add(StringReplace(outstr, #13#10, '', [rfReplaceAll]));
    Memo1.Lines.Add('');
    
    alg:=CALG_GR3411;

    try
      Win32Check(CryptCreateHash(Prov, alg, 0, 0, Hash));
    except
      on E: Exception do
        ShowMessage('CryptCreateHash ' + E.Message);
    end;

    s := '';
    size := Length(s);
    if not CryptHashData(hash, PByte(s), size, 0) then
      begin
        raise Exception.Create('Ошибка при хешировании');
      end;

    DataSize := SizeOf(DataSize);
    if not CryptGetHashParam(hash, HP_HASHSIZE, @hashSize, DataSize, 0) then
      begin
        raise Exception.Create('Ошибка при хешировании');
      end;
    GetMem(pbHash, hashSize);
    
    try
      if not CryptGetHashParam(hash, HP_HASHVAL, pbHash, hashSize, 0) then
        begin
          raise Exception.Create('Ошибка при хешировании');
        end;  
       outstr := EncodeBase64(pbHash, hashSize);
       Memo1.Lines.Add('Хеш : ');
       Memo1.Lines.Add(StringReplace(outstr, #13#10, '', [rfReplaceAll]));
       Memo1.Lines.Add('');
    finally
      FreeMem(pbHash);
    end; 

    signSize := 0;
    try
      Win32Check(CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, nil, signSize));
    except
      on E: Exception do
        ShowMessage('Ошибка получение длины подписи ' + E.Message);
    end;

    GetMem(pbSign, signSize);

    try
      Win32Check(CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, pbSign, signSize));
    except
      on E: Exception do
        ShowMessage('Ошибка получение подписи ' + E.Message);
    end;

    outstr := EncodeBase64(pbSign, signSize);
    Memo1.Lines.Add('Подпись хеша : ');
    Memo1.Lines.Add(StringReplace(outstr, #13#10, '', [rfReplaceAll]));
    if not CryptDestroyHash(hash) then
      begin
        raise Exception.Create('Ошибка при уничтожении хеша');
      end;

  finally
    CryptReleaseContext(Prov, 0);
  end;
end;




Вопросы из предыдущего комментария в принципе актуальны, если кто то может ответить или поделиться ссылками, буду только рад.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38787091
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kloppik

Вопрос такого плана, каким образом можно получить X.509 сертификат ключа использовавшегося для шифрования.

Может для создания электронной подписи?
Можно так:
Подключиться к Хранилищу сертификатов (MY | ROOT) и сверить открытый ключ полученный через CSP и в сертификате.

Если для шифрования (дословно трактую вопрос):
до расшифровки - необходимо получить информацию о получателях (серийный номер сертификата и информацию по УЦ, в котором выдан сертификат). Далее (до начала расшифровки) - подключаемся к хранилищу (MY | ROOT), находим сертификат, по нему запрашиваем информацию о CSP\контейнере и получив указатель на закрытый ключ - идем к функции расшифровки...


kloppik
И общий вопрос звучит так, правильно ли я вообще подписываю, на данный момент я понимаю происходит следующее
1. Получаем контекст провайдера
2. Из провайдера дергаем ключевую пару, в моем случае это AT_KEYEXCHANGE

Бывают и исключения: AT_SIGNATURE

kloppik3. Делаем хеш, он от ключа как я понимаю не зависит, зависит тока от провайдера и поддерживаемых алгоритмов

Хеш зависит от алгоритма, если бы он зависел от CSP ... (хотя встречались ранние альфа\бета версии, в которых хеши не так считались)

kloppik4. Делаем CryptSignHash для полученного хеша с указанием ключевой пары, подпись будет открытым ключом или закрытым???

Подписание будет с участием закрытого ключа и случайного числа. И такая специфика ГОСТ-а дает каждый раз разные значения ЭП для одних и тех же подписываемых байтов.


kloppik5. Экспортируем сертификат выбранной ключевой пары.

У если "у меня" его нет? :)


kloppikДостаточно ли будет данных о сертификате, хеша и подписи, для проверки не изменялись ли исходные данные?
Вполне.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38787185
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql2012

Может для создания электронной подписи?
Можно так:
Подключиться к Хранилищу сертификатов (MY | ROOT) и сверить открытый ключ полученный через CSP и в сертификате.


Да для подписи, неверно сформулировал.

А тут проблема в том, что ключи и сертификат лежат на токене, и у меня не получилось выдернуть сертификат с хранилища, подозреваю что его изначально надо туда положить.

sql2012kloppik

И общий вопрос звучит так, правильно ли я вообще подписываю, на данный момент я понимаю происходит следующее
1. Получаем контекст провайдера
2. Из провайдера дергаем ключевую пару, в моем случае это AT_KEYEXCHANGE


Бывают и исключения: AT_SIGNATURE


По идее, как раз таки использование AT_KEYEXCHANGE это исключение, для подписи по феншую надо использовать AT_SIGNATURE , но в моем случае на токенах не оказалось этой ключевой пары, я пробовал ее генерировать, но у с генерированной ключевой пары отсутствует сертификат. А сертификат мне обязателен, он содержит инфу кто сформировал подписанный запрос. У меня подпись используется не только для страховки от подмены данных в запросе, но и для получения данных о том какой конкретно сотрудник сформировал запрос.

sql2012kloppik
5. Экспортируем сертификат выбранной ключевой пары.

У если "у меня" его нет? :)


Ну судя по ответам, ты знаешь что делать в этом случае)), по идее открытого ключа будет достаточно для проверки валидности подписи, если я все правильно понял, в моем случае сертификат обязательно будет, либо эта ключевая пара не подходит для подписи.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38787401
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kloppik
Ну судя по ответам, ты знаешь что делать в этом случае)), по идее открытого ключа будет достаточно для проверки валидности подписи, если я все правильно понял, в моем случае сертификат обязательно будет, либо эта ключевая пара не подходит для подписи.

"Подписывают" не сертификатом...
Пример:
У меня есть контейнеры с AT_KEYEXCHANGE и с AT_SIGNATURE, но нет сертификатов.

Будет ли этого достаточно для создания подписи?
- да.

Будет ли работать экспорт несуществующего сертификата?
- нет.
...
Рейтинг: 0 / 0
Delphi + КриптоПро + ЭЦП
    #38788054
kloppik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql2012"Подписывают" не сертификатом...


Да с этим я согласен, для подписи достаточно закрытого ключа, для валидации подписи открытого, добавление сертификата в моем случае служит не только цели проверки корректности подписи, но и для цели выяснения кто эту подпись создал. Мой вопрос был не обобщением процедуры, а уточнением правильности моего понимания что непроходимо реализовать в моем конкретном случае.

Если не прикладывать сертификат, то невозможно к примеру принимать запросы от конкретной организации, а в моем случае это критично. Т.е. со стороны принимающей запрос, происходит не только проверка корректности подписи и данных, но и проверка на то что запрос подписан конкретным пользователем с конкретными правами.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Delphi + КриптоПро + ЭЦП
    #40141153
MakcuM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ли оживить эту тему?
Может кто то поделиться наработками по взаимодействию с налоговой xmldsig для SOAP:BODY?
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Delphi + КриптоПро + ЭЦП
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]