如何在 Delphi 中使用此算法?德尔福有这样的课程吗?
谢谢你。
我使用@alzaimar 提供的链接和维基百科上的一些阅读实现了该算法。当然欢迎提出改进建议!
uses
System.SysUtils, System.Math, IdHMAC, IdHMACSHA1;
type
TIdHMACClass = class of TIdHMAC;
// Modeled after http://www.di-mgt.com.au/cryptoKDFs.html#PKCS5
function PBKDF2(const P: TBytes; const S: TBytes; const C: Integer;
const kLen: Integer; PRFC: TIdHMACClass = nil): TBytes;
var
PRF: TIdHMAC;
D: Integer;
I: Int32;
F: TBytes;
U: TBytes;
J: Integer;
T: TBytes;
function _ConcatenateBytes(const _B1: TBytes; const _B2: TBytes): TBytes; inline;
begin
SetLength(Result, Length(_B1) + Length(_B2));
if Length(_B1) > 0 then
Move(_B1[Low(_B1)], Result[Low(Result)], Length(_B1));
if Length(_B2) > 0 then
Move(_B2[Low(_B2)], Result[Low(Result)+Length(_B1)], Length(_B2));
end;
function _INT_32_BE(const _I: Int32): TBytes; inline;
begin
Result := TBytes.Create(_I shr 24, _I shr 16, _I shr 8, _I);
end;
procedure _XorBytes(var _B1: TBytes; const _B2: TBytes); inline;
var
_I: Integer;
begin
for _I := Low(_B1) to High(_B1) do
_B1[_I] := _B1[_I] xor _B2[_I];
end;
begin
if not Assigned(PRFC) then
PRFC := TIdHMACSHA1;
PRF := PRFC.Create;
try
D := Ceil(kLen / PRF.HashSize);
PRF.Key := P;
for I := 1 to D do
begin
F := PRF.HashValue(_ConcatenateBytes(S, _INT_32_BE(I)));
U := Copy(F);
for J := 2 to C do
begin
U := PRF.HashValue(U);
_XorBytes(F, U);
end;
T := _ConcatenateBytes(T, F);
end;
Result := Copy(T, Low(T), kLen);
finally
PRF.Free;
end;
end;
procedure TestPBKDF2SHA1HMAC;
var
P: TBytes;
S: TBytes;
K: TBytes;
function _BytesToHexString(const _B: TBytes): string;
var
_I: Integer;
begin
for _I := Low(_B) to High(_B) do
Result := Result + IntToHex(_B[_I], 2);
end;
begin
P := TBytes.Create($70, $61, $73, $73, $77, $6F, $72, $64);
S := TBytes.Create($78, $57, $8E, $5A, $5D, $63, $CB, $06);
K := PBKDF2(P, S, 2048, 24);
Assert('BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643' = _BytesToHexString(K));
P := TBytes.Create($70, $61, $73, $73, $77, $6F, $72, $64);
S := TBytes.Create($73, $61, $6C, $74);
K := PBKDF2(P, S, 1, 20);
Assert('0C60C80F961F0E71F3A9B524AF6012062FE037A6' = _BytesToHexString(K));
K := PBKDF2(P, S, 2, 20);
Assert('EA6C014DC72D6F8CCD1ED92ACE1D41F0D8DE8957' = _BytesToHexString(K));
K := PBKDF2(P, S, 4096, 20);
Assert('4B007901B765489ABEAD49D926F721D065A429C1' = _BytesToHexString(K));
K := PBKDF2(P, S, 16777216, 20);
Assert('EEFE3D61CD4DA4E4E9945B3D6BA2158C2634E984' = _BytesToHexString(K));
P := TBytes.Create($70, $61, $73, $73, $77, $6F, $72, $64, $50, $41,
$53, $53, $57, $4F, $52, $44, $70, $61, $73, $73, $77, $6F, $72, $64);
S := TBytes.Create($73, $61, $6C, $74, $53, $41, $4C, $54, $73, $61, $6C,
$74, $53, $41, $4C, $54, $73, $61, $6C, $74, $53, $41, $4C, $54, $73, $61,
$6C, $74, $53, $41, $4C, $54, $73, $61, $6C, $74);
K := PBKDF2(P, S, 4096, 25);
Assert('3D2EEC4FE41C849B80C8D83662C0E44A8B291A964CF2F07038' = _BytesToHexString(K));
end;
做任何你喜欢的事,但使用它需要你自担风险。