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

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

Вот текст тестовой процедуры, в комментариях
Сори за форматирование, просто изучаю :)
Код: 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
12.05.2018, 09:49
    #39643526
Devillio
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
Может это важно?


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

Навскидку - вот так, не?
Код: pascal
1.
function MySignerCertificateCallback( pvGetArg : pvoid; dwCertEncodingType : DWORD;pSignerId : PCERT_INFO;hMsgCertStore : HCERTSTORE): PCCERT_CONTEXT ; stdcall;
...
Рейтинг: 0 / 0
12.05.2018, 13:42
    #39643577
Devillio
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
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
12.05.2018, 16:38
    #39643606
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature)
DevillioДа, натыкался на такой совет
Это не совет, это правило. Любые коллбэки, которые вызывает винда, должны быть объявлены как stdcall, если в описании не сказано иного. Иначе параметры передаются неправильно и вы получаете мусор внутри.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как получить сведения подписантов из sig-файла? (CryptVerifyDetachedMessageSignature) / 5 сообщений из 5, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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