delphi XE8 的多设备 Bcrypt 库

Multi-device Bcrypt library for delphi XE8

我找到了两个可以为 windows 编译的 Bcrypt 库,但我很难在 Delphi XE8 中为 Android 编译它们。

第一个是 https://github.com/chinshou/bcrypt-for-delphi,它不需要为 Windows 编译任何修改。

对于第二个 https://github.com/PonyPC/BCrypt-for-delphi-lazarus-fpc 我不得不在 checkPassword 函数中进行一些小的调整以获得相同的结果,因为它是 FreePascal 特定的:

function checkPassword(const Str: string; const Hash: ansistring): boolean;
var
  RegexObj: TRegEx;
  match   : TMatch;
  Salt    : String;
begin
  RegexObj := TRegEx.Create('^$2a$10$([\./0-9A-Za-z]{22})',[roIgnoreCase]);
  match := RegexObj.Match(Hash);
  if match.Success then
  begin
    Salt := Copy(match.Value,8,22);
    Result := HashPassword(Str, Salt) = Hash;
  end
  else
  begin
    Result := False;
  end;
end;

将平台从 Win 更改为 Android 后,第一个显示了很多错误,因为它依赖于 ComObj、Windows 和 ActiveX。用 RegularExpressions 和 Types 替换 RegExpr 后的第二个显示仅显示 changes in the String variable 导致的冲突。该代码使用 AnsiString、AnsiChar,我不能只用 String 和 Char 替换它们,因为它会影响哈希函数。

我错过了什么?我应该做哪些其他修改来替换过时的 AnsiString 和 AnsiChar 声明,从而允许为 Android?

编译代码

第二个库的String声明问题是由HashPassword函数中的move命令引起的

Move(password[1], key[0], Length(password));

因为在将声明从 AnsiString 替换为 String 后,密码变量的大小发生了变化。用一个简单的 for 循环和 Ord 函数替换它可以解决问题,尽管可能有更优雅的方法。

function HashPassword(const Str: string; const salt: string): string;
var
  password: String ;
  key, saltBytes, Hash: TBytes;
  i: Integer;
begin
  password := AnsiToUtf8(str);

  SetLength(key, Length(password) + 1);
  for i := 0 to length(password)-1 do
    key[i]:=ord(password[i+1]);

  key[high(key)] := 0;
  saltBytes := BsdBase64Decode(salt);
  Hash := CryptRaw(key, saltBytes);
  Result := FormatPasswordHashForBsd(saltBytes, Hash);
end;

总而言之,将 second library 转换为 Android 兼容代码需要进行以下更改:

  • 修改checkPassword函数中的正则表达式代码 根据问题

  • 中发布的代码
  • 通过将 "RegExpr" 替换为 "RegularExpressions, Types"

  • 来更改使用部分
  • 将所有声明从 AnsiString 替换为 String,将 AnsiChar 替换为 Char

  • 修改HashPassword函数如上图