php Drupal 7密码的 Delphi 身份验证

ct2axkht  于 2023-01-04  发布在  PHP
关注(0)|答案(1)|浏览(192)

我正在尝试用 Delphi 10验证Drupal 7密码。
我正在模仿使用PHP hash( ,,TRUE)函数的_password_crypt()函数。
散列过程重复进行,从字符串开始,切换到字节;

$hash = hash($algo, $salt . $password, TRUE);
  do {
    $hash = hash($algo, $hash . $password, TRUE);
  } while (--$count);
  $len = strlen($hash);
  $output = $setting . _password_base64_encode($hash, $len);

THashSHA2能否复制这一点?如果可以,您能否概述一下该方法?

hi3rlvi2

hi3rlvi21#

unit DrupalPasseordClass;

interface

uses System.SysUtils, System.Classes, System.Hash;

const
  DRUPAL_HASH_LENGTH=55;

type
  TDrupalPassword=record

  private
    function _password_itoa64(): String;
    function CombineByteArrays(ABytes, BBytes: TBytes): TBytes;
    function _password_get_count_log2(setting: String): Integer;
    function _password_base64_encode(hash: TBytes; count: Integer): String;
  public
    function CheckPassword(Password, StoredHash: String): Boolean;

End;

implementation

function TDrupalPassword._password_itoa64(): String;
begin
  result:='./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
end;

function TDrupalPassword._password_get_count_log2(setting: String): Integer;
var
 itoa64: String;
begin
  itoa64:= _password_itoa64();
  result:=Pos(setting[4], itoa64)-1;
end;

function TDrupalPassword.CombineByteArrays(ABytes, BBytes: TBytes): TBytes;
var
  k: Integer;
begin
  result:=ABytes;
  SetLength(result, Length(ABytes)+Length(BBytes));
  for k := 0 to Length(BBytes)-1 do
    result[Length(ABytes)+k]:=BBytes[k];
end;

function TDrupalPassword.CheckPassword(Password, StoredHash: String): Boolean;
var
  Count, k: Integer;
  algorithm, ComputedHash, Salt, Setting: String;
  Hash: TBytes;
  bPassword, bSalt, bSeed: TBytes;
  BS: TBytesStream;
begin
  BS:=TBytesStream.Create;
  try
    algorithm:=Copy(StoredHash,1, 3);
    if not algorithm.Equals('$S$') then
       Exit(False);

    Setting:=Copy(StoredHash,1, 12);
    Salt:=Copy(StoredHash, 5, 8);

    bSalt:=TEncoding.UTF8.GetBytes(sALT);
    bPassword:=TEncoding.UTF8.GetBytes(Password);
    bSeed:=CombineByteArrays(bSalt, bPassword);

    BS.WriteData(bSeed, Length(bSeed));
    BS.Seek(0, soBeginning);
    Hash:=THashSHA2.GetHashBytes(BS, SHA512);

    Count:=1 ShL _password_get_count_log2(Setting);
    for k:=1 to Count do
    begin
      bSeed:=CombineByteArrays(Hash, bPassword);
      BS.Clear;
      BS.Write(bSeed, Length(bSeed));
      BS.Seek(0, soBeginning);
      Hash:=THashSHA2.GetHashBytes(BS, SHA512);
    end;
    ComputedHash:=Setting+_password_base64_encode(Hash, Length(Hash));
    ComputedHash:=Copy(ComputedHash,1,DRUPAL_HASH_LENGTH);
    result:=(StoredHash=ComputedHash);
  finally
    bs.Free;
  end;
end;

function TDrupalPassword._password_base64_encode(hash: TBytes; count: Integer): String;
var
  Index, Value: Integer;
  itoa64: String;
begin
  result:='';
  itoa64:= _password_itoa64();
  Index:=0;
  repeat
    value:=ord(hash[Index]);
    result:=result+itoa64[(value and $3f)+1];
    inc(Index);
    if (Index < count) then
      value:=value or  ord(Hash[Index]) shl 8;

    result:=result+itoa64[(value shr 6 and $3f)+1];
    if (Index >= count) then
      break;
    inc(Index);

    if (Index < count) then
      value:=value or ord(Hash[Index]) shl 16;

    result:=result+itoa64[(value shr 12 and $3f)+1];
    if (Index>= count) then
      break;
    inc(Index);
    result:=result+itoa64[(value shr 18 and $3f)+1];
  until (Index>count);
end;

end.

相关问题