powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как сделать цифровую подпись на основе сертификата
25 сообщений из 128, страница 1 из 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
25 сообщений из 128, страница 1 из 6
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как сделать цифровую подпись на основе сертификата
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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