我一直在探索 Twin-Bcrypt JavaScript库,发现了一件奇怪的事情。有一次,我在服务器端使用PHP base64_encode(openssl_random_pseudo_bytes(16))
制作了自己的盐,并在TwinBcrypt.hash()
函数中使用它,由于库中的常规模式不匹配,因此响应盐无效。所以,模式是:
var SALT_PATTERN = /^\$2[ay]\$(0[4-9]|[12][0-9]|3[01])\$[.\/A-Za-z0-9]{21}[.Oeu]/;
我的盐看起来很好,除了一件事 - 这到底是什么 - [.Oeu]
?
我的第一个问题是,为什么他们希望salt以 dot , O , e 或结束û?据我所知openssl_random_pseudo_bytes()
生成安全 CSPRNG ,但由于模式,JS库不想接受它。
第二个问题 - 盐是否有任何安全理由以/[.Oeu]/
模式结束?
我会非常感谢任何帮助,因为没有太多关于它的信息。
答案 0 :(得分:4)
我不太了解bcrypt,但看来Twin-Bcrypt希望salt
参数包含完整的类型标记(2a
/ 2y
/ {{1 }}),cost参数,和实际的加密盐值。 (我相信这样做是为了满足其他库的期望。)加密盐值只是2x
参数字符串的最后22个字符,表示128位值。
要真正解决您的问题,您需要做两件事:
使用salt
为您的盐添加前缀,使其具有类型标记和费用参数。
将您的PHP $2y$10$
结果映射到bcrypt的非标准base64值。作为参考,值为:
base64_encode
如果您只想将标准base64转换为brcypt-base64字符串,则可以将所有Standard: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
bcrypt: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
替换为+
,但这将导致不同的值(因为标准.
}是+
,而62
是.
,所有其他值也都是偏移量)。如果您想要一个与原始字符串值相同的brypt字符串,则需要用其bcrypt等效字符替换每个字符。
您可能还需要从标准字符串中删除尾随0
(如果存在)。
额外信息:为什么盐必须以=
结束?
bcrypt中的盐是128位。每个base64字符传递6位信息。这意味着21个base64字符可以均匀地传输126位。最后的2位必须以最后的第22个字符编码。由于该字符仅由2位定义,因此它只能有4个可能的值。
当我们检查brypt的base64字符池时,我们看到:
[.Oeu]
从零开始计算,我们看到这些值出现在标记处:
./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
所以最后两位是设置最终字符的高端位。