Пишу программку, стоит задача проверить подпись приличного количества фалов, работая в PE. SignTool verify работает, но медленно. Если парсить ее вывод, будет еще дольше. Хотел попробовать через API, да вот не могу разобраться с механизмом.
Пытаюсь делать так:
procedure TForm1.Button1Click(Sender: TObject);
var
Prov: HCRYPTPROV;
sKey: HCRYPTKEY;
Stream: TMemoryStream;
Hash: HCRYPTHASH;
F: TMemoryStream;//TFileStream;
Rez: boolean;
Sign: string;
Size: DWORD;
BufLen: DWORD;
b: boolean;
err: DWORD;
begin
Sign:='';
F:=TMemoryStream.Create;
F.LoadFromFile('c:\windows\system32\drivers\acpi.sys');
Size:=F.Size;
b:=CryptAcquireContext(@Prov,nil,nil,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT); //true
b:=CryptCreateHash(Prov,CALG_MD5,0,0,@Hash); // true
b:=CryptHashData(Hash,PByte(F.Memory),Size,0); // true
// Получили хэш файла, вроде бы. Дальше нужно получить подпись хэша,
// используя какой-то ключ, и сверить с подписью, которая где-то хранится.
// Где брать ключ - не пойму, где хранится подпись - тоже.
SetLastError(0);
BufLen:=0;
b:=CryptSignHash(Hash,AT_SIGNATURE,nil,0,nil,@BufLen); // false
if b then Memo1.Lines.Add('YES') ;
err:= GetLastError; // 0x80090016
// Логично, ключ не выбран
if BufLen>0 then begin
SetLength(Sign,BufLen);
CryptSignHash(Hash,AT_SIGNATURE,nil,0,PByte(Sign),@BufLen);
end;
Rez:=CryptVerifySignature(Hash,PByte(Sign),Length(Sign),sKey,nil,0);
if Rez then Memo1.Lines.Add('YES') else Memo1.Lines.Add('NO');
F.Free;
CryptDestroyHash(Hash);
CryptReleaseContext(Prov,0);
end;
Вот такая ботва.
Пытаюсь делать так:
procedure TForm1.Button1Click(Sender: TObject);
var
Prov: HCRYPTPROV;
sKey: HCRYPTKEY;
Stream: TMemoryStream;
Hash: HCRYPTHASH;
F: TMemoryStream;//TFileStream;
Rez: boolean;
Sign: string;
Size: DWORD;
BufLen: DWORD;
b: boolean;
err: DWORD;
begin
Sign:='';
F:=TMemoryStream.Create;
F.LoadFromFile('c:\windows\system32\drivers\acpi.sys');
Size:=F.Size;
b:=CryptAcquireContext(@Prov,nil,nil,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT); //true
b:=CryptCreateHash(Prov,CALG_MD5,0,0,@Hash); // true
b:=CryptHashData(Hash,PByte(F.Memory),Size,0); // true
// Получили хэш файла, вроде бы. Дальше нужно получить подпись хэша,
// используя какой-то ключ, и сверить с подписью, которая где-то хранится.
// Где брать ключ - не пойму, где хранится подпись - тоже.
SetLastError(0);
BufLen:=0;
b:=CryptSignHash(Hash,AT_SIGNATURE,nil,0,nil,@BufLen); // false
if b then Memo1.Lines.Add('YES') ;
err:= GetLastError; // 0x80090016
// Логично, ключ не выбран
if BufLen>0 then begin
SetLength(Sign,BufLen);
CryptSignHash(Hash,AT_SIGNATURE,nil,0,PByte(Sign),@BufLen);
end;
Rez:=CryptVerifySignature(Hash,PByte(Sign),Length(Sign),sKey,nil,0);
if Rez then Memo1.Lines.Add('YES') else Memo1.Lines.Add('NO');
F.Free;
CryptDestroyHash(Hash);
CryptReleaseContext(Prov,0);
end;
Вот такая ботва.