我发现了一些使用 String.crypt 来散列密码的代码(哎呀!),所以我尝试了一种可以根据 BCrypt 散列以及旧的 String.crypt 散列检查密码的方法。
我的发现令我惊讶。以下方法似乎适用于 BCrypt 哈希和 String.crypt 哈希,但我不知道为什么:
def check_password(password, stored_hash)
password.crypt(stored_hash) == stored_hash
end
尝试一下:
string_crypt_pass = "mysuperpass".crypt("$1$abasasa")
bcrypt_pass = BCrypt::Password.create("mysuperpass").to_s
check_password("mysuperpass", string_crypt_pass) #true
check_password("mywrongpass", string_crypt_pass) #false
check_password("mysuperpass", bcrypt_pass) #true
check_password("mywrongpass", bcrypt_pass) #false
这是如何运作的?
如果这些是您正在经历的结果,那么这似乎纯粹是偶然的。
String#crypt
:
返回调用
标准库函数生成的字符串...crypt(3)
请不要再使用此方法。这是遗产;提供的目的只是为了向后兼容早期的 ruby 脚本。由于以下几个原因,在当代程序中使用它是不好的:
C
的行为取决于它运行的操作系统。生成的字符串缺乏数据可移植性。crypt(3)
我已经在多台机器上运行了你的确切代码(包括这个在线Repl,我无法重现你的结果。
每次运行此程序时,我都会收到我所期望的结果:
require 'bcrypt'
def check_password(password, stored_hash)
password.crypt(stored_hash) == stored_hash
end
string_crypt_pass = "mysuperpass".crypt("$1$abasasa")
bcrypt_pass = BCrypt::Password.create("mysuperpass").to_s
check_password("mysuperpass", string_crypt_pass)
#=> true
check_password("mywrongpass", string_crypt_pass)
#=> false
check_password("mysuperpass", bcrypt_pass)
#=> false
check_password("mywrongpass", bcrypt_pass)
#=> false