PHP Bcrypt Salt 自 7.0 起
PHP Bcrypt Salt as of 7.0
我正在开发一个应用程序,我必须在其中比较数据库中的 2 个散列密码,一个密码在 PHP 和 $Password = password_hash($RawPassword, PASSWORD_BCRYPT);
中生成
而发送到数据库以与 PHP 散列密码进行比较的另一个密码是在 Java 中生成的 String hashedPassword = BCrypt.hashpw(password);
从 PHP 7.0 开始,加盐是自动生成的,我怎么知道 PHP 中应用了什么加盐,以便我可以将其应用到我的 java 代码中?或者有没有办法仍然指定不再在 PHP 散列的文档中的盐?
绝大多数 bcrypt impls 背后的标准思想是数据库中的内容看起来像 y$AB
,其中 A 是 22 个字符,B 是 31 个字符,总共 60 个字符。A 是:left(base64(salt + 00 + 00), 22)
和 B 是:left(base64(bcryptraw(salt + pass)), 31)
。 (2y
指的是哈希算法/编辑:2y 和 2a 或多或少是可以互换的;大多数 bcrypt impls 将它们视为相同,并且不太可能重要。10
指的是应用的 bcrypt 轮数。10 是常见的,通常是你想要的)。
其中:
base64(X)
= 应用 base64 转换,使用 .和 / 作为第 63 和 64 个字符。
+
是串联的,即 salt
(一个 16 字节的字节数组)添加了 2 个零字节。
left(chars, size)
表示:取前 size
个字符并丢弃其余字符。
salt
是以字节为单位的盐,pass
是密码,通过 UTF_8 转换为字节。 (如果不是通过 UTF-8 转换,它通常是 $2a$,你应该升级,密码中有非 ascii 字符的人在旧的 $2a$ 模式下会得到非常糟糕的哈希值!
这个字符串包含 bcrypt impl 需要检查给定密码是否正确的所有内容。因此,所有非愚蠢的 bcrypt 库 impls 只有两种方法,没有其他方法:
// This is for when the user creates an account or edits their password.
// send the password to this method, then take the string it returns,
// and store this in your database.
hash = crypto.hashPass(password);
// This is for when the user tries to log in. For 'hash', send the thing
// that the hashPass method made for you.
boolean passwordIsCorrect = crypto.checkPass(password, hash);
编辑:注意:一个真正设计良好的加密库调用这些方法 processNewPassword
和 checkExistingPassword
以避免导致你问这个问题的那种混淆,但不幸的是,似乎没有人有足够的资金思考 5 秒钟他们的名字所暗示的意思。不幸的。安全很难。
如果您的 BCrypt API 不能像这样工作,摆脱它,并找到像这样工作的标准实现。
听起来你使用了错误的方法。要检查密码,请不要使用 hashPass。使用 checkPass,或者在你的 impl 中用于 checkPass 的任何东西(它可能被称为 checkPw
或 verifyPw
或 validate
,等等。它需要 2 个字符串)。
因此,你不应该生成盐,也不应该从这样的字符串中提取盐。让 bcrypt 库来做。标准 bcrypt 库生成的那些 'hashes'(y$
字符串)是可以互换的;您的 PHP 图书馆可以生成 em,您的 java 图书馆可以检查 em,反之亦然。
如果您必须提取盐(但没有提取):
- 取那 22 个字符,在
$protocol$rounds$
部分之后。
- 将 'aa' 添加到此。
- base64解码结果
- 这会得到 18 个字节。扔掉最后2个字节,其中包含垃圾。
- 剩下的16个字节是盐。
你绝对不应该这样写 - 你的 bcrypt 库会这样做。
我正在开发一个应用程序,我必须在其中比较数据库中的 2 个散列密码,一个密码在 PHP 和 $Password = password_hash($RawPassword, PASSWORD_BCRYPT);
中生成
而发送到数据库以与 PHP 散列密码进行比较的另一个密码是在 Java 中生成的 String hashedPassword = BCrypt.hashpw(password);
从 PHP 7.0 开始,加盐是自动生成的,我怎么知道 PHP 中应用了什么加盐,以便我可以将其应用到我的 java 代码中?或者有没有办法仍然指定不再在 PHP 散列的文档中的盐?
绝大多数 bcrypt impls 背后的标准思想是数据库中的内容看起来像 y$AB
,其中 A 是 22 个字符,B 是 31 个字符,总共 60 个字符。A 是:left(base64(salt + 00 + 00), 22)
和 B 是:left(base64(bcryptraw(salt + pass)), 31)
。 (2y
指的是哈希算法/编辑:2y 和 2a 或多或少是可以互换的;大多数 bcrypt impls 将它们视为相同,并且不太可能重要。10
指的是应用的 bcrypt 轮数。10 是常见的,通常是你想要的)。
其中:
base64(X)
= 应用 base64 转换,使用 .和 / 作为第 63 和 64 个字符。+
是串联的,即salt
(一个 16 字节的字节数组)添加了 2 个零字节。left(chars, size)
表示:取前size
个字符并丢弃其余字符。salt
是以字节为单位的盐,pass
是密码,通过 UTF_8 转换为字节。 (如果不是通过 UTF-8 转换,它通常是 $2a$,你应该升级,密码中有非 ascii 字符的人在旧的 $2a$ 模式下会得到非常糟糕的哈希值!
这个字符串包含 bcrypt impl 需要检查给定密码是否正确的所有内容。因此,所有非愚蠢的 bcrypt 库 impls 只有两种方法,没有其他方法:
// This is for when the user creates an account or edits their password.
// send the password to this method, then take the string it returns,
// and store this in your database.
hash = crypto.hashPass(password);
// This is for when the user tries to log in. For 'hash', send the thing
// that the hashPass method made for you.
boolean passwordIsCorrect = crypto.checkPass(password, hash);
编辑:注意:一个真正设计良好的加密库调用这些方法 processNewPassword
和 checkExistingPassword
以避免导致你问这个问题的那种混淆,但不幸的是,似乎没有人有足够的资金思考 5 秒钟他们的名字所暗示的意思。不幸的。安全很难。
如果您的 BCrypt API 不能像这样工作,摆脱它,并找到像这样工作的标准实现。
听起来你使用了错误的方法。要检查密码,请不要使用 hashPass。使用 checkPass,或者在你的 impl 中用于 checkPass 的任何东西(它可能被称为 checkPw
或 verifyPw
或 validate
,等等。它需要 2 个字符串)。
因此,你不应该生成盐,也不应该从这样的字符串中提取盐。让 bcrypt 库来做。标准 bcrypt 库生成的那些 'hashes'(y$
字符串)是可以互换的;您的 PHP 图书馆可以生成 em,您的 java 图书馆可以检查 em,反之亦然。
如果您必须提取盐(但没有提取):
- 取那 22 个字符,在
$protocol$rounds$
部分之后。 - 将 'aa' 添加到此。
- base64解码结果
- 这会得到 18 个字节。扔掉最后2个字节,其中包含垃圾。
- 剩下的16个字节是盐。
你绝对不应该这样写 - 你的 bcrypt 库会这样做。