powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как сделать цифровую подпись на основе сертификата
128 сообщений из 128, показаны все 6 страниц
Как сделать цифровую подпись на основе сертификата
    #34770141
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сорри несколько за глупый вопрос. Просто проект нужно сдать в понедельник. Время поджимает и реально не успеваю.
Что нужно:
на основе сертификата (выбирается вручную из установленных) подписать файл цифровой подписью, а потом проверить эту самую подпись. Стало быть как сделать? Если кто-нибудь кинет рабочим примером на Дельфи, буду очень благодарен.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34770195
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вам ответил на форуме КриптоПро Кирил Соболев... а это наверное единственный человек... отвечающий на вопросы сторонних разработчиков... использующих продукты борланда
И ответил правильно... дал сылку на sample в си-исходниках... казалось бы, что еще требуется специалисту... вы же начали клянчить код на паскале...
Что могу добавить еще по теме... вам требуется научиться пользоваться минимальным набором функций "Simplified Message Functions" из крипто раздела msdn

зы: или назвать сумму вечнозеленых... с которой вы готовы расстаться... чтобы другие люди писали за вас код
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34770212
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На форуме КриптоПро вопрос задавал человек, который ушел в отпуск. А эту задачу теперь повесили на меня. Я с такими вещами никогда не работал и поэтому решил написать здесь. CryptoAPI я сейчас активно изучаю, но и еще хотелось бы посмотреть на код-пример.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34770233
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тогда остается только повторить... что исходники примеров растут тут:
http://www.cryptopro.ru/cryptopro/products/csp/20/sample-2-0.zip
раздел msdn по CryptoAPI можно почитать тут:
http://msdn2.microsoft.com/en-us/library/aa380252.aspx

CryptoAPI message functions consist of two groups of functions: low-level message functions and simplified message functions.

Simplified message functions are at a higher level and wrap several low-level message functions and certificate functions into single functions that perform a specific task in a specific manner. These functions reduce the number of function calls needed to accomplish a task, thereby simplifying CryptoAPI use. For an overview of simplified messages, see Simplified Messages.

а из них только вот эти две:
CryptSignMessage
CryptVerifyDetachedMessageSignature (CryptVerifyMessageSignature)

код за вас я писать не буду, но на конкретные вопросы (подкрепленные самостоятельно написанным кодом) отвечу
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34771169
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрался до функции
function CertFindCertificateInStore(hCertStore :HCERTSTORE;
dwCertEncodingType :DWORD;
dwFindFlags :DWORD;
dwFindType :DWORD;
const pvFindPara :PVOID;
pPrevCertContext :PCCERT_CONTEXT
):PCCERT_CONTEXT ; stdcall;

Не моуг понять что должно быть указано в параметре pvFindPara? Знаю что это должно быть название сертификата. Пробовал искать его в личных сертификатах, но где оно там написано не понял. Там есть инфа о том кому выдали сертификат, кто выдал, когда выдали и т.д.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34771870
MAX2002
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может эта статейка тебе поможет?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34772011
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LimonFXДобрался до функции
function CertFindCertificateInStore(hCertStore :HCERTSTORE;
dwCertEncodingType :DWORD;
dwFindFlags :DWORD;
dwFindType :DWORD;
const pvFindPara :PVOID;
pPrevCertContext :PCCERT_CONTEXT
):PCCERT_CONTEXT ; stdcall;

Не моуг понять что должно быть указано в параметре pvFindPara? Знаю что это должно быть название сертификата. Пробовал искать его в личных сертификатах, но где оно там написано не понял. Там есть инфа о том кому выдали сертификат, кто выдал, когда выдали и т.д.

Вот это уже более конструктивный разговор....
http://msdn2.microsoft.com/en-us/library/aa376064.aspx
Я не совсем понял, что подразумевается под под "названием сертификата", у него куча атрибутов, но предположим, что это CERT_FIND_SUBJECT_STR для dwFindType... msdn однозначно говорит, что pvFindPara для CERT_FIND_SUBJECT_STR должен быть data type: null-terminated Unicode string... т.е.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 var 
  wsFind : WideString;
  ...
 begin 
  ...
  wsFind := 'find';
  m_pHandle := CertFindCertificateInStore(...., CERT_FIND_SUBJECT_STR, PWideString( wsFind ), ... );
  ...
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34772232
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
C предыдущим вопросом я уже разобрался - сертификат находит. Теперь другая проблема. Функция CertNameToStr возвращает не нулевое значение, а вот Cert_name почему-то пустой.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
........
  hStoreHandle := CertOpenSystemStore( 0 , PChar(CERT_STORE_NAME));
........
  enctype := PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING;
  pSignerCert:= CertFindCertificateInStore(hStoreHandle,enctype, 0 ,CERT_FIND_SUBJECT_STR,pSignerName, nil );
   if  pSignerCert <>  nil   then 
    SignSize := CertNameToStr(encType, @pSignerCert.pCertInfo.Issuer , CERT_SIMPLE_NAME_STR, Cert_name,  512 );
  Memo.Lines.Add(IntToStr(SignSize));
  Memo.Lines.Add(Cert_name);
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34772258
__Avenger__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может данная статья поможет?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34772637
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сам нашел свою ошибку. Забыл вот эту строчку написать в коде Cert_name:= StrAlloc(2048); :)

Альт
Допустим я вытащил цифровую подпись из сертификата. Дальше мне нужно проверить подписанный файл. Какую из след. функции мне использовать, в чем их разница?
CryptSignMessage или CryptVerifyDetachedMessageSignature
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34772784
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LimonFXСам нашел свою ошибку. Забыл вот эту строчку написать в коде Cert_name:= StrAlloc(2048); :)
Допустим я вытащил цифровую подпись из сертификата. Дальше мне нужно проверить подписанный файл. Какую из след. функции мне использовать, в чем их разница?
CryptSignMessage или CryptVerifyDetachedMessageSignature

Плохо искал ошибку... узнай, что такое "Retrieving Data of Unknown Length"... пройдет желание писать "StrAlloc(2048)" ))
Самое забавное, что ничего тебе уже не надо... ты поймал контекст сертификата, а именно с ним и работают сипл-функции
Первая подписывает... вторая проверяет detached подписи
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774138
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Со StrAlloc потом буду разбираться, не столь важно это сейчас.
На данный момент EXEшник собирается и даже работает, но результатом проверки подписи является такая вот ошибка NTE_BAD_ALGID. Вроде как не нравится используемый алгоритм. Хотелось бы узнать на что нужно в первую очередь обратить внимание, чтобы узнать причину этой ошибки?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774194
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NTE_BAD_ALGID The hHash handle specifies an algorithm that this CSP does
not support.

Покажи, какие константы CALG_* использовал?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774481
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ALG_ID нигде не использовал. Где его нужно указывать?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774495
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LimonFXСо StrAlloc потом буду разбираться, не столь важно это сейчас.
На данный момент EXEшник собирается и даже работает, но результатом проверки подписи является такая вот ошибка NTE_BAD_ALGID. Вроде как не нравится используемый алгоритм. Хотелось бы узнать на что нужно в первую очередь обратить внимание, чтобы узнать причину этой ошибки?

А как именно выполняется проверка? Например CRYPT_VERIFY_MESSAGE_PARA обязательно должна быть предварительно занулена и потом наполнена... размер cbSize должен быть правильным... подкрепляйте вопрос кодом, гадание на кофейной гуще утомляет...

для CryptVerify*
NTE_BAD_ALGID The message was hashed and signed by using an unknown or unsupported algorithm.

Как вариант... в системе отсутствует необходимый провайдер
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774530
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
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.
.......  
VerifyPara.cbSize := SizeOf(CRYPT_VERIFY_MESSAGE_PARA);
  VerifyPara.dwMsgAndCertEncodingType := enctype;
  VerifyPara.hCryptProv := hProv;
  VerifyPara.pfnGetSignerCertificate := @MySignerCertificateCallback;
  VerifyPara.pvGetArg := pSignerCert;


   if  (dlgOpenSign.Execute)  and  (dlgOpenSign.FileName <> EmptyStr)  then 
   begin 
 //файл с подписью 
    AssignFile(f1,dlgOpenSign.FileName);
    Reset(f1,  1 );
    SignSize := FileSize(f1);
    GetMem(Sign, SignSize);

    BlockRead(f1,Sign^,SignSize);
    CloseFile(f1);
   end ;

   if  (dlgOpenFile.Execute)  and  (dlgOpenFile.FileName <> EmptyStr)  then 
   begin 
 //подписанынй файл 
    SetLength(MessageArray, sizeof(PByte));
    SetLength(MessageSize, sizeof(DWORD));

    AssignFile(f1,dlgOpenFile.FileName);
    Reset(f1,  1 );

    MessageSize[ 0 ] := FileSize(f1);
    GetMem(MessageArray[ 0 ], MessageSize[ 0 ]);

    BlockRead(f1, MessageArray[ 0 ]^, MessageSize[ 0 ]);
    CloseFile (f1);
   end ;


   if  CryptVerifyDetachedMessageSignature(@VerifyPara,  0 , Sign, SignSize,  1 , MessageArray, MessageSize, pSignerCert)  then 
   begin 
    Memo.Lines.Add('Проверка прошла успешно');
   end 
   else 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Ошибка:' + err);
   end ;
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774538
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LimonFXГде его нужно указывать?

В CryptCreateHash например...
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34774861
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предположим, что подпись и сообщение читаются правильно... и содержат все необходимые данные....
Ну и заполняется вами вроде вся структура... хотя и тут есть свой нюанс:
VerifyPara.hCryptProv := hProv;
хендл какого провайдера вы сюда подпихиваете? может ну его нафик... жираф то большой и ему видней... скиньте в ноль... он сам проверить провайдеров в системе на факт реализации необходимых алгоритмов
VerifyPara.hCryptProv := 0;

Надеюсь и калбек (MySignerCertificateCallback) делает, что нужно

а подписывалось на каком HashAlgorithm.pszObjId?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34778768
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообщем задача немного поменялась. Теперь все в одном флаконе (инфа и подпись в одном файле), т.е. не detached. Старый код выбросил, залез на msdn, нашел там подходящий пример и на его основе сделал вот этот код:
Код: plaintext
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.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
 procedure  TForm1.Button3Click(Sender: TObject);
 Const 
  CERT_STORE_NAME = 'MY';
  MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING;
 var 
  hCertStoreHandle : HCERTSTORE;
  SIGNER_NAME:  string ;
  pSignerName: PWideChar;
   //pbMessage: PByte; 
   //cbMessage: DWORD; 
  MessageArray:  array   of  PByte;
  MessageSize :  array   of  DWORD;
  pSignerCert: PCCERT_CONTEXT;
  SigParams: CRYPT_SIGN_MESSAGE_PARA;
  cbSignedMessageBlob: DWORD;
  pbSignedMessageBlob: PByte;
  pSignedMessageBlob: CRYPT_DATA_BLOB;
  err:  String ;
  f1:  File ;
 begin 
  Memo.Clear;
  SIGNER_NAME := 'test';
  hCertStoreHandle :=  nil ;
  pSignedMessageBlob.cbData :=  0 ;
  pSignedMessageBlob.pbData :=  nil ;
  hCertStoreHandle := CertOpenSystemStore( 0 ,PChar(CERT_STORE_NAME));
   if  hCertStoreHandle =  nil   then  Memo.Lines.Add('Ошибка при открытии хранилища ' + CERT_STORE_NAME);
  GetMem(pSignerName, 2 *Length(SIGNER_NAME)+ 1 );
  StringToWideChar(SIGNER_NAME,pSignerName, 2 *Length(SIGNER_NAME)+ 1 );
  pSignerCert := CertFindCertificateInStore(
                                            hCertStoreHandle,
                                            MY_ENCODING_TYPE,
                                             0 ,
                                            CERT_FIND_SUBJECT_STR,
                                            pSignerName,
                                             nil );
  FreeMem(pSignerName);
   if  pSignerCert =  nil   then 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Сертификат ' + SIGNER_NAME + ' не найден: ' + err);
    exit;
   end ;

   if  (srcFile.Execute)  and  (srcFile.FileName <> EmptyStr)  then 
   begin 
    SetLength(MessageArray,  1 *sizeof(PByte));
    SetLength(MessageSize,  1 *sizeof(DWORD));

    AssignFile(f1,srcFile.FileName);
    Reset(f1,  1 );

    MessageSize[ 0 ] := FileSize(f1);
    GetMem(MessageArray[ 0 ], MessageSize[ 0 ]);

    BlockRead(f1, MessageArray[ 0 ]^, MessageSize[ 0 ]);
    CloseFile (f1);
   end ;

  SigParams.cbSize := SizeOF(CRYPT_SIGN_MESSAGE_PARA);
  SigParams.dwMsgEncodingType := MY_ENCODING_TYPE;
  SigParams.pSigningCert := pSignerCert;
  SigParams.HashAlgorithm.pszObjId := szOID_PKCS_7;
  SigParams.HashAlgorithm.Parameters.cbData :=  0 ;
  SigParams.cMsgCert :=  1 ;
  SigParams.rgpMsgCert := @pSignerCert;
  SigParams.cAuthAttr :=  0 ;
  SigParams.dwInnerContentType :=  0 ;
  SigParams.cMsgCrl :=  0 ;
  SigParams.cUnauthAttr :=  0 ;
  SigParams.dwFlags :=  0 ;
  SigParams.pvHashAuxInfo :=  nil ;
  SigParams.rgAuthAttr :=  nil ;

   if   not  (CryptSignMessage(
        @SigParams,
        FALSE,
         1 ,
        MessageArray,
        MessageSize,
         nil ,
        @cbSignedMessageBlob))  then 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Размер буфера: ' + err);
    exit;
   end ;
  GetMem(pbSignedMessageBlob, cbSignedMessageBlob);
   if   not  (CryptSignMessage(
          @SigParams,
          FALSE,
           1 ,
          MessageArray,
          MessageSize,
          pbSignedMessageBlob,
          @cbSignedMessageBlob))  then 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Файл не подписан: ' + err);
    exit;
   end 
   else  Memo.Lines.Add('Файл подписан: ' + err);
  CertFreeCertificateContext(pSignerCert);
  CertCloseStore(hCertStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
  hCertStoreHandle :=  nil ;
  pSignedMessageBlob.cbData := cbSignedMessageBlob;
  pSignedMessageBlob.pbData := pbSignedMessageBlob;
   if  SaveSignFile.Execute  then 
   begin 
    AssignFile(f1,SaveSignFile.FileName);
    Rewrite(f1,  1 );
    BlockWrite(f1, pbSignedMessageBlob^, cbSignedMessageBlob);
    CloseFile (f1);
   end ;
 end ;

 procedure  TForm1.Button4Click(Sender: TObject);
 Const 
  CERT_STORE_NAME = 'MY';
  MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING;
  PROVIDER_NAME = '';
 var 
  hCertStoreHandle: HCERTSTORE;
  cbDecodedMessageBlob: DWORD;
  pbDecodedMessageBlob: PByte;
  VerifyParams: CRYPT_VERIFY_MESSAGE_PARA;
  pSignedMessageBlob: CRYPT_DATA_BLOB;
  pDecodedMessageBlob: CRYPT_DATA_BLOB;
  err:  string ;
  SIGNER_NAME:  string ;
  pSignerName: PWideChar;
  pSignerCert: PCCERT_CONTEXT;
  MessageArray:  array   of  PByte;
  MessageSize :  array   of  DWORD;
  f1:  File ;
  hProv: HCRYPTPROV;
  
   function  MySignerCertificateCallback( pvGetArg : pvoid; 
dwCertEncodingType : DWORD;
pSignerId : PCERT_INFO;
hMsgCertStore : HCERTSTORE): PCCERT_CONTEXT ; stdcall;
   begin 
    Result := PCCERT_CONTEXT(pvGetArg);
   end ;

 begin 
  pbDecodedMessageBlob :=  nil ;
  pDecodedMessageBlob.cbData :=  0 ;
  pDecodedMessageBlob.pbData :=  nil ;

  Memo.Clear;
  SIGNER_NAME := 'test';
  hCertStoreHandle :=  nil ;
  pSignedMessageBlob.cbData :=  0 ;
  pSignedMessageBlob.pbData :=  nil ;
  hCertStoreHandle := CertOpenSystemStore( 0 ,PChar(CERT_STORE_NAME));
   if  hCertStoreHandle =  nil   then  Memo.Lines.Add('Ошибка при открытии хранилища ' + CERT_STORE_NAME);
  GetMem(pSignerName, 2 *Length(SIGNER_NAME)+ 1 );
  StringToWideChar(SIGNER_NAME,pSignerName, 2 *Length(SIGNER_NAME)+ 1 );
  pSignerCert := CertFindCertificateInStore(
                                            hCertStoreHandle,
                                            MY_ENCODING_TYPE,
                                             0 ,
                                            CERT_FIND_SUBJECT_STR,
                                            pSignerName,
                                             nil );
  FreeMem(pSignerName);
   if  pSignerCert =  nil   then 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Сертификат ' + SIGNER_NAME + ' не найден: ' + err);
    exit;
   end ;

   if   not  CryptAcquireContext(@hProv,  nil , PROVIDER_NAME, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)  then 
   begin 
    Memo.Lines.Add('Провайдер '+PROVIDER_NAME+' не найден');
    exit;
   end ;

  VerifyParams.cbSize := sizeof(CRYPT_VERIFY_MESSAGE_PARA);
  VerifyParams.dwMsgAndCertEncodingType := MY_ENCODING_TYPE;
  VerifyParams.hCryptProv := hProv;
  VerifyParams.pfnGetSignerCertificate := @MySignerCertificateCallback;
  VerifyParams.pvGetArg := pSignerCert;

   if  (srcFile.Execute)  and  (srcFile.FileName <> EmptyStr)  then 
   begin 
    AssignFile(f1,srcFile.FileName);
    Reset(f1,  1 );

    pSignedMessageBlob.cbData := FileSize(f1);
    GetMem(pSignedMessageBlob.pbData, pSignedMessageBlob.cbData);

    BlockRead(f1, pSignedMessageBlob.pbData^, pSignedMessageBlob.cbData);
    CloseFile (f1);
   end ;

   if   not  (CryptVerifyMessageSignature(
                  @VerifyParams,
                   0 ,
                  pSignedMessageBlob.pbData,
                  pSignedMessageBlob.cbData,
                   nil ,
                  cbDecodedMessageBlob,
                   nil ))  then 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Не удалось узнать размер буфера : ' + err);
    exit;
   end ;

  GetMem(pbDecodedMessageBlob,cbDecodedMessageBlob); 

   if   not  (CryptVerifyMessageSignature(
                  @VerifyParams,
                   0 ,
                  pSignedMessageBlob.pbData,
                  pSignedMessageBlob.cbData,
                  pbDecodedMessageBlob,
                  cbDecodedMessageBlob,
                   nil ))  then 
   begin 
    err := IntToStr(GetLastError);
    Memo.Lines.Add('Не удалось проверить подпись: ' + err);
    exit;
   end ;
  pDecodedMessageBlob.cbData := cbDecodedMessageBlob;
  pDecodedMessageBlob.pbData := pbDecodedMessageBlob;
 end ;
Сам файл вроде бы подписывается, ошибок замечено не было. А вот при проверке подписи всё таже ошибка - NTE_BAD_ALGID.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34780265
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нда... очень смешно про "szOID_PKCS_7"... ты где взял этот код? короче уломал ты меня писать за тебя... готовь деньги
Вот слепленная на скорую руку реализация поверх твоей

Код: plaintext
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.
 uses 
  WinCrypt;

 const 
  CERT_STORE_NAME = 'MY';
  MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING;
  SignerName : WideString = 'Pavel';

 procedure  Err(  const  msg :  String  );
 var 
  dwError, dwLen : DWORD;
  sError, sErrorDecode :  String ;
  pBuffer : Cardinal;
 begin 
  dwError := GetLastError;
  dwLen := FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM  or 
                          FORMAT_MESSAGE_ARGUMENT_ARRAY  or 
                          FORMAT_MESSAGE_ALLOCATE_BUFFER,
                           nil , dwError,  0 , @pBuffer,  0 ,  nil  );
   try 
    SetString( sErrorDecode, PChar( pBuffer ), dwLen );
   finally 
    LocalFree( pBuffer );
   end ;
  sError := Format( '%s'# 10 # 13 '0x%x %s', [ msg, dwError, sErrorDecode ] );
  Form1.Memo.Lines.Add( msg );
   Raise  Exception.Create( sError );
 end ;

 procedure  TForm1.Button1Click(Sender: TObject);
 var 
  pSignerCert: PCCERT_CONTEXT;
  hCertStoreHandle : HCERTSTORE;
  SigParams: CRYPT_SIGN_MESSAGE_PARA;
  pStreamIn, pStreamOut : TMemoryStream;
  MessageArray : PAPBYTE;
  MessageSize : PADWORD;
  MessageCert : PAPCCERT_CONTEXT;
  cbSignedMessageBlob: DWORD;
 begin 
  Memo.Clear;
  hCertStoreHandle := CertOpenSystemStore(  0 , PChar( CERT_STORE_NAME ));
   if  (  not  assigned( hCertStoreHandle ))  then 
    Err( Format( 'Ошибка при открытии хранилища: %s', [ CERT_STORE_NAME ] ));
   try 
    pSignerCert := CertFindCertificateInStore( hCertStoreHandle, MY_ENCODING_TYPE,  0 , CERT_FIND_SUBJECT_STR, PWideChar( SignerName ),  nil  );
     try 
       if  (  not  assigned( pSignerCert ))  then 
        Err( Format( 'Сертификат %s не найден', [ SignerName ] ));
      pStreamIn := TMemoryStream.Create;
      pStreamOut := TMemoryStream.Create;
       try 
        pStreamIn.LoadFromFile( 'd:\test.txt' );
        GetMem( MessageArray,  1  * SizeOf( PByte ));
        GetMem( MessageSize,  1  * SizeOf( DWORD ));
        GetMem( MessageCert,  1  * SizeOf( PAPCCERT_CONTEXT ));
        MessageArray[  1  ] := pStreamIn.Memory;
        MessageSize[  1  ] := pStreamIn.Size;
        MessageCert[  1  ] := pSignerCert;
        FillChar( SigParams, SizeOf( CRYPT_SIGN_MESSAGE_PARA ), # 0  );
        SigParams.cbSize := SizeOF( CRYPT_SIGN_MESSAGE_PARA );
        SigParams.dwMsgEncodingType := MY_ENCODING_TYPE;
        SigParams.pSigningCert := pSignerCert;
        SigParams.HashAlgorithm.pszObjId := szOID_RSA_MD5;
        SigParams.cMsgCert :=  1 ;
        SigParams.rgpMsgCert := MessageCert;
         if   not  ( CryptSignMessage( @SigParams, false,  1 , MessageArray, MessageSize,  nil , cbSignedMessageBlob ))  then 
          Err( 'Размер буфера' );
        pStreamOut.Size := cbSignedMessageBlob;
         if   not  ( CryptSignMessage( @SigParams, false,  1 , MessageArray, MessageSize, pStreamOut.Memory, cbSignedMessageBlob ))  then 
          Err( 'Файл не подписан' );
        pStreamOut.Size := cbSignedMessageBlob;
        pStreamOut.SaveToFile( 'd:\test.sig' );
        Memo.Lines.Add( 'Файл подписан' );
       finally 
        FreeAndNil( pStreamIn );
        FreeAndNil( pStreamOut );
       end ;
     finally 
      CertFreeCertificateContext(pSignerCert);
     end ;
   finally 
    CertCloseStore( hCertStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG );
   end ;
 end ;

 procedure  TForm1.Button2Click(Sender: TObject);
 var 
  VerifyParams : CRYPT_VERIFY_MESSAGE_PARA;
  pStreamIn, pStreamOut : TMemoryStream;
  cbDecodedMessageBlob : DWORD;
 begin 
  Memo.Clear;
  pStreamIn := TMemoryStream.Create;
  pStreamOut := TMemoryStream.Create;
   try 
    pStreamIn.LoadFromFile( 'd:\test.sig' );
    FillChar( VerifyParams, SizeOf( CRYPT_VERIFY_MESSAGE_PARA ), # 0  );
    VerifyParams.cbSize := SizeOf( CRYPT_VERIFY_MESSAGE_PARA );
    VerifyParams.dwMsgAndCertEncodingType := MY_ENCODING_TYPE;
     if   not  ( CryptVerifyMessageSignature( @VerifyParams,  0 , pStreamIn.Memory, pStreamIn.Size,
                                           nil , cbDecodedMessageBlob,  nil  ))  then 
      Err( 'Не удалось узнать размер буфера' );
    pStreamOut.Size := cbDecodedMessageBlob;
     if   not  ( CryptVerifyMessageSignature( @VerifyParams,  0 , pStreamIn.Memory, pStreamIn.Size,
                                          pStreamOut.Memory, cbDecodedMessageBlob,  nil  ))  then 
      Err( 'Не удалось проверить подпись' );
    pStreamOut.Size := cbDecodedMessageBlob;
    pStreamOut.SaveToFile( 'd:\test.res' );
    Memo.Lines.Add( 'Подпись верна' );
   finally 
    FreeAndNil( pStreamIn );
    FreeAndNil( pStreamOut );
   end ;
 end ;

у тебя прототипы функций неправильные... ты используешь очень странный алгоритм хеширования... он вообще вычисляется перепобором по-хорошему
Я заморачиваться не стал и просто вложил сертификат в подписанное attached сообщение... потому верификация выглядит так скромно... специфичных мементов в этом коде вагон и маленькая тележка... разбирайся... удачи
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34780301
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
потерял все парные FreeMem в коде есть утечки... только заметил
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #34781487
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Про код я уже писал. За основу взял СИшный пример с MSDN. Ну вообщем, спасибо. Будем разбираться, а там глядишь и знающий человек с отпуска вернется.

P.S: еще немного и я смело могу программистом идти работать :)
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35182159
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ты прогу домучал?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35216378
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня таже проблема. Попробовал код, любезно предоставленный Альт 'ом, но на строчке
Код: plaintext
1.
2.
 if   not  ( CryptSignMessage( @SigParams, false,  1 , MessageArray, MessageSize,  nil , cbSignedMessageBlob ))  then 
          Err( 'Размер буфера' );
вы дает ошибку "Access viol... in module wcrypt32.dll". Я не очень разбираюсь в алгоритмах всей этой криптографии... Мне просто нужно подписать сертификатом и проверить подпись. Может есть готовые решения или компоненты?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35217190
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Давайте сверять прототипы функций и типов. Я тоже.. в свое время... стучал головой в монитор... например вот такой нюанс:
WinCrypt.pas
Код: plaintext
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.
 {.$define CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS} 

 type 
  PCRYPT_SIGN_MESSAGE_PARA = ^CRYPT_SIGN_MESSAGE_PARA;
  CRYPT_SIGN_MESSAGE_PARA =  record 
    cbSize :DWORD;
    dwMsgEncodingType :DWORD;
    pSigningCert :PCCERT_CONTEXT;
    HashAlgorithm :CRYPT_ALGORITHM_IDENTIFIER;
    pvHashAuxInfo :PVOID;
    cMsgCert :DWORD;
    rgpMsgCert : PPCCERT_CONTEXT;
    cMsgCrl : DWORD;
    rgpMsgCrl : PPCCRL_CONTEXT;
    cAuthAttr :DWORD;
    rgAuthAttr :PCRYPT_ATTRIBUTE;
    cUnauthAttr :DWORD;
    rgUnauthAttr :PCRYPT_ATTRIBUTE;
    dwFlags :DWORD;
    dwInnerContentType :DWORD;
   {$ifdef CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS} 
    HashEncryptionAlgorithm : CRYPT_ALGORITHM_IDENTIFIER;
    pvHashEncryptionAuxInfo : DWORD;
   {$endif} 
   end ;
т.е. структура должна быть реально короче для операционок ниже XP/2003
Ну и давайте показывайте все ваши используемые прототипы... танцуя от CryptSignMessage
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35217573
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а вас не затруднило бы выложить фаил wincrypt.pas
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35217705
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спросите гугль по WinCrypt.pas


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35219435
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот этой части
Код: plaintext
1.
2.
3.
 {$ifdef CRYPT_SIGN_MESSAGE_PARA_HAS_CMS_FIELDS} 
    HashEncryptionAlgorithm : CRYPT_ALGORITHM_IDENTIFIER;
    pvHashEncryptionAuxInfo : DWORD;
   {$endif} 
там не оказалось. Т.е. все одинаковое кроме условной директивы.
АльтНу и давайте показывайте все ваши используемые прототипы... танцуя от CryptSignMessage
Т.е. мне сюда выложить исходники всех используемых прототипов?
Код: plaintext
1.
2.
3.
4.
5.
6.
 function  CryptSignMessage(pSignPara :PCRYPT_SIGN_MESSAGE_PARA;
                          fDetachedSignature :BOOL;
                          cToBeSigned :DWORD;
                     const  rgpbToBeSigned : array   of  PBYTE;
                          rgcbToBeSigned : array   of  DWORD;
                          pbSignedBlob :PBYTE;
                          pcbSignedBlob :PDWORD):BOOL ; stdcall;
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 function  CryptVerifyMessageSignature(pVerifyPara :PCRYPT_VERIFY_MESSAGE_PARA;
                                     dwSignerIndex :DWORD;
                                const  pbSignedBlob :PBYTE;
                                     cbSignedBlob :DWORD;
                                     pbDecoded :PBYTE;
                                     pcbDecoded :DWORD;
                                     ppSignerCert :PCCERT_CONTEXT
                                     ):BOOL ; stdcall;
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 function  CertFindCertificateInStore(hCertStore :HCERTSTORE;
                                    dwCertEncodingType :DWORD;
                                    dwFindFlags :DWORD;
                                    dwFindType :DWORD;
                               const  pvFindPara :PVOID;
                                    pPrevCertContext :PCCERT_CONTEXT
                                    ):PCCERT_CONTEXT ; stdcall;
Вроде больше ничего такого не используется...
И еще попутный вопрос: как вообще устроена логика? В системе установлены сертификаты (на некоторых несколько различных). Пользователь нажимает кнопку "Подписать", после этого он должен выбрать нужный сертификат и предоставив носитель (дикету или SmartCard или еще что) и введя пароль запускается процедура подписания? При этом в нашем примере мы вкладываем сертификат в подписаный документ, поэтому не надо устанавливать все сертификаты явно? Я вообще не несу чушь? )))) Давайте объясню задачу: у нас разрабатывается ПО "Делопроизводство". Сечас уже эксплуатируется в некотором объеме и постепенно наращиваем функционал. Ну вот начальство придумало чтобы документы были полность в электронном виде. Т.е. докладные, приказы, распоряжения и пр. были подписаны цифровой подписью. Кроме того так же буду проходить согласования тех. задания и договора. Внутри предприятия розданы всем СмакртКарты с уже выданными сертификатами от сервера. Естественно этого достаточно для документов внутри компании. Но вот не надо ли будет устанавливать каждому ВСЕ выданные сертификаты чтобы прошла проверка подписи? Сорри если сильно путано рассказал.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35220136
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем причину AV я вижу и она типична. Заголовочник содержит неправильные типы. Джеди-тим конечно подложила большую свинью всем дельфистам. Всегда сверяйте прототипы с оригиналами в msdn. Например, чтобы много не переделывать, можно привести все к такому типу:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
 type 
  TByteArray =  Array   of  PByte;
  PByteArray = ^TByteArray;
  TDWordArray =  Array   of  DWORD;
  PDWordArray = ^TDWordArray;
  TPCCertContextArray =  Array   of  PCCERT_CONTEXT;
  PPCCertContextArray = ^TPCCertContextArray;

 function  CryptSignMessage(  var  pSignPara : CRYPT_SIGN_MESSAGE_PARA;
                           fDetachedSignature : BOOL;
                           cToBeSigned :DWORD;
                      const  rgpbToBeSigned : PByteArray;
                           rgcbToBeSigned : PDWordArray;
                           pbSignedBlob : PBYTE;
                            var  pcbSignedBlob : DWORD ) : BOOL; stdcall;

и, соответственно, поменяется реализация подписи...

Код: plaintext
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.
 var 
  ...
  MessageArray : TByteArray;
  MessageSize : TDWordArray;
  MessageCert : TPCCertContextArray;
  ...
 begin 
   ...
     try 
      pStreamIn := TMemoryStream.Create;
      pStreamOut := TMemoryStream.Create;
      SetLength( MessageArray,  1  );
      SetLength( MessageSize,  1  );
      SetLength( MessageCert,  1  );
       try 
        pStreamIn.LoadFromFile( 'c:\test.txt' );
        MessageArray[  0  ] := pStreamIn.Memory;
        MessageSize[  0  ] := pStreamIn.Size;
        MessageCert[  0  ] := pSignerCert;
        FillChar( SigParams, SizeOf( CRYPT_SIGN_MESSAGE_PARA ),  0  );
        SigParams.cbSize := SizeOF( CRYPT_SIGN_MESSAGE_PARA );
        SigParams.dwMsgEncodingType := MY_ENCODING_TYPE;
        SigParams.pSigningCert := pSignerCert;
        SigParams.HashAlgorithm.pszObjId := szOID_RSA_MD5;
        SigParams.cMsgCert :=  1 ;
        SigParams.rgpMsgCert := Pointer( MessageCert );
         if  (  not  ( CryptSignMessage( SigParams, false,  1 , Pointer( MessageArray ), Pointer( MessageSize ),  nil , cbSignedMessageBlob )))  then 
          Err( 'Размер буфера' );
        pStreamOut.Size := cbSignedMessageBlob;
         if   not  ( CryptSignMessage( SigParams, false,  1 , Pointer( MessageArray ), Pointer( MessageSize ), pStreamOut.Memory, cbSignedMessageBlob ))  then 
          Err( 'Файл не подписан' );
        pStreamOut.Size := cbSignedMessageBlob;
        pStreamOut.SaveToFile( 'c:\test.sig' );
        Memo.Lines.Add( 'Файл подписан' );
       finally 
        FreeAndNil( pStreamIn );
        FreeAndNil( pStreamOut );
       end ;
    ...
 end ;

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

зы: а где будет храниться приватный ключ дело ваше, на отчужденных ключевых носителях, в реестре или еще где, тут скорее только вопрос стоимости развертывания решения и требований к конфиденциальности от вашей СБ. Я работал и с параноиками и жадными ит-директорами. Везде свои плюсы ))))))


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35222389
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а еще вопрос какая версия делфи использовалась?
у меня половина величин не распознается компилятором, на пример типы данных DWORD Cardinal
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35222619
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uses Windows?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35222636
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а вот еще вопрос тут выложен пример но он ссылается на TForm1 с описанием пареметров окна. можно ли посмотреть код TForm1 для этого примера
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35222638
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я его выдумал 5 сентября 2007 года... т.е. более 6 месяцев назад... просто глядя на код LimonFX... никакого кода у меня нет... что именно вам не понятно? старайтесь задавать вопросы в топике по криптографии, а не по базовым знаниям программирования


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35222678
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
просто я привык разбираться во всем сам, на примерах, а для этого нужна полностью рабочая прога. я писал анологичную прогу на си на базе примера из мсдн, там у меня все получилось. а здесь ничего не выходит:(
ладно буду дальше стараться понять
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35222863
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Статей хватает за оба глаза, например:
http://rsdn.ru/article/crypto/cryptoapi.xml
Ну и... http://www.podgoretsky.com/ftp/Docs/Delphi/CryptoAPI/
В оригинале это ^^ было тремя или четырьмя статьями... потому есть мысль, что Анатолий что-то потерял при выкладывании
На предыдущей странице я давал ссылку на готовые примеры от компании КриптоПро
http://www.cryptopro.ru/cryptopro/products/csp/20/sample-2-0.zip
Ну и msdn, который стал уже давно бесплатным
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223035
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо я пополним мою коллекцию програмных кодов на эту тему:)
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223063
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovankaспасибо я пополним мою коллекцию програмных кодов на эту тему:)
пока вы что-то там копите... другие уже выписали XEnroll, CAPICOM и CNG )
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223292
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ну пример проги http://www.cryptopro.ru/cryptopro/products/csp/20/sample-2-0.zip на си:(
на си у меня у самого есть:( причем собственного написания
а остальные две ссылки я уже давно изучаю. у меня это уже есть:(
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223310
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovankaну пример проги http://www.cryptopro.ru/cryptopro/products/csp/20/sample-2-0.zip на си:(
на си у меня у самого есть:( причем собственного написания
можете подобное... идите в криптографы, а не тусуйтесь среди прикладников
какая разница, какой язык из типовых для программирования... ведь это лишь инструмент
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223320
Артем_84
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovanka на си у меня у самого есть:( причем собственного написания
Ох, как это гордо было сказано



Согласен с Альтом
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223530
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
я очень плохой програмист
а цифровая подпись это мой диплом
я в курсаче написал консольную прогу на си, теперь одна из поставленных задач это написать прогу на делфи с оконным интерфейсом возможностью выбора ключа из опр контейнера и нужного куска внутри текста для подписи. но вот на дефи у меня ничего не выходит:(
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35223563
Карабас Барабас
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovanka
v> я очень плохой програмист
v> а цифровая подпись это мой дипломну и зачем всё это ?
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35224124
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovankaя в курсаче написал консольную прогу на си, теперь одна из поставленных задач это написать прогу на делфи с оконным интерфейсом возможностью выбора ключа из опр контейнера и нужного куска внутри текста для подписи. но вот на дефи у меня ничего не выходит:(

В вашем задании нет ничего по теме топика... тут разбираются симпл-функции, а вам нужны лишь базовые... CryptAcquireContext/CryptReleaseContext, CryptGenKey/CryptExportKey, CryptCreateHash/CryptHashData/CryptDestroyHash и CryptSignHash/CryptVerifySignature... т.е. достаточно открыть/создать контейнер, открыть/создать ключевую пару, посчитать хеш по любым данным и зашифровать полученный хеш приватным ключем, экспортировать публичный ключ... все это есть в первых двух частях статьи про защиту секретов. Ничего не выходит потому, что вы лентяй и нюня. Начните писать хоть что-то приблизительно работающее и по ходу вашей работы я смогу ответить на вопросы.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35228692
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Альт

Блин перепробовал все...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
        SigParams.cMsgCert :=  1 ;
        SigParams.rgpMsgCert := Pointer( MessageCert );
         if  (  not  ( CryptSignMessage( SigParams, false,  1 , Pointer( MessageArray ),
          Pointer( MessageSize ),  nil , Pointer( cbSignedMessageBlob ))))  then 
          Err( 'Размер буфера' );
        pStreamOut.Size := cbSignedMessageBlob;
         if   not  ( CryptSignMessage( SigParams, false,  1 , Pointer( MessageArray ),
          Pointer( MessageSize ), pStreamOut.Memory, Pointer( cbSignedMessageBlob )))  then 
          Err( 'Файл не подписан' );
        pStreamOut.Size := cbSignedMessageBlob;
        pStreamOut.SaveToFile( 'c:\test.sig' );
        Memo1.Lines.Add( 'Файл подписан' );

С переменным успехом оба раза функция выполняется и даже создается файл test.sig. Но размер у него 9 255 712 и весь заполнен пустыми значениями. Пробовал в объявлении функции писать не CRYPT_SIGN_MESSAGE_PARA а PCRYPT_SIGN_MESSAGE_PARA. Результат тот же. Но сечас и так не работает. Опять Access viol... crypt32.dll.
Пытался очистить StreamOut.Clear. Но так вообще не пашет.

Я уже готов оговорить сумму за работоспособный код.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35228712
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спокойствие, смотрим на последний параметр в моем определении функции

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 function  CryptSignMessage(  var  pSignPara : CRYPT_SIGN_MESSAGE_PARA;
                           fDetachedSignature : BOOL;
                           cToBeSigned :DWORD;
                      const  rgpbToBeSigned : PByteArray;
                           rgcbToBeSigned : PDWordArray;
                           pbSignedBlob : PBYTE;
                            var  pcbSignedBlob : DWORD ) : BOOL; stdcall;

И, само собой, в моем коде нет Pointer( cbSignedMessageBlob ) и быть не может, в принципе.
Штатные телепаты подсказывают, что у вас в объявлении сидит
Код: plaintext
                           pcbSignedBlob : PDWORD ) : BOOL; stdcall;
что в корне неверно


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35228717
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя... вам можно написать и так:
Код: plaintext
@cbSignedMessageBlob
получатся теже яйца, только в профиль... но уж точно не надо писать Pointer( cbSignedMessageBlob ) %)


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35228727
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да про Pointer это я пытался различные варианты испробовать. Ну ессно отправил неправильный код. Сорри. Все что я говорил касалось и исходного варианта.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35228733
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MiktorДа про Pointer это я пытался различные варианты испробовать. Ну ессно отправил неправильный код. Сорри. Все что я говорил касалось и исходного варианта.
Не обманывайте меня... я не спал 20 часов за себя не ручаюсь. Вот попытка компиляции с Pointer( cbSignedMessageBlob )
Код: plaintext
[Error] test.pas(100): Types of actual and formal var parameters must be identical
на моем типе функции. выкладывайте полный ваш тестовый компилируемый и не работающий вариант и сертификат тоже
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35228772
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просто у меня действительно в прототипе было
Код: plaintext
1.
...
pcbSignedBlob :PDWORD):BOOL ; stdcall;
Поэтому
Альт[Error] test.pas(100): Types of actual and formal var parameters must be identical
не выскакивало и все компилировалось.
Хорошо. Вот прототип
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
 type 
  TByteArray =  Array   of  PByte;
  PByteArray = ^TByteArray;
  TDWordArray =  Array   of  DWORD;
  PDWordArray = ^TDWordArray;
  TPCCertContextArray =  Array   of  PCCERT_CONTEXT;
  PPCCertContextArray = ^TPCCertContextArray;
...
 function  CryptSignMessage(pSignPara :CRYPT_SIGN_MESSAGE_PARA;
                          fDetachedSignature :BOOL;
                          cToBeSigned :DWORD;
                     const  rgpbToBeSigned :PByteArray;
                          rgcbToBeSigned :PDWordArray;
                          pbSignedBlob :PBYTE;
                          pcbSignedBlob :PDWORD):BOOL ; stdcall;
Вот процедура
Код: plaintext
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.
 procedure  TForm1.Button1Click(Sender: TObject);
 var 
  pSignerCert: PCCERT_CONTEXT;
  hCertStoreHandle : HCERTSTORE;
  SigParams: CRYPT_SIGN_MESSAGE_PARA;
  pStreamIn, pStreamOut : TMemoryStream;
  MessageArray : TByteArray;
  MessageSize : TDWordArray;
  MessageCert : TPCCertContextArray;
  cbSignedMessageBlob: DWORD;
 begin 
  Memo1.Clear;
  hCertStoreHandle := CertOpenSystemStore(  0 , PChar( CERT_STORE_NAME ));
   if  (  not  assigned( hCertStoreHandle ))  then 
    Err( Format( 'Îøèáêà ïðè îòêðûòèè õðàíèëèùà: %s', [ CERT_STORE_NAME ] ));
   try 
    pSignerCert := CertFindCertificateInStore( hCertStoreHandle, MY_ENCODING_TYPE,  0 ,
 CERT_FIND_SUBJECT_STR, PWideChar( SignerName ),  nil  );
    cbSignedMessageBlob :=  0 ;
     try 
       if  (  not  assigned( pSignerCert ))  then 
        Err( Format( 'Ñåðòèôèêàò %s íå íàéäåí', [ SignerName ] ));
      pStreamIn := TMemoryStream.Create;
      pStreamOut := TMemoryStream.Create;
      SetLength( MessageArray,  1  );
      SetLength( MessageSize,  1  );
      SetLength( MessageCert,  1  );
       try 
        pStreamIn.LoadFromFile( 'c:\Test.txt' );
        MessageArray[  0  ] := pStreamIn.Memory;
        MessageSize[  0  ] := pStreamIn.Size;
        MessageCert[  0  ] := pSignerCert;
        FillChar( SigParams, SizeOf( CRYPT_SIGN_MESSAGE_PARA ),  0  );
        SigParams.cbSize := SizeOF( CRYPT_SIGN_MESSAGE_PARA );
        SigParams.dwMsgEncodingType := MY_ENCODING_TYPE;
        SigParams.pSigningCert := pSignerCert;
        SigParams.HashAlgorithm.pszObjId := szOID_RSA_MD5;
        SigParams.cMsgCert :=  1 ;
        SigParams.rgpMsgCert := Pointer( MessageCert );
         if  (  not  ( CryptSignMessage( SigParams, false,  1 , Pointer( MessageArray ),
          Pointer( MessageSize ),  nil , cbSignedMessageBlob )))  then 
          Err( 'Ðàçìåð áóôåðà' );
        pStreamOut.Size := cbSignedMessageBlob;
        pStreamOut.Clear;
         if   not  ( CryptSignMessage( SigParams, false,  1 , Pointer( MessageArray ),
          Pointer( MessageSize ), pStreamOut.Memory, cbSignedMessageBlob ))  then 
          Err( 'Ôàéë íå ïîäïèñàí' );
        pStreamOut.Size := cbSignedMessageBlob;
        pStreamOut.SaveToFile( 'c:\test.sig' );
        Memo1.Lines.Add( 'Ôàéë ïîäïèñàí' );
       finally 
        FreeAndNil( pStreamIn );
        FreeAndNil( pStreamOut );
        FreeAndNil( SigParams );
       end ;
     finally 
      CertFreeCertificateContext(pSignerCert);
     end ;
   finally 
    CertCloseStore( hCertStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG );
   end ;
 end ;
В доказательство прикалываю скриншот ))))
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35229158
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Боже мой
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 function  CryptSignMessage(pSignPara :CRYPT_SIGN_MESSAGE_PARA;
                          fDetachedSignature :BOOL;
                          cToBeSigned :DWORD;
                     const  rgpbToBeSigned :PByteArray;
                          rgcbToBeSigned :PDWordArray;
                          pbSignedBlob :PBYTE;
                          pcbSignedBlob :PDWORD):BOOL ; stdcall;
ну найдете уже два отличия с моим:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 function  CryptSignMessage(  var  pSignPara : CRYPT_SIGN_MESSAGE_PARA;
                           fDetachedSignature : BOOL;
                           cToBeSigned :DWORD;
                      const  rgpbToBeSigned : PByteArray;
                           rgcbToBeSigned : PDWordArray;
                           pbSignedBlob : PBYTE;
                            var  pcbSignedBlob : DWORD ) : BOOL; stdcall;

И, что характерно, опять обманываете... вы уже сами запутались с каким именно юнитом WinCrypt у вас реально компилируется приложение... т.к. простая проверка на
Код: plaintext
pcbSignedBlob :PDWORD):BOOL ; stdcall;
и попыткой собрать приложение с
Код: plaintext
 nil , cbSignedMessageBlob )))  then 
приводит к ошибке:
Код: plaintext
[Error] test.pas(98): Incompatible types: 'Cardinal' and 'PDWORD'
А я тем временем медленно, но верно приближаюсь к целым рабочим суткам


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35231514
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Намек понял ) Готов возместить пивом потраченое на меня время )
На самом деле огоромное спасибо. Все подписывает.
Если я еще не довел до белого коленя...
Как теперь вывести на экран информацию о том кто подписал?
Да, и вторая процедура тоже компилируется, но при втором вызове CryptVerifyMessageSignature говорит что "Не удалось проверить подпись". :(
И еще... сверял с MSDN протопит фукнции CryptVerifyMessageSignature... там почемуто pbSignedBlob и pbDecoded объявлены как BYTE. ( вот ).
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35232486
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну раз на проверке сертификата не скандалит на структуру "подписи", значит и правда подписали удачно... чтобы опять не переделывать код... поменяйте тип так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
 function  CryptVerifyMessageSignature(pVerifyPara :PCRYPT_VERIFY_MESSAGE_PARA;
                                     dwSignerIndex :DWORD;
                                const  pbSignedBlob :PBYTE;
                                     cbSignedBlob :DWORD;
                                     pbDecoded :PBYTE;
                                     pcbDecoded :DWORD;
                                     ppSignerCert :PCCERT_CONTEXT
                                     ):BOOL ; stdcall;


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 function  CryptVerifyMessageSignature( pVerifyPara : PCRYPT_VERIFY_MESSAGE_PARA;
                                      dwSignerIndex : DWORD;
                                 const  pbSignedBlob : PBYTE;
                                      cbSignedBlob : DWORD;
                                      pbDecoded : PBYTE;
                                  var   pcbDecoded : DWORD;
                                      ppSignerCert : PCCERT_CONTEXT
                                     ) : BOOL; stdcall;                                     

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
BOOL WINAPI CryptVerifyMessageSignature(
  __in       PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  __in       DWORD dwSignerIndex,
  __in       const BYTE* pbSignedBlob,
  __in       DWORD cbSignedBlob,
  __out      BYTE* pbDecoded,
  __inout    DWORD* pcbDecoded,
  __out_opt  PCCERT_CONTEXT* ppSignerCert
);

вроде все.


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35234551
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да у меня так и сделано. Вот только при проверке - "Не удалось проверить подпись. 0x80090006 Неправильная подпись." :(
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35237094
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>на проверке сертификата
это не я писал... это демоны...

Выложите уже эту "подпись"... я не телепат... я программист


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35257716
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
мне нужно включить в прграмму возможность выбора криптопровайдера из всех возможных. подскажите пожалуйста функцию в дельфи позволяющую вывести список всех доступных криптоправайдеров
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35258461
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет, vovanka!
Ты пишешь:

vovankav> мне нужно включить в прграмму возможность выбора криптопровайдера из всех возможных.
смотри описание Predefined Provider Types

--
With best regards, Мимопроходящий.

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35258502
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovankaмне нужно включить в прграмму возможность выбора криптопровайдера из всех возможных. подскажите пожалуйста функцию в дельфи позволяющую вывести список всех доступных криптоправайдеров

перебираете функциями CryptEnumProviderTypes/CryptEnumProviders начиная с Index = 0 до тех пор пока не вернет ошибку ERROR_NO_MORE_ITEMS
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35258659
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя стоп... vovanka, вы вообще читали ссылки, которые тут приводились по нескольку раз... вот первое же с CryptEnumProviders...
http://www.podgoretsky.com/ftp/Docs/Delphi/CryptoAPI/list2.htm
лень - это ваша беда


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35263340
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Альт

Вот файлик с подписью...
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35264814
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сейчас мозг себе сломаю... подпись правильна


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35265064
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Структурно правильная. Подпись заявлена именно от того сертификата, который в нее и вложен, дата использования у сертификата не просрочена, в szOID_KEY_USAGE (Digital Signature заявлено)... но на проверке получаю стабильное "0x80090006 Invalid Signature."... одолевает, кучу времени убил на перепроверках. Смущает внушительный список Extension, может использование сертификата ограничивает одна из них. Сейчас у меня уже каша в голове и не получается сообразить (может что-то в szOID_ENHANCED_KEY_USAGE).

Вадим, давайте проведем эксперимент, я выкладываю самоподписной сертификат с приватным ключем вообще без ограничений на использование и подпись с моей машины. Проверяем в два этапа:
1. На первом просто валидируете мою подпись. Если все ок. Двигаемся дальше.
2. На втором вы импортируете сертификат с паролем 123, включив приватный ключ. Устанавливаете его в пользовательское хранилище и до кучи в хранилище доверенных корневых центров.
Пользователь для поиска DPN, подписываете и проверяете подпись. Если опять все ок, то разбираемся с областью использования вашего сертификата.


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35266022
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Понял. Попробую. (я уже чуствую что пивом не обойдусь )
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35266023
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все проходит на ура. И проверка вашего файла и подпись и проверка на месте.

Miktor
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35266516
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем моя теория, что виноваты KU/EKU не подтвердилась, в приложении к посту проверочный сертификат с приватным ключем (пароль тот же, пользователь при поиске Test). Есть последняя мысль, что надо обязательно кормить систему корневым сертификатом и списком отзыва (у меня на проверке он конечно нагибает сеть, но по заявленным в сертификате путям и для CS-ROOTDC.crl и для CS-ROOTDC.crt ничего нет). Выложите их
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35267427
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проверочный сертификат тоже все подписал и проверил успешно. У меня есть 3 корневых сертификата с именем CS-ROOTDC. Выложил в архиве...
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35267750
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зачем вам столько перевыпусков (да еще и не цепочкой)? Подошел второй. Перепроверил до кучи самую тоску Application Certificate Policy (szOID_APPLICATION_CERT_POLICIES = '1.3.6.1.4.1.311.21.10')
Подписывает!, что с политикой:
XCN_OID_KP_DOCUMENT_SIGNING = 1.3.6.1.4.1.311.10.3.12
The certificate can be used for signing documents.
Вот по этому списку , что без него (как у вас).
Все. Больше в сертификате нет узких мест. Вы морочите мне голову. Ваш сертификат выпущен от другой ключевой пары. Либо пара была пересоздана позднее. Очень жаль потраченное время.
Ключевые пары обычно вообще не пересоздаются или в редких чп случаях... вроде ситуации компрометации. И корневые сертификаты так тоже не пересоздаются. Отформатируйте ключевой носитель. Создайте чистую пару. Создайте запрос своему ца именно от этой пары и выпустите на нем (текущем!) нормальный сертификат


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35268459
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все стихло... я забыл последние тестовые сертификаты прикрепить. Корневой с приватным ключем для хранилища доверенных корневых. И тестовый, копия по всем ключевым атрибутам обсуждаемого. Пароли 123. И, в принципе, мне больше нечего добавить к теме симпл-функций. Все работает, если делать правильно
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35270019
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Большущее спасибо. Удалил лишние корневые пары и все заработало. Надеюсь все-таки что время потрачено не зря и топик будет полезен еще кому-нибудь.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35295786
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Снова я...
Хочу вывести информацию о подписи (сертификате)
Код: plaintext
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.
  pSignerCert: PCCERT_CONTEXT;
  CertInfo: CERT_INFO;
  VerifyParams : CRYPT_VERIFY_MESSAGE_PARA;
  pStreamIn, pStreamOut : TMemoryStream;
  cbDecodedMessageBlob : DWORD;
  MemAddr: Cardinal;
  hCertStoreHandle : HCERTSTORE;
 begin 
  Memo1.Clear;
  pStreamIn := TMemoryStream.Create;
  pStreamOut := TMemoryStream.Create;
   //if ( not assigned( hCertStoreHandle )) then 
   //  Err( Format( 'Îøèáêà ïðè îòêðûòèè õðàíèëèùà: %s', [ CERT_STORE_NAME ] )); 
   try 
     //pSignerCert := CertFindCertificateInStore( hCertStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, PWideChar( SignerName ), nil ); 
    pStreamIn.LoadFromFile( 'c:\test.sig' );
    FillChar( VerifyParams, SizeOf( CRYPT_VERIFY_MESSAGE_PARA ), # 0  );
    VerifyParams.cbSize := SizeOf( CRYPT_VERIFY_MESSAGE_PARA );
    VerifyParams.dwMsgAndCertEncodingType := MY_ENCODING_TYPE;
     if   not  ( CryptVerifyMessageSignature( @VerifyParams,  0 , pStreamIn.Memory, pStreamIn.Size,
                                           nil , cbDecodedMessageBlob,  nil  ))  then 
      Err( 'Íå óäàëîñü óçíàòü ðàçìåð áóôåðà' );
    pStreamOut.Size := cbDecodedMessageBlob;
     if   not  ( CryptVerifyMessageSignature( @VerifyParams,  0 , pStreamIn.Memory, pStreamIn.Size,
                                          pStreamOut.Memory, cbDecodedMessageBlob,  nil  ))  then 
      Err( 'Íå óäàëîñü ïðîâåðèòü ïîäïèñü' );
    pStreamOut.Size := cbDecodedMessageBlob;
    pStreamOut.SaveToFile( 'c:\test.res' );
    Memo1.Lines.Add( 'Ïîäïèñü âåðíà' );
    FillChar(CertInfo, SizeOf(CERT_INFO), # 0 );
    hCertStoreHandle := CertOpenSystemStore(  0 , PChar( CERT_STORE_NAME ));
    pSignerCert := VerifyParams.pfnGetSignerCertificate(VerifyParams.pvGetArg,
                                                        X509_ASN_ENCODING  or  PKCS_7_ASN_ENCODING,
                                                        @CertInfo,
                                                        hCertStoreHandle);
    Memo1.Lines.Add('Äî: '+DateTimeToStr(CertInfo.NotAfter.dwHighDateTime+CertInfo.NotAfter.dwLowDateTime));
   finally 
    FreeAndNil( pStreamIn );
    FreeAndNil( pStreamOut );
   end ;

Но ругается в функции pfnGetSignerCertificate на AccessViol...
Может кто знает в чем тут дело? Сама проверка проходит нормально. Структура CertInfo благополучно заполняется 0-ми... Чего ему еще надо?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35295898
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет, а это снова я... душевно сидим ) похоже, что тема больше никому не интересна...
Между вашей постановкой задачи и реализацией мало связей... или я опять не понял ваш код. Вам нужно поймать контексты сертификатов... и сделать это можно кучей способов... хотите про pfnGetSignerCertificate, давайте... она является калбек функцией и вызывается крипто ядром для поиска сертификата еще на этапе валидации ... сама attached подпись является, если утрировать, хранилищем сертификатов... вы делаете странные вещи… занулили структуру VerifyParams, а потом пытаетесь вызвать pfnGetSignerCertificate с нулевого адреса… какой в этом смысл? только не говорите, что в мсдн именно так выглядит пример...

Я не знаю, что придумать, чтобы нам не лезть в дебри… давайте просто отработаем калбек и переберем сертификаты в подписи…
Код: plaintext
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.
 function  CompareCertificateInfo(  const  Base, Comp: PCERT_INFO ) : Boolean;
 var  iSize : DWORD;
 begin 
  iSize := Base.SerialNumber.cbData;
   if  iSize > Comp.SerialNumber.cbData  then 
    iSize := Comp.SerialNumber.cbData;
  Result := CompareMem( Base.SerialNumber.pbData, Comp.SerialNumber.pbData, iSize );
 end ;

 function  GetSignerCertificate( pvGetArg: PVOID; dwCertEncodingType: DWORD; pSignerId: PCERT_INFO;
          hMsgCertStore: HCERTSTORE  ) : PCCERT_CONTEXT; stdcall;
 begin 
  Result :=  nil ;
   repeat 
    Result := CertEnumCertificatesInStore( hMsgCertStore, Result );
     if  Assigned( Result )  then 
       if  CompareCertificateInfo( pSignerId, Result.pCertInfo )  then 
        Break;
   until   not  assigned( Result );
 end ;

...
 var 
  Certificate : PCCERT_CONTEXT;
  VerifyParams : CRYPT_VERIFY_MESSAGE_PARA;
  pStreamIn, pStreamOut : TMemoryStream;
  cbDecodedMessageBlob : DWORD;
 begin 
  Memo.Clear;
  pStreamIn := TMemoryStream.Create;
  pStreamOut := TMemoryStream.Create;
   try 
    pStreamIn.LoadFromFile( 'c:\test.sig' );
    FillChar( VerifyParams, SizeOf( CRYPT_VERIFY_MESSAGE_PARA ), # 0  );
    VerifyParams.cbSize := SizeOf( CRYPT_VERIFY_MESSAGE_PARA );
    VerifyParams.dwMsgAndCertEncodingType := MY_ENCODING_TYPE;
    VerifyParams.pfnGetSignerCertificate := @GetSignerCertificate;
     if   not  ( CryptVerifyMessageSignature( VerifyParams,  0 , pStreamIn.Memory, pStreamIn.Size,
                                           nil , cbDecodedMessageBlob,  nil  ))  then 
      Err( 'Не удалось узнать размер буфера' );
    pStreamOut.Size := cbDecodedMessageBlob;
    Memo.Lines.Add( IntToStr( cbDecodedMessageBlob ));
     if   not  ( CryptVerifyMessageSignature( VerifyParams,  0 , pStreamIn.Memory, pStreamIn.Size,
                                          pStreamOut.Memory, cbDecodedMessageBlob, @Certificate ))  then 
      Err( 'Не удалось проверить подпись' );
    pStreamOut.Size := cbDecodedMessageBlob;
    pStreamOut.SaveToFile( 'c:\test.res' );
    Memo.Lines.Add( 'Подпись верна' );
     { тут можно делать с контекстом серитфиката все, что вашей душе угодно } 
     if   not  ( CertFreeCertificateContext( Certificate ))  then 
      Err( 'Не удалось удалить контекс сертификата' );
   finally 
    FreeAndNil( pStreamIn );
    FreeAndNil( pStreamOut );
   end ;
 end ;

а вообще вам все это не нужно... калбек интересен, например, когда мы хотим работать с альтернативными хранилищами сертификатов... например бд... лучше посмотрите на описание последнего параметра CryptVerifyMessageSignature, до CertFreeCertificateContext вы можете все что угодно делать в полученным в Certificate контекстом сертификата подписавшего...


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35296567
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что-то у меня только сейчас мозг включился... исправляю дополнительную функцию сравнения...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 function  CompareBlob(  const  Base, Comp: PCRYPTOAPI_BLOB ) : Boolean;
 begin 
  Result := ( Base.cbData = Comp.cbData );
   if  Result  then 
    Result := CompareMem( Base.pbData, Comp.pbData, Base.cbData );
 end ;

 function  CompareCertificateInfo(  const  Base, Comp: PCERT_INFO ) : Boolean;
 begin 
  Result := CompareBlob( @Base.Issuer, @Comp.Issuer )  and 
            CompareBlob( @Base.SerialNumber, @Comp.SerialNumber );
 end ;
извиняюсь за неточность


Скажи, что с нами будет, если нам дадут все ни за что,
Мы умрем в изумрудах, не сказав ничего (с) Магнитная Аномалия - В Изумрудах
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35298099
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
интересна, я ее постоянно читаю
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35301200
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да нет, это я извиняюсь за безграмотную постановку. Надо было действительно внимательней прочиться описание функции CryptVerifyMessageSignature. Кажется это все что мне надо. Т.е. хотелось бы подписать документ (проверив его валидность по срокам), потом проверить правильность подписи и в случае необходимости вывести информацию о сертификате. Больше ничего не надо. Ну может быть еще при настройке клиента, вывести список его личных сертификатов, чтобы выбрать тот, которым он будет подписывать. Но это можно сделать и в ручную.
И опять же спасибо за помощ.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35301225
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще вопрос. (может не в тему) Не могу получить дату из CertInfo.NotAfter. Пытаюсь
Код: plaintext
1.
2.
3.
4.
5.
 Var 
  FileTime: DWORD;
...
    LongRec(FileTime).Lo := CertInfo.NotAfter.dwLowDateTime;
    LongRec(FileTime).Hi := CertInfo.NotAfter.dwHighDateTime;
    Memo1.Lines.Add('Äî: '+DateTimeToStr(FileDateToDateTime(FileTime)));

Выдает 1982 год. Ну вообще не ту дату. Нашел функцию
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 function  FileDate2DateTime(FileTime : tFileTime) : tDateTime;
 var  LocalTime : tFileTime;
    DOSFileTime : DWord;
 begin 
  FileTimeToLocalFileTime(LocalTime, LocalTime);  // Compensate for time zone 
  FileTimeToDosDateTime(FileTime,  LongRec(DOSFileTime).Hi,
     LongRec(DOSFileTime).Lo);
  Result := FileDateToDateTime(DOSFileTime);
 end ;
но результат тоже не тот. Совсем не тот. Че не так-то?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35301561
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Валидация срока использования пойманного контекста выполняется, например, вызовом в лоб:
Код: plaintext
Win32Check( CertVerifyTimeValidity(  nil , Certificate.pCertInfo ) =  0  );

функция разбора дат
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
 function  DecodeDate( FileTime : TFileTime ) : TDateTime;
 var 
  SystemTime : TSystemTime;
  ModifiedTime : TFileTime;
 begin 
  FileTimeToLocalFileTime( FileTime, ModifiedTime );
  FileTimeToSystemTime( ModifiedTime, SystemTime );
  Result := SystemTimeToDateTime( SystemTime );
 end ;

пример вызова
Код: plaintext
1.
2.
3.
4.
  ...
  DateTimeToStr( DecodeDate( Certificate.pCertInfo.NotBefore ))
  DateTimeToStr( DecodeDate( Certificate.pCertInfo.NotAfter ))
  ...

А вообще я не гордый и бедный... принимаю любые суммы на вебмани счет R153279149005
Раз уж писать код... тем более профильный, то делать это надо за вознаграждение.
С уважением, Павел Данченко
http://cryptocode.ru
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35305487
Фотография Miktor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дык я вроде сразу предлагал :) (найду где продаются ВебМани обязательно отблагодарю)
С датами все получилось. Спасибо. Последние 2 маленьких вопроса: Как получить имя серт. центра и владельца сертификата?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35305588
renaton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MiktorДык я вроде сразу предлагал :) (найду где продаются ВебМани обязательно отблагодарю)
С датами все получилось. Спасибо. Последние 2 маленьких вопроса: Как получить имя серт. центра и владельца сертификата?

не сможешь поделицца исходниками?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35306332
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Miktor, упрощенно вот так...
Код: plaintext
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.
 procedure  BinToHexInverted( Buffer, Text: PChar; BufSize: Integer);
 const 
  Convert :  Array  [  0 .. 15  ]  of  Char = '0123456789abcdef';
 var 
  ii : Integer;
 begin 
   for  ii := BufSize -  1   downto   0   do 
   begin 
    Text[  0  ] := Convert[ Byte( Buffer[ ii ])  shr   4  ];
    Text[  1  ] := Convert[ Byte( Buffer[ ii ])  and  $F ];
    Inc( Text,  2  );
   end ;
 end ;

 function  DecodeSerialNumber( Source : PCRYPT_INTEGER_BLOB ) :  String ;
 begin 
  SetLength( Result, Source.cbData *  2  );
  BinToHexInverted( PChar( Source.pbData ), Pointer( Result ), Source.cbData );
 end ;

 function  DecodeName( Source : PCRYPTOAPI_BLOB ) :  String ;
 var  iLength : DWORD;
 begin 
  iLength := CertNameToStr( MY_ENCODING_TYPE,
                            PCERT_NAME_BLOB( Source ),
                            CERT_OID_NAME_STR,
                             nil ,  0  );
  SetLength( Result, iLength );
  iLength := CertNameToStr( MY_ENCODING_TYPE,
                            PCERT_NAME_BLOB( Source ),
                            CERT_OID_NAME_STR,
                            Pointer( Result ), iLength );
  SetLength( Result, iLength );
 end ;

ну и примеры вызовов...
Код: plaintext
1.
2.
3.
4.
5.
  ...
  DecodeName( @Certificate.pCertInfo.Subject )
  DecodeName( @Certificate.pCertInfo.Issuer )
  DecodeSerialNumber( @Certificate.pCertInfo.SerialNumber )
  ...

Поиграйтесь с dwStrType у CertNameToStr и определитесь, что именно вам необходимо из данных, возможно хватит и флага CERT_SIMPLE_NAME_STR
Если капать дальше, то OIDs описаны в разделе Name Properties в Platform SDK, до кучи типы X500 частично описаны таблицей в описании функции CertStrToName
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35306339
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
renatonне сможешь поделицца исходниками?
любой каприз за ваши деньги... все равно я напишу быстрее, чем вы сумеете понять суть )
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35306644
renaton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А где достать правильный файл CryptoAPI.pas ???
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35307631
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
renatonА где достать правильный файл CryptoAPI.pas ???
Уже обсуждалось начиная от.
Для полноценной работы так же необходимы оригинальный WinCrypt.h (7z) ( zip ) и MS Platform SDK... чем выше версии, тем лучше
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35310522
renaton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как сделать так чтобы в свойствах подписаннго файла появилась вкладка подписи и там уже показывались подписанные сертификаты????
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35310645
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
renatonКак сделать так чтобы в свойствах подписаннго файла появилась вкладка подписи и там уже показывались подписанные сертификаты????
Добрый день. Я не понял вопроса. Почти все обсуждение мы говорим об "присоединенной" подписи. Я уже озвучивал, что она по своей сути является хранилищем сертификатов. "показывались подписанные сертификаты" наверное имелось ввиду сертификаты подписавших... в примерах формировали подпись в файле test.sig, чтобы винда корректно открывала подпись в снапине... ".sig" можно заменить на одно из зарегистрированных расширений, к примеру так test.p7s.
Или мы про программную реализацию... тогда вот так (я немного поменял обвязку кода, который уже приводил ранее в калбек функции GetSignerCertificate):

Код: plaintext
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.
 var 
  Store : HCERTSTORE;
  Blob : CRYPTOAPI_BLOB;
  pStream : TMemoryStream;
  Certificate : PCCERT_CONTEXT;
 begin 
  pStream := TMemoryStream.Create;
   try 
    Stream.LoadFromFile( 'c:\test.sig' );
    Blob.cbData := pStream.Size;
    Blob.pbData := pStream.Memory;
    Store := CertOpenStore( CERT_STORE_PROV_PKCS7, MY_ENCODING_TYPE,  0 ,  0 , @Blob );
     if   not  Assigned( Store )  then 
      Err( 'Не удалось открыть хранилище' );
    Certificate :=  nil ;
     repeat 
      Certificate := CertEnumCertificatesInStore( Store, Certificate );
       if  Assigned( Certificate )  then 
       begin 
         { тут можно делать с контекстом серитфиката все, что вашей душе угодно } 
       end ;
     until   not  assigned( Certificate );
     if  (  not  CertCloseStore( Store, CERT_CLOSE_STORE_CHECK_FLAG ))  then 
      Err( 'Ошибка закрытия хранилища' );
   finally 
    FreeAndNil( pStream );
   end ;

тут уже нет никакой валидации подписи и она просто рассматривается как хранилище
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35310661
renaton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так может вот этот скриншот пояснит мой вопрос, это свойтсва инсталлятора АдобеРидер 8
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35310810
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
renatonТак может вот этот скриншот пояснит мой вопрос, это свойтсва инсталлятора АдобеРидер 8

Зачем вы оверкворите.. неудобно же читать. То, что вы хотите... к теме топика не относится - это authenticode signature. Выполняется утилитами идущими в поставке почти всех девелоперских продуктов мс... подпись в лоб в использованием мастера и сертификата, который я выкладывал для примера тут ранее (у сертификата должна быть включена KU = Code sign или область использования неограниченна), с ком.строки запускаю:
Код: plaintext
signtool.exe signwizard
по завершению работы мастера, ответив на вопросы и указав файл и сертификат для подписи получаем
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35310866
renaton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Альт renatonТак может вот этот скриншот пояснит мой вопрос, это свойтсва инсталлятора АдобеРидер 8

Зачем вы оверкворите.. неудобно же читать. То, что вы хотите... к теме топика не относится - это authenticode signature. Выполняется утилитами идущими в поставке почти всех девелоперских продуктов мс... подпись в лоб в использованием мастера и сертификата, который я выкладывал для примера тут ранее (у сертификата должна быть включена KU = Code sign или область использования неограниченна), с ком.строки запускаю:
Код: plaintext
signtool.exe signwizard
по завершению работы мастера, ответив на вопросы и указав файл и сертификат для подписи получаем

А где достать signtool.exe? В поставке делфи он есть?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35310938
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
renatonА где достать signtool.exe? В поставке делфи он есть?
Ну, имя тоже может отличаться (например signcode.exe)... не знаю про дельфи... потому утверждать не буду. Список, куда конкретно включены SignTool ищите в msdn, глянул каталоги... у меня на девелоперской машине они продублированы в куче мест... Microsoft SDK/Microsoft.NET 1.1/Microsoft.NET 2.0 и т.д.
поколупайтесь в bin каталогах эмсишных продуктов... первое же найденное:
Код: plaintext
C:\Program Files\Microsoft.NET\SDK\v1.1\Bin\signcode.exe
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35390491
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vovankaты прогу домучал?
Прогу домучал. Вроде всё работает.
Если есть вопросы то чем смогу, помогу. Но это было так давно, что я уже успел немного позабыть и уволится из того банка в котором писал эту программку, не знаю какова её судьба, но для себя исходнички успел скопировать :)
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35459440
vovanka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
дай почитать пожалуста, для само образования:))
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35956563
_test_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LimonFXC предыдущим вопросом я уже разобрался - сертификат находит.

Ребят, такая же проблема. выложил вопрос здесь:

http://programmersforum.ru/showthread.php?t=47254

http://www.cyberforum.ru/win-api/thread31754.html

http://forum.vingrad.ru/forum/topic-257177/kw-certfindcertificatei-%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82.html

http://www.cryptopro.ru/cryptopro/forum2/default.aspx?g=posts&t=1319

ПОМОГИТЕ ПОЖАЛУЙСТА!
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35957095
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О... Томск... единственный, известный мне город, где есть маршрутка двигающаяся со Спичечной фабрики на Карандашную ) один из самых любимых городов ) еще неделю назад я бы помог разобраться... сидя в том же лагерном... без всяких проблем )
Вопрос сишный и это первое... CertOpenStore без "MY_ENCODING_TYPE" и с закомментированным enc.type... на глаз мало чего ловится... покажите сертификат
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #35957517
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как-то я вчера больше о Томске мечтал... чем на код смотрел )
В общем, нормальный код... насколько он может быть нормальным для си )... соорудил пробник (в приложении сертификат с RDN CN='Gafarov_Artur') и запихнул его в личные... проверяю кодом:
Код: plaintext
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.
 const 
  CN = 'Gafarov_Artur';
  CERT_STORE_NAME = 'MY';
  CRYPTO_ENCODING_TYPE : DWORD = PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING;
 var 
  hStore : HCERTSTORE;
  pCert : PCCERT_CONTEXT;
 begin 
  hStore := CertOpenSystemStore(  0 , CERT_STORE_NAME );
   if  CryptoCheck( hStore <>  0  )  then 
   try 
    pCert := CertFindCertificateInStore( hStore, CRYPTO_ENCODING_TYPE,  0 ,
      CERT_FIND_SUBJECT_STR, CN,  nil  );
     if  CryptoCheck( Assigned( pCert ))  then 
     try 
     // 
     // Работаем с сертификатом 
     // 
     finally 
      CryptoCheck( CertFreeCertificateContext( pCert ));
     end ;
   finally 
    CryptoCheck( CertCloseStore( hStore, CERT_CLOSE_STORE_CHECK_FLAG ));
   end ;
 end ;

все работает, все находит... попробуйте моим вариантом, через CertOpenSystemStore и моим же сертификатом.
зы: есть еще мысли про printableString в вашем RDN и допустимых символов в значении ('_' не входит в их число), но тут надо видеть ваш сертификат. Чем вы его сооружали?
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как сделать цифровую подпись на основе сертификата
    #36617647
LimonFX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О! Моя первая тема на sql.ru :) Помню тогда сильно погрузился в эту задачу, недели на две. Очень помогли примеры на msdn'e. Там правда код на Си, но на delphi с легкостью можно самому переписать.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36678319
frozzen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Альт, спасибо!
коды в теме полезные
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36834495
_Сыр_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да... Ребята... Тема интересная... Жаль что я ее смотрю ))
Подскажите с чего начать?.. Допустим какие компоненты должны быть на 12 дельфе, библиотеки?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36835711
one123456
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Люди, подскажите, как получить данные о сертификате, который находится в контейнере. Ну или ссыли, чет я уже совсем подзадолбался.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36907166
Гвость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дабы не плодить тему...

Нужно подписать сертификатом файл.

Мой код:

Код: plaintext
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.
 procedure  TForm1.btnSignClick(Sender: TObject);
 Const 
  CERT_STORE_NAME = 'MY';
  MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING;
 var 
  wsFind : WideString;
  CertStore: HCERTSTORE;
  Cert:  PCERT_CONTEXT;

  SigParams: CRYPT_SIGN_MESSAGE_PARA;

  strMessage:  String ;
  strSize: DWORD;

  SignedBlob: CRYPT_DATA_BLOB;
  SignedSize: DWORD;
 begin 
   //Хранилище 
  CertStore := CertOpenSystemStore(  0 , 'MY');
   if  CertStore =  nil   then  exit;

   //Сертификат 
  wsFind := 'ТЕСТ';
  Cert := CertFindCertificateInStore(CertStore, PKCS_7_ASN_ENCODING  or  X509_ASN_ENCODING,
   0 , CERT_FIND_SUBJECT_STR, PWideString(wsFind),  nil );
   if  Cert =  nil   then  exit;

   //Данные которые подписываем 
  strMessage := '123';
  strSize :=  3 ;

      SigParams.cbSize := SizeOF(CRYPT_SIGN_MESSAGE_PARA);
      SigParams.dwMsgEncodingType := MY_ENCODING_TYPE;
      SigParams.pSigningCert := Cert;
      SigParams.HashAlgorithm.pszObjId := szOID_PKCS_7;
      SigParams.HashAlgorithm.Parameters.cbData :=  0 ;
      SigParams.cMsgCert :=  1 ;
      SigParams.rgpMsgCert := @Cert;
      SigParams.cAuthAttr :=  0 ;
      SigParams.dwInnerContentType :=  0 ;
      SigParams.cMsgCrl :=  0 ;
      SigParams.cUnauthAttr :=  0 ;
      SigParams.dwFlags :=  0 ;
      SigParams.pvHashAuxInfo :=  nil ;
      SigParams.rgAuthAttr :=  nil ;

      SignedBlob.pbData :=  nil ;

       if  CryptSignMessage(@SigParams, False,  1 , @strMessage, @strSize, SignedBlob.pbData, SignedBlob.cbData)  then 
         begin 
          Memo1.Lines.Add('Размер: ' + intToStr(SignedBlob.cbData));
         end 
       else  Memo1.Lines.Add('False');

      FreeAndNil(SigParams);

      CertFreeCertificateContext(Cert);
      CertCloseStore(CertStore, CERT_CLOSE_STORE_CHECK_FLAG );
 end ;

Размер возвращается но после этого пол секунды спустя Эксес Виолешн... Если запускать не из Delphi прога просто закрывается...

для работы с cryptoAPI использую JwaWinCrypt.pas от JEDI

Код: plaintext
1.
2.
3.
 function  CryptSignMessage(pSignPara: PCRYPT_SIGN_MESSAGE_PARA;
  fDetachedSignature: BOOL; cToBeSigned: DWORD; rgpbToBeSigned: LPBYTE;
  rgcbToBeSigned: LPDWORD;  var  pbSignedBlob: LPBYTE;  var  pcbSignedBlob: DWORD): BOOL; stdcall;
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36911159
Фотография Альт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не спешите меня хоронить, я тут регулярно появлюсь.

Тут надо просто немного думать.
Код: plaintext
SigParams.HashAlgorithm.pszObjId := szOID_PKCS_7;
основа подписи - это хеш к данным (вычисленный по какому-то известному аглоритму), который на втором шаге шифруется приватным ключом пары. Разные провайдеры поддерживают разные наборы алгоритмов хеширования. Вот этой строчкой и задается алгоритм хеша. Перечитайте топик, ведь это обсуждалось c LimonFX еще в 2007 году.

Код: plaintext
FreeAndNil(SigParams);
SigParams - это структура, а не объект и этот код никогда не откомпилируется. И SignedBlob тоже структура. Их элементарно надо занулить перед использованием. Как-то вот так.
Код: plaintext
1.
FillChar(SigParams, SizeOf(SigParams),  0 );
FillChar(SignedBlob, SizeOf(SignedBlob),  0 );
Можно смело воткнуть в самое начало функции.
Да и телепаты подсказывают, что у вас в SignedBlob мусор. Вызов CryptSignMessage должен быть двойным. На первом вы запрашиваете размер подписи, потом выделяете память, и лишь на повторном вызове получаете заветную подпись. Профит.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36912035
Гвость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте, Альт.

Сейчас если ставлю перед вызовом CryptSignMessage ваш код:
Код: plaintext
1.
FillChar(SignedBlob, SizeOf(SignedBlob),  0 );

или

Код: plaintext
1.
SignedBlob.cbData :=  0 ;

функция возвращает False. Но при этом приложение не падает.

Если перед вызовом CryptSignMessage не ставить вышеприведённый код. То при первом вызове функция возвращает размер:
Код: plaintext
1.
Memo1.Lines.Add('Размер: ' + intToStr(SignedBlob.cbData));

но сразу после вылетает...

с алгоритмом хеширования понятно:
Код: plaintext
1.
SigParams.HashAlgorithm.pszObjId := szOID_RSA_SHA1RSA;

теперь так... посмотрел в сертификате "алгоритм подписи".
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36912638
Гвость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GetLastError даёт 5... ERROR_ACCESS_DENIED
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36913719
Fiyanov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ура!

было:
Код: plaintext
1.
2.
3.
 function  CryptSignMessage(pSignPara: PCRYPT_SIGN_MESSAGE_PARA;
  fDetachedSignature: BOOL; cToBeSigned: DWORD; rgpbToBeSigned: LPBYTE;
  rgcbToBeSigned: LPDWORD; pbSignedBlob: LPBYTE;  var  pcbSignedBlob: DWORD): BOOL; stdcall;

стало:
Код: plaintext
1.
2.
3.
 function  CryptSignMessage( var  pSignPara: CRYPT_SIGN_MESSAGE_PARA;
  fDetachedSignature: BOOL; cToBeSigned: DWORD; rgpbToBeSigned: LPBYTE;
  rgcbToBeSigned: LPDWORD; pbSignedBlob: LPBYTE;  var  pcbSignedBlob: DWORD): BOOL; stdcall;

сделал как у Альта... пока всё решилось:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
       if  CryptSignMessage(SigParams, False,  1 , @strMessage, @strSize, SignedBlob.pbData, SignedBlob.cbData)  then 
         begin 
          Memo1.Lines.Add('Размер: ' + intToStr(SignedBlob.cbData));
           if  CryptSignMessage(SigParams, False,  1 , @strMessage, @strSize, SignedBlob.pbData, SignedBlob.cbData)  then 
            Memo1.Lines.Add('Подписано!');
         end 
       else  Memo1.Lines.Add('False');
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #36913726
Fiyanov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотя странно... в msdn именно PCRYPT_SIGN_MESSAGE_PARA . Но почему то при:

Код: plaintext
1.
2.
 var 
SigParams: CRYPT_SIGN_MESSAGE_PARA;

и вызове функции с этим параметром со знаком "@":

Код: plaintext
1.
  if  CryptSignMessage(@SigParams, ...

Наблюдается как раз мой случай когда после возврата размера прога падает... хотя может дело в ключевом слове var которого в моём заголовочном файле от JEDI не было...
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #37337496
dv_belyaev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
всем привет
в проекте использую шифрование и подпись файлов сертификатами
функции CryptEncryptMessage / CryptDecryptMessage / CryptSignMessage / CryptVerifyMessageSignature

все работает отлично, но есть момент
при расшифровке и проверке подписи у файлов размером ~ 100 Мб и выше
выскакивет ошибка Слишком большое значение ASN1"
в инете ничего кроме http://www.sql.ru/forum/actualthread.aspx?tid=804878 не обнаружил
там чел предлагает "Спасибо, скорее всего нужно блоками дробить."
пробовал расшифровывать кусками - копирую в дополнительный буфер часть файла и на расшифровку
ошибка - "В ASN1 встречен неожиданный конец данных"
наталкивает на мысль что я неправильно загоняю данные в буфер
вот кусок кода (на тестировании подразумеваю что файл больше 100 Мб, но всего 2 куска)

Код: 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.
     pStreamIn := TMemoryStream.Create;
     pStreamOut := TMemoryStream.Create;
     pStreamIn.LoadFromFile(filename);


     if pStreamIn.Size > 95 * 1024 * 1024 then // если файл больше 95 Мб
     begin
       for i := 0 to 1 do
       begin
         tpStreamIn := TMemoryStream.Create;
         tpStreamOut := TMemoryStream.Create;
         if i = 0
           then tpStreamIn.CopyFrom(pStreamIn, 95 * 1024 * 1024)
           else tpStreamIn.CopyFrom(pStreamIn, pStreamIn.Size - pStreamIn.Position);
         tpStreamIn.Position := 0;

         if CryptVerifyMessageSignature( @VerifyParams, 0, tpStreamIn.Memory, tpStreamIn.Size, nil, @cbDecodedMessageBlob, nil ) then
         begin
           tpStreamOut.Size := cbDecodedMessageBlob;
           if CryptVerifyMessageSignature(@VerifyParams, 0, tpStreamIn.Memory, tpStreamIn.Size, tpStreamOut.Memory, @cbDecodedMessageBlob, @pCert) then
           begin
             pStreamOut.Size := pStreamOut.Size + tpStreamOut.Size;
             tpStreamOut.Position := 0;
             pStreamOut.CopyFrom(tpStreamOut, tpStreamOut.Size);
           end;
         end else ShowMessage(SysErrorMessage(GetLastError));
         tpStreamIn.Free;
         tpStreamOut.Free;
       end;
       if pStreamOut.Size > 0 then
       begin
         fotopath := UserTEMPDir+'tmp'+ExtractFileExt(temp);
         DeleteFile(fotopath);
         pStreamOut.SaveToFile( fotopath );
       end;
     end else  //  загоняю целиком
     begin
       if CryptVerifyMessageSignature( @VerifyParams, 0, pStreamIn.Memory, pStreamIn.Size, nil, @cbDecodedMessageBlob, nil ) then
       begin
         pStreamOut.Size := cbDecodedMessageBlob;
         if CryptVerifyMessageSignature(@VerifyParams, 0, pStreamIn.Memory, pStreamIn.Size, pStreamOut.Memory, @cbDecodedMessageBlob, @pCert) then
         begin
           fotopath := UserTEMPDir+'tmp'+ExtractFileExt(temp);
           pStreamOut.Size := cbDecodedMessageBlob;
           pStreamOut.SaveToFile( fotopath );
         end;
       end;
     end;
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #37337927
A-n-d-r-e-y
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Откажись от высокоуровневых функций: CryptVerifyMessageSignature и т.п.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #37605591
exsander
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!
Пытаюсь найти установленный в системе тестовый сертификат от КриптоПро. За основу взят код из первых сообщений данной темы
При поиске по отпечатку сертификат не найден, GetLastError возвращает ошибку 0x80092004 Объект или свойство не найдено

Код: 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.
...
implementation
const
  CERT_STORE_NAME = 'ROOT';
  MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
  SignerName : WideString = 'Test Center CRYPTO-PRO';
...
procedure TForm1.btFindHashClick(Sender: TObject);
var
  pSignerCert: PCCERT_CONTEXT;
  hCertStoreHandle : HCERTSTORE;
  iLen, i:integer;
  P:PByte;
  pError:LPCTSTR;
  pCertHash: CRYPT_HASH_BLOB;
begin
  Memo.Clear;
  FillChar(pCertHash,SizeOf(pCertHash),0);

  Memo.Lines.Add(ByteArrayToStr(pCertHash.pbData,pCertHash.cbData));

  hCertStoreHandle := CertOpenSystemStore( 0, PChar( CERT_STORE_NAME ));
  if ( not assigned( hCertStoreHandle )) then
    Err( Format( 'Ошибка при открытии хранилища: %s', [ CERT_STORE_NAME ] ));

  iLen := Length(CertHash.Text) div 2;
  pCertHash.cbData:=iLen;
  pCertHash.pbData:= GetMemory(iLen);

  P:=pCertHash.pbData;
  i:=Length(CertHash.Text)-1;
  while i >= 0 do begin
    P^ := GetHexValue(CertHash.Text[i]) * 16 + GetHexValue(CertHash.Text[i + 1]);
    P := Pointer(Integer(P) + 1);
    dec(i, 2);
  end;
  Memo.Lines.Add(ByteArrayToStr(pCertHash.pbData,pCertHash.cbData));
  pSignerCert := CertFindCertificateInStore(hCertStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_SHA1_HASH, @pCertHash, nil);
  if ( not assigned( pSignerCert )) then
    Err('Сертификат не найден')
  else
    Memo.Lines.Add(GetSerialNumber(pSignerCert));
end;




Хочется понять что делается мной не так? Заранее спасибо.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #37606211
Здравствуйте, я даже задумываться не хочу, что именно делает вот этот говнокод:
exsander 0x80092004 Объект или свойство не найдено

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
  iLen := Length(CertHash.Text) div 2;
  pCertHash.cbData:=iLen;
  pCertHash.pbData:= GetMemory(iLen);

  P:=pCertHash.pbData;
  i:=Length(CertHash.Text)-1;
  while i >= 0 do begin
    P^ := GetHexValue(CertHash.Text[i]) * 16 + GetHexValue(CertHash.Text[i + 1]);
    P := Pointer(Integer(P) + 1);
    dec(i, 2);
  end;




Хочется понять что делается мной не так? Заранее спасибо.

при поиске там должен быть хеш в виде бина, т.е. если вам на влете приходит хеш в виде хекса, то и приводить его надо через HexToBin. Вы точно в правильном хранилище ищите? Сертификат не в MY? На глаз я больше особых проблем не вижу. В моих поделках эта функция объявлена вот так, сравнивайте со своим:
Код: 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.
//+-------------------------------------------------------------------------
//  Find the first or next certificate context in the store.
//
//  The certificate is found according to the dwFindType and its pvFindPara.
//  See below for a list of the find types and its parameters.
//
//  Currently dwFindFlags is only used for CERT_FIND_SUBJECT_ATTR,
//  CERT_FIND_ISSUER_ATTR or CERT_FIND_CTL_USAGE. Otherwise, must be set to 0.
//
//  Usage of dwCertEncodingType depends on the dwFindType.
//
//  If the first or next certificate isn't found, NULL is returned.
//  Otherwise, a pointer to a read only CERT_CONTEXT is returned. CERT_CONTEXT
//  must be freed by calling CertFreeCertificateContext or is freed when passed as the
//  pPrevCertContext on a subsequent call. CertDuplicateCertificateContext
//  can be called to make a duplicate.
//
//  pPrevCertContext MUST BE NULL on the first
//  call to find the certificate. To find the next certificate, the
//  pPrevCertContext is set to the CERT_CONTEXT returned by a previous call.
//
//  NOTE: a NON-NULL pPrevCertContext is always CertFreeCertificateContext'ed by
//  this function, even for an error.
//--------------------------------------------------------------------------

function CertFindCertificateInStore( hCertStore :HCERTSTORE;
                                     dwCertEncodingType, dwFindFlags,
                                     dwFindType : DWORD;
                               const pvFindPara;
                                     pPrevCertContext: PCERT_CONTEXT = nil
                                    ): PCERT_CONTEXT ; stdcall;



ну и вызов первого поиска тогда будет вот таким:
Код: pascal
1.
CertFindCertificateInStore( FStore, CRYPT_ENCODING, 0, CERT_FIND_HASH, Blob );
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #37637028
exsander
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!

С поиском я разобрался, сертификат находится, подписывает и шифрует файл. Непонятен остался один момент. При подписи файла, перед текстом сообщения и после него добавляется информация. При помощи утилиты cryptcp (КриптоПро-шная утилита командной строки) пытаюсь удалить подпись из сообщения. То что находится после текста, т.е. сама подпись удаляется, а вот то, что добавилось перед текстом - остается.
это подписываемый текст

Код: pascal
1.
2.
3.
 Сорри несколько за глупый вопрос. Просто проект нужно сдать в понедельник. Время поджимает и реально не успеваю.
Что нужно:на основе сертификата (выбирается вручную из установленных) подписать файл цифровой подписью, а потом
проверить эту самую подпись. Стало быть как сделать? Если кто-нибудь кинет рабочим примером на Дельфи, буду очень благодарен.


Это уже подписанный текст

Код: 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.
0'	*&#9532;H&#9532;ч
 '0'10
*:	
 'd'`Сорри несколько за глупый вопрос. Просто проект нужно сдать в понедельник. Время поджимает и реально не успеваю.
Что нужно:на основе сертификата (выбирается вручную из установленных) подписать файл цифровой подписью, а потом
проверить эту самую подпись. Стало быть как сделать? Если кто-нибудь кинет рабочим примером на Дельфи, буду очень благодарен.1'v0'r0_Є0_>10	*&#9532;H&#9532;ч
	test-uc@tii.ru10	URU10
Umoscow10
Umoscow10U

Integrator IT10USecurity of documents10U
Testing CA
}О_
*:	
	1	*&#9532;H&#9532;ч
0	*&#9532;H&#9532;ч
	1
120129100105Z0/	*&#9532;H&#9532;ч
	1" UBiЙ-_РЪFzй)Х:о<sы&#9488;JН_у&#9488;D8лD0_ш*&#9532;H&#9532;ч
	/1_и0_е0_в0_Я0*:	 2Д-NУЬ![<&#9488;__biiЇ2XПpц_c~HЦы0_°0_Ў¤__0_>10	*&#9532;H&#9532;ч
	test-uc@tii.ru10	URU10
Umoscow10
Umoscow10U

Integrator IT10USecurity of documents10U
Testing CA
}О_
*:
р-є
р-є
р-є



а это текст после удаления подписи при помощи cryptcp

Код: pascal
1.
2.
3.
4.
5.
6.
0'_	*&#9532;H&#9532;ч
 '_0'_10
*:	
 'd'`Сорри несколько за глупый вопрос. Просто проект нужно сдать в понедельник. Время поджимает и реально не успеваю.
Что нужно:на основе сертификата (выбирается вручную из установленных) подписать файл цифровой подписью, а потом
проверить эту самую подпись. Стало быть как сделать? Если кто-нибудь кинет рабочим примером на Дельфи, буду очень благодарен.1



Что это за инфа в начале текста, и если это часть подписи почему она не удалилась? Заранее спасибо.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #37637259
exsander
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вопрос снят, ответ нашелся здесь: http://citforum.ru/security/articles/defense/
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как сделать цифровую подпись на основе сертификата
    #38861312
SereZa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в теме встретился кусочек кода:
Store := CertOpenStore( CERT_STORE_PROV_PKCS7, MY_ENCODING_TYPE, 0, 0, @Blob );
я так понимаю что это работает только в случае если не было пароля. а если есть пароль на сертификате - коим образом его указать? это должна быть другая команда для чтения такого сертификата?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #38861348
Antoshka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SereZaв теме встретился кусочек кода:
Store := CertOpenStore( CERT_STORE_PROV_PKCS7, MY_ENCODING_TYPE, 0, 0, @Blob );
я так понимаю что это работает только в случае если не было пароля. а если есть пароль на сертификате - коим образом его указать? это должна быть другая команда для чтения такого сертификата?
На сертификате пароля не бывает. Вы про PFX или про eToken?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #38862071
SereZa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
наверное про PFX... только PFXImportCertStore не хочет работать, пишет что не правильный алгоритм. PFXIsPFXBlob и PFXVerifyPassword замечательно работают. а вот PFXImportCertStore нет. и сам этот сертификат стандартным виндосовским мастером регистрации не устанавливается. в самом конце выдает ошибку про поставщика криптографии. здесь на форуме писали что нужен CSP - только на том сайте java апплет читает этот сертификат и регистрирует его в системе. никакой дополнительной программы при этом не устанавливается.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #38862080
Antoshka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На каком "том сайте"? Вангую, что в сертификате у вас ГОСТовский ключ, который не распознаётся системой без установки соответствующего криптопровайдера, умеющего работать с алгоритмами ГОСТ. Откуда у вас вообще появился данный сертификат в PFX?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #38862102
SereZa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
никакой установки криптопровайдера не происходит. все делает java апплет. он может выполнять функции подобного криптопровайдера? своеобразный портэйбл-CSP? такой сертификат выдает налоговая. для своего сайта для отправки налоговой отчетности. задумка была сделать программу, которая бы могла проверять сроки действия и читать имя в подобных сертификатах на жестком диске.


и второй момент, не совсем по теме - но рядом. существует некоторые интернет банкинки, которые как раз используют подобные CSP - там целая программа, что должна быть установлена, висит в процессах, работает как сервис. как можно объяснить браузеру чтоб он запустился без использования этого CSP? режим инкогнито хрома вроде как запускается без него... но проблема в том, что он не запоминает какой сертификат был выбран и опять выкидывает окно выбора сертификата при входе и зацикливается. (имелось в виду окошко с выбором уже установленных в системе сертификатов). как бы так хитро запустить браузер, чтоб и запоминал что выбрано и чтоб без использования CSP? принудительная остановка службы этого криптопровайдера не помогает. только если удалить полностью программы. а вот как бы без удаления...
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #38862107
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AntoshkaНа каком "том сайте"? Вангую, что в сертификате у вас ГОСТовский ключ, который не распознаётся системой без установки соответствующего криптопровайдера, умеющего работать с алгоритмами ГОСТ. Откуда у вас вообще появился данный сертификат в PFX?

Похоже SereZa Delphi и CryptoAPI ]не читает ответы на свои вопросы.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как сделать цифровую подпись на основе сертификата
    #39602196
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хорошая тема, помогла найти многие ответы на вопросы, но кое-что мне непонятно.

Код: 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.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
unit JwaWinCrypt;
...
function CryptSignMessage( var pSignPara : CRYPT_SIGN_MESSAGE_PARA;
                           fDetachedSignature : BOOL;
                           cToBeSigned :DWORD;
                     const rgpbToBeSigned : PByteArray;
                           rgcbToBeSigned : PDWordArray;
                           pbSignedBlob : PBYTE;
                           var pcbSignedBlob : DWORD ) : BOOL; stdcall;
....

unit Main;

uses jwaWinScrypt...

// обрабатываем ошибки
procedure Err( const msg : String );
var
  dwError, dwLen : DWORD;
  sError, sErrorDecode : String;
  pBuffer : Cardinal;
begin
  dwError := GetLastError;
  dwLen := FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM or
                          FORMAT_MESSAGE_ARGUMENT_ARRAY or
                          FORMAT_MESSAGE_ALLOCATE_BUFFER,
                          nil, dwError, 0, @pBuffer, 0, nil );
  try
    SetString( sErrorDecode, PChar( pBuffer ), dwLen );
  finally
    LocalFree( pBuffer );
  end;
  sError := Format( '%s'#10#13'0x%x %s', [ msg, dwError, sErrorDecode ] );
  frmSignatureFromCertificate.mDestination.Lines.Text := msg;
  Raise Exception.Create( sError );
end;

// подписываем содержимое одного Memo-поля, выводим в другое Memo поле
procedure TfrmSignatureFromCertificate.acSignFileExecute(Sender: TObject);
const
  CERT_STORE_NAME = 'MY';
  MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
  SignerName : WideString = 'Shuraken';
var
  pSignerCert: PCCERT_CONTEXT;
  hCertStoreHandle: HCERTSTORE;
  SigParams: CRYPT_SIGN_MESSAGE_PARA;
  pStreamIn, pStreamOut: TMemoryStream;
  MessageArray : TByteArray;
  MessageSize : TDWordArray;
  MessageCert : TPCCertContextArray;
  cbSignedMessageBlob: DWORD;
  SignName: WideString;
begin
  mDestination.Clear;
  hCertStoreHandle := CertOpenSystemStore( 0, PChar( CERT_STORE_NAME ));
  if ( not assigned( hCertStoreHandle )) then
    Err( Format( 'Ошибка при открытии хранилища: %s', [ CERT_STORE_NAME ] ));
  try
    SignName := Trim(cmbCertificates.Text);
    pSignerCert := CertFindCertificateInStore( hCertStoreHandle, MY_ENCODING_TYPE, 0, CERT_FIND_SUBJECT_STR, PWideChar( SignName ), nil );
    try
      if ( not assigned( pSignerCert )) then
        Err( Format( 'Сертификат %s не найден', [ SignName ] ));
      pStreamIn := TMemoryStream.Create;
      pStreamOut := TMemoryStream.Create;
      try
        mSource.Lines.SaveToStream(pStreamIn);
        GetMem( MessageArray, 1 * SizeOf( PByte ));
        GetMem( MessageSize, 1 * SizeOf( DWORD ));
        GetMem( MessageCert, 1 * SizeOf( PPCCERT_CONTEXT ));
        MessageArray[ 0 ] := pStreamIn.Memory;
        MessageSize[ 0 ] := pStreamIn.Size;
        MessageCert[ 0 ] := pSignerCert;
        FillChar( SigParams, SizeOf( CRYPT_SIGN_MESSAGE_PARA ), 0 );
        SigParams.cbSize := SizeOF( CRYPT_SIGN_MESSAGE_PARA );
        SigParams.dwMsgEncodingType := MY_ENCODING_TYPE;
        SigParams.pSigningCert := pSignerCert;
        SigParams.HashAlgorithm.pszObjId := szOID_RSA_MD5;
        SigParams.cMsgCert := 1;
        SigParams.rgpMsgCert := Pointer( MessageCert );
        if ( not ( CryptSignMessage( SigParams, false, 1, Pointer( MessageArray ), Pointer( MessageSize ), nil, cbSignedMessageBlob ))) then
          Err( 'Размер буфера' );
        pStreamOut.Size := cbSignedMessageBlob;
        if not ( CryptSignMessage( SigParams, false, 1, Pointer( MessageArray ), Pointer( MessageSize ), pStreamOut.Memory, cbSignedMessageBlob )) then
          Err( 'Файл не подписан' );
        pStreamOut.Size := cbSignedMessageBlob;

        mDestination.Lines.LoadFromStream(pStreamOut);
      finally
        FreeAndNil( pStreamIn );
        FreeAndNil( pStreamOut );
      end;
    finally
      CertFreeCertificateContext(pSignerCert);
    end;
  finally
    CertCloseStore( hCertStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG );
  end;
end;

// выводим список личных сертификатов
procedure TfrmSignatureFromCertificate.FormShow(Sender: TObject);
var
  hProv       : HCRYPTPROV;
  hStoreHandle: hcertstore;
  pSignerCert : PCCERT_CONTEXT;
  pCertContext: PCCERT_CONTEXT;
  len: integer;
  CertName: PByte;

function CertNameToWideString: WideString;
begin
  if (len = 0) then
  begin
    Result := '';
    Exit;
  end;

  SetLength(Result, len div 2);
  System.Move(CertName^, Pointer(Result)^, len);
  len := Length(Result);
  if (Result[len] = #0) then
  begin
    Dec(len);
    SetLength(Result, len);
  end;
end;

begin

  if not CryptAcquireContext(hProv, nil, nil, PROV_RSA_SIG, CRYPT_VERIFYCONTEXT) then
    exit;

  hStoreHandle := CertOpenSystemStore(hProv, 'MY');
  if (hStoreHandle = nil) then
  begin
    Err('ErrorOpenStore');
    exit;
  end;

  pCertContext := nil;
  repeat
    pCertContext := CertEnumCertificatesInStore(hStoreHandle, pCertContext);
    if (pCertContext <> nil) then
    begin
      len := CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, nil, 0);
      if len > 0 then
      begin
        len := len*2;
        GetMem(CertName, len);
        CertGetNameStringW(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, PWideChar(CertName), len);
        cmbCertificates.Items.Add(CertNameToWideString);
        FreeMem(CertName);
        CertName := nil;
      end;
    end;
  until (pCertContext = nil);
  cmbCertificates.ItemIndex := 0;
end;



Какой-то код взят из этой темы, какой-то из других источников, и вот что интересно. У меня на компьютере установлено 5 различных сертификатов. Когда я пытаюсь подписать содержимое memo-поля сертификатом, у которого нет закрытого ключа, то выдаётся ошибка "0х8009200В Не удаётся найти сертификат и закрытый ключ для расшифровки". Делая то же самое сертификатом с закрытым ключом, получаю нормальный результат. Вопрос: почему не удаётся подписать содержимое сертификатом без закрытого ключа.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39604755
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подниму тему. Можно ли вообще подписывать что-либо сертификатом без закрытого ключа?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39605510
__Avenger__
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShurakenПодниму тему. Можно ли вообще подписывать что-либо сертификатом без закрытого ключа?

Нет. Подпись только закрытым ключом. Шифровать можно на открытом ключе.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39699762
alexer81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо большое за код!
добавлю при подписи удобнее выбрать сертификат из установленных:
pSignerCert :=CryptUIDlgSelectCertificateFromStore(hCertStoreHandle, self.Handle,'','',0,0,nil);
и вставил (не знаю правильно ли)CryptAcquireCertificatePrivateKey(pSignerCert,CRYPT_ACQUIRE_CACHE_FLAG,nil,prov,@pdwKeySpec,@pfCallerFreeProv)
перед CryptSignMessage(..) чтобы пароль два раза от контейнера не вводить

А остался у меня такой вопрос - CryptVerifyMessageSignature возвращает исходные данные и сертификат которым подписано, а как достать "Время подписания (1.2.840.113549.1.9.16.2.47 )" через CryptoAPi?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39699911
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexer81спасибо большое за код!
добавлю при подписи удобнее выбрать сертификат из установленных:
pSignerCert :=CryptUIDlgSelectCertificateFromStore(hCertStoreHandle, self.Handle,'','',0,0,nil);
и вставил (не знаю правильно ли)CryptAcquireCertificatePrivateKey(pSignerCert,CRYPT_ACQUIRE_CACHE_FLAG,nil,prov,@pdwKeySpec,@pfCallerFreeProv)
перед CryptSignMessage(..) чтобы пароль два раза от контейнера не вводить

А остался у меня такой вопрос - CryptVerifyMessageSignature возвращает исходные данные и сертификат которым подписано, а как достать "Время подписания (1.2.840.113549.1.9.16.2.47 )" через CryptoAPi?


CryptUIDlgSelectCertificateFromStore - не особо будет удобен, когда есть сертификаты с одинаковым CN и т.п.
(разные УЦ\разные SN, G- ФИО, которые ОС не покажет в этом списке) + эта функция может "тормозить", не использую её...
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39699913
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
поэтому - можно своё что-то изобразить всегда, если захочется, см. снимок выше.
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39699916
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexer81,

Добавление атрибута даты в ЭЦП
https://qa-help.ru/questions/dobavlenie-atributa-daty-v-ecp
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39699918
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
  ca: array[0..10] of CRYPT_ATTRIBUTE;  // перечень подписываемых атрибутов: дата\время, комментарий, использование, csp и т.д.
  FTime: TFileTime;
  cablob: CRYPT_ATTR_BLOB;
  pbAuth : PByte;
...

 ///////////////////////////////////////////////////////////////////////////////////////////
  FTime := DateTimeToFileTime(DTSign);
  CryptEncodeObject(MY_ENCODING_TYPE, szOID_RSA_signingTime, @FTime, nil, cbAuth);
  GetMem(pbAuth, cbAuth);  
  CryptEncodeObject(MY_ENCODING_TYPE, szOID_RSA_signingTime, @FTime, pbAuth, cbAuth); 
  cablob.cbData := cbAuth;
  cablob.pbData := pbAuth;
  ///////////////////////////////////////////////////////////////////////////////////////////
  ca[0].pszObjId := szOID_RSA_signingTime; // дата и время
  ca[0].cValue := 1;
  ca[0].rgValue := @cablob;
  /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
 // ca[1] .. 9 - другие атрибуты при необходимости
...

  SignerEncodeInfo.rgAuthAttr := @ca; 
    SignerEncodeInfo.cAuthAttr :=1 ; // если использовать только дату\время из ca[]
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39700283
alexer81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql2012, спасибо за ответы! ваша информация пригодится.
Но в подписанном файле есть уже время подписания и потому мой вопрос:
автор- CryptVerifyMessageSignature возвращает исходные данные и сертификат которым подписано, а как достать "Время подписания (1.2.840.113549.1.9.16.2.47 )" через CryptoAPi?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39700288
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexer81,


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
hMsg: HCRYPTMSG;  
  authAttr: PCRYPT_ATTRIBUTES;
  Attr: PCRYPT_ATTRIBUTE;  
ft: FILETIME;

...
CryptMsgGetParam(hMsg, CMSG_SIGNER_AUTH_ATTR_PARAM, signerIndex, nil, authAttr_len)
выделить память размером authAttr_len  для authAttr 
 CryptMsgGetParam(hMsg, CMSG_SIGNER_AUTH_ATTR_PARAM, signerIndex, authAttr, authAttr_len) 
...
 Attr := CertFindAttribute(szOID_RSA_signingTime, authAttr.cAttr, authAttr.rgAttr);

 dwSize := SizeOf(ft);
    Win32Check(CryptDecodeObject(MY_ENCODING_TYPE, szOID_RSA_signingTime,
    
  Attr.rgValue.pbData, Attr.rgValue.cbData, 0, @ft, dwSize));
    

DT := DecodeFileTime(ft);



+ добавить проверку вызовов, выделение\освобождение памяти
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39700484
alexer81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо. разобрался.
время конечно в в атрибуте с оид - szOID_RSA_signingTime. я приплёл 1.2.840.113549.1.9.16.2.47, не туда наверно глянул
но почему-то атрибуты сразу через CryptMsgGetParam(..CMSG_SIGNER_AUTH_ATTR_PARAM..) не получилось взять
взял через CryptMsgGetParam(..CMSG_SIGNER_INFO_PARAM..)
в CMSG_SIGNER_INFO.AuthAttrs
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39714321
alexer81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте. нужно из контейнера достать Срок действия закрытого ключа "1.2.643.2.2.37.3.10"
Для этого нужно перечислить расширения контейнера через GetProvParam(PP_ENUM_CONTAINER_EXTENSION).
в документации КриптоПро определена получаемая структура :
Код: plaintext
1.
2.
3.
4.
5.
6.
typedef struct _CONTAINER_EXTENSION {
    BOOL bCritical; /*!< Флаг критического расширения. */
    DWORD cbExtension; /*!< Длина данных в pbExtension. */
    BYTE pbExtension[1]; /*!< Данные. */
    char sOid[1]; /*!< Строка с OID-ом расширения (невыровненный указатель). */
} CONTAINER_EXTENSION;


делаю в delphi
Код: 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.
PCONTAINER_EXTENSION = ^CONTAINER_EXTENSION;
_CONTAINER_EXTENSION =record
  bCritical: BOOL;
 cbExtension:DWORD;
 pbExtension:array[0..0] of byte;
  sOid:array [0..0] of char;
 end;
CONTAINER_EXTENSION = _CONTAINER_EXTENSION;
///
var cExtension:PCONTAINER_EXTENSION;
///
Flag :=CRYPT_FIRST;
if CryptGetProvParam(Prov,PP_ENUM_CONTAINER_EXTENSION,nil,Size,Flag) then
 begin
     GetMem(Info,Size);
   try
   while  CryptGetProvParam(Prov,PP_ENUM_CONTAINER_EXTENSION,Info,Size,Flag) do
    begin
        //
    cExtension:=PCONTAINER_EXTENSION(Info);
     Flag := CRYPT_NEXT;
    end;
   finally
   FreeMem(Info,Size);
  end;
end;


и как тут получить нужные данные?
cExtension.cbExtension = 19 это правильно
cExtension.pbExtension[0] - первый байт, а остальные как брать?
в cExtension.sOid не понятно что за символ, как взять полностью?
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39714327
alexer81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ну cExtension.pbExtension[0] - первый байт есть, и есть длина
весь массив понятно есть.
а с cExtension.sOid не понятно
...
Рейтинг: 0 / 0
Как сделать цифровую подпись на основе сертификата
    #39714457
alexer81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
oid взял так:
oid = Pchar(pointer(integer(@cExtension.pbExtension[0])+cExtension.cbExtension))
как взять с помощью cExtension.sOid не знаю
...
Рейтинг: 0 / 0
128 сообщений из 128, показаны все 6 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как сделать цифровую подпись на основе сертификата
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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