在Delphi中实现PBKDF2?

时间:2013-01-02 04:49:24

标签: delphi delphi-xe3 pbkdf2

如何在Delphi中使用此算法?在Delphi中有没有一个类?

谢谢。

1 个答案:

答案 0 :(得分:3)

我使用@alzaimar提供的链接和维基百科上的一些阅读来实现算法。当然欢迎提出改进建议!

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;

做任何你喜欢的事情,但使用它需要你自己承担风险。