powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
5 сообщений из 5, страница 1 из 1
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
    #39643521
Devillio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток!

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

Вот текст тестовой процедуры, в комментариях
Сори за форматирование, просто изучаю :)
Код: 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.
procedure TMainForm.Button3Click(Sender: TObject);
var veriPara: CRYPT_VERIFY_MESSAGE_PARA;
     mStreamIn, mStreamSignIn: TMemoryStream;
     arrDataPointer: array of Pointer;
     arrDataSize: array of DWORD;

     c, i: Integer;
     sFileToVerifyPath, sSignaturePath: String;
     S: String;
     ACert: PCCERT_CONTEXT;
     PPCert: PPCCERT_CONTEXT;

function ByteArrayToStr(pbData: PByte; cbData: DWORD): String;
var
I, J: Integer;
S: String;
begin
Result := '';
if not Assigned(pbData) or (cbData <= 0) then
Exit;
for I := 0 to cbData - 1 do
begin
J := PByteArray(pbData)^[i];
S := IntToHex(J, 2);
if (I > 0) and (I and 1 = 0) then
S := S + ' ';
Result := S + Result;
end;
end;

function GetSerialNumber(CertInfo: PCCERT_CONTEXT): String;
begin
Result := ByteArrayToStr(CertInfo.pCertInfo.SerialNumber.pbData,
CertInfo.pCertInfo.SerialNumber.cbData);
end;

function MySignerCertificateCallback( pvGetArg : pvoid; dwCertEncodingType : DWORD;pSignerId : PCERT_INFO;hMsgCertStore : HCERTSTORE): PCCERT_CONTEXT ;
begin
Result := PCCERT_CONTEXT(pvGetArg); //вот здесь Access Violation
end;

begin
  if not OpenDialog1.Execute then Exit;
  sFileToVerifyPath := OpenDialog1.FileName;
  sSignaturePath := OpenDialog1.FileName+'.sig';
  try
    mStreamIn:= TMemoryStream.Create;
    mStreamIn.LoadFromFile(sFileToVerifyPath);
    SetLength(arrDataPointer, 1);
    SetLength(arrDataSize, 1);
    arrDataPointer[0]:= mStreamIn.memory;
    arrDataSize[0]:= mStreamIn.Size;
    mStreamSignIn:= TMemoryStream.Create;
    mStreamSignIn.LoadFromFile(sSignaturePath);
    FillChar(veriPara, SizeOf(CRYPT_VERIFY_MESSAGE_PARA), #0);
    veriPara.cbSize:= SizeOf(CRYPT_VERIFY_MESSAGE_PARA);
    veriPara.dwMsgAndCertEncodingType:= PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
//    veriPara.pfnGetSignerCertificate := @MySignerCertificateCallback;
    C := CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, mStreamSignIn.Memory, mStreamSignIn.Size);
    for i := 0 to C-1 do
      if CryptVerifyDetachedMessageSignature(@veriPara, i, mStreamSignIn.Memory, mStreamSignIn.Size, 1, Pointer(arrDataPointer), Pointer(arrDataSize), PPCert) then
      begin
        //при ремарке строки "veriPara.pfnGetSignerCertificate := @..." здесь Access Violation
        //PPCert всегда nil приходит, но подпись есть и верна (проверял сайтом криптопро)
        with PPCert^.pCertInfo.Issuer do 
        S :=S+#13#10+'SN: '+ByteArrayToStr(pbData, cbData) ;
//        S :=S+#13#10+'SN: '+GetSerialNumber(aCERT^);
        S:=S+#13#10;
//       CertFreeCertificateContext(ACert^);
      end;


  except
    on e:exception do
    MessageDlg(e.Message, mtInformation, [mbok], 0);
  end;

  MessageDlg('Подписантов: '+IntToStr(C)+S, mtInformation, [mbok], 0);
end;



Помогите, будьте добры? Очень не очень я с указателями :(
Спасибо!
...
Рейтинг: 0 / 0
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
    #39643526
Devillio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может это важно?


...
Рейтинг: 0 / 0
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
    #39643538
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Devillio,

Навскидку - вот так, не?
Код: pascal
1.
function MySignerCertificateCallback( pvGetArg : pvoid; dwCertEncodingType : DWORD;pSignerId : PCERT_INFO;hMsgCertStore : HCERTSTORE): PCCERT_CONTEXT ; stdcall;
...
Рейтинг: 0 / 0
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
    #39643577
Devillio
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alekcvp, благодарю за ответ.
Да, натыкался на такой совет, не помогло, т.к. навертел там еще несколько ошибок :)
Мож вдруг кто-то на те же грабли наступит:
1)
veriPara.pfnGetSignerCertificate := nil; // @MySignerCertificateCallback;
veriPara.pvGetArg := nil; // ACert;
(не надо куралесить своё, встроенное работает)
2) CryptVerifyDetachedMessageSignature(@veriPara, i, mStreamSignIn.Memory, mStreamSignIn.Size, 1, Pointer(arrDataPointer), Pointer(arrDataSize), @ACert )
(ACert: PCCERT_CONTEXT)

3) еще вот такую функцию нашел читать encoded data:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
function GetCertString(dwType,dwFlags:DWORD;pvTypePara:Pointer=nil):string;
var dwSize: DWORD;
  begin
    dwSize:=CertGetNameString(ACert,dwType,dwFlags,pvTypePara,nil,0);
    Win32Check(dwSize<>0);
    SetLength(Result,dwSize);
    Win32Check(CertGetNameString(ACert,dwType,dwFlags,pvTypePara,
      Pointer(Result),dwSize)<>0);
    Result := StringReplace(Result, #0, '', []);
  end;

...
        S :=S+#13#10+'Issuer Name: '+GetCertString(CERT_NAME_SIMPLE_DISPLAY_TYPE,CERT_NAME_ISSUER_FLAG);
        S :=S+#13#10+'Subject: '+ GetCertString(CERT_NAME_SIMPLE_DISPLAY_TYPE,0) ;
//GetCertString возвращает распакованные строчки кто выпустил серт, на кого, и т.д.


Результирующую процедуру пока не могу проверить на две и более подписи, но для одной работает
...
Рейтинг: 0 / 0
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
    #39643606
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DevillioДа, натыкался на такой совет
Это не совет, это правило. Любые коллбэки, которые вызывает винда, должны быть объявлены как stdcall, если в описании не сказано иного. Иначе параметры передаются неправильно и вы получаете мусор внутри.
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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