Delphi(使用 10.3 Professional)中是否有一个“简单”函数,允许我使用
password_hash()
使用 PHP 中生成的哈希代码来验证密码?与 PHP 的功能相同的函数 password_verify($password, $hash)
?
使用 PHP 的示例:
$hash = password_hash('thisismyaccesscode', PASSWORD_DEFAULT);
// $hash == '$2y$10$21qire0Qwz/gj6HEej3tf.skdiZzeB.rgFdg7qD.5rAhE/AFg.U8q'
现在我正在寻找一个 Delphi 函数,它告诉我,是否可以根据此哈希验证输入到我的程序中的密码。
背景:我的网络服务器有一个用户记录列表。使用网络服务,我可以从该服务器检索用户的密码哈希值。我知道它是使用 PHP 函数生成的
password_hash()
。我想让我的用户能够使用网站上的访问代码登录到我的 Delphi 程序。因此,我从 Web 服务器获取密码哈希,并希望在我的 Delphi 程序中本地验证它,而不是将密码上传到服务器并使用 PHP 检查。
我找到了一个 BCrypt Delphi 库,它可以满足我的需要。 实现起来非常简单:只需将
bcrypt.pas
添加到用途列表中即可。
类
TBCrypt
仅包含类函数。
TBCrypt.CheckPassword
满足我的需要:输入密码和哈希(我了解到,我在问题中显示的哈希字符串包含“盐”)。
我的密码检查类似于:
PWOK := TBCrypt.CheckPassword(KeyedInPwdString, PWHashStringFromWebDB, BooleanDummy);
PHP 函数“password_hash()”使用的算法对同一字符串返回不同的哈希值,因为它们的计算取决于所使用的盐和开发人员定义的成本以及服务器硬件(成本必须足够高,以便该函数将根据硬件能力在所需的时间内进行计算)。因此,算法必须在同一设备上使用相同的盐和参数运行(如果您优化硬件,那么您必须调整成本以获得相同的效率,并设置迁移过程)才能返回相同的哈希值。
在这种情况下,针对哈希的验证必须在服务器端进行,并且您必须在请求中以纯文本形式将密码发送到您实现 Web 服务以验证密码的服务器。您将必须使用 HTTPS 并努力确保传输安全。
如果您的服务器是用 PHP 开发的,您可以使用函数“password_verify()”来验证“password_hash()”生成的哈希值。 但如果你的服务器是用Delphi开发的,那么就没有现成的验证功能。您必须使用您使用的算法的 Delphi 端口,然后实现一个验证密码的函数(用存储的哈希包装哈希算法和字符串验证)。
正如您在文档中看到的,PHP 的
password_hash
返回的字符串具有格式。如果您的哈希值以 $2y
开头...那么您还可以理解(重新实现)PHP password_hash
函数,如下所示(仍在 PHP 中):
$salt = base64_encode($random_string_of_22_characters_in_length);
$salt = str_replace('+', '.', $salt);
$hash = crypt('supers3cretpassword', '$2y$10$'.$salt.'$');
crypt()
是基于标准 UNIX DES 算法的实现,您可以轻松找到该算法的 Delphi 实现。快速谷歌返回了TUnixCrypt,但我确信还有其他。来自其文档:
...它的工作原理与
Unix 命令crypt(key, salt)
...这是您缺失的环节。您只需要从服务器的哈希值中解析盐,并用它和用户密码生成一个新的哈希值。
请注意,原始密码可能采用不同的字符编码,请确保对密码进行相应编码,否则非 ASCII 密码将无法验证。