有人可以解释BCrypt如何validation散列?
我正在使用C#和BCrypt.Net哈希我的密码。
例如:
string salt = BCrypt.Net.BCrypt.GenerateSalt(6); var hashedPassword = BCrypt.Net.BCrypt.HashPassword("password", salt); //This evaluates to True. How? I'm not telling it the salt anywhere, nor //is it a member of a BCrypt instance because there IS NO BCRYPT INSTANCE. Console.WriteLine(BCrypt.Net.BCrypt.Verify("password", hashedPassword)); Console.WriteLine(hashedPassword);
如果BCrypt没有在任何地方保存盐,那么如何用哈希validation密码。 我唯一的想法是它以某种方式在散列末尾添加salt。
这是一个正确的假设吗?
如果不在任何地方储存盐,BCrypt如何用哈希validation密码?
显然这没有做任何这样的事情。 盐必须保存在某个地方。
我们来看维基百科上的密码encryptionscheme。 来自http://en.wikipedia.org/wiki/Crypt_(Unix); :
函数的输出不仅仅是散列:它是一个文本string,它也编码盐并标识所使用的散列algorithm。
另外,对这个主题的上一个问题的答案包括一个链接到源代码 。 而不是要求互联网阅读你的源代码,你可以select自己阅读。 这可能会让你的答案更快。 源代码的相关部分是:
StringBuilder rs = new StringBuilder(); rs.Append("$2"); if (minor >= 'a') { rs.Append(minor); } rs.Append('$'); if (rounds < 10) { rs.Append('0'); } rs.Append(rounds); rs.Append('$'); rs.Append(EncodeBase64(saltBytes, saltBytes.Length)); rs.Append(EncodeBase64(hashed,(bf_crypt_ciphertext.Length * 4) - 1)); return rs.ToString();
很显然,返回的string是版本信息,接着是使用的循环次数,接着是编码为base64的盐,接着是编码为base64的哈希。
BCrypt哈希string如下所示:
$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm $==$==$======================-------------------------------
哪里
-
2a
:algorithm标识符(BCrypt,UTF8编码密码,空终止) -
10
:成本因素(210
= 1,024轮) -
Ro0CUfOqk6cXEKf3dyaM7O
:OpenBSD-Base64编码盐(22个字符,16字节) -
hSCvnwM9s4wIX9JeLapehKK5YdLxKcm
:OpenBSD-Base64编码散列(31个字符,24个字节)
编辑 :我只是注意到这些词完全适合。 我不得不分享:
$2a$10$TwentytwocharactersaltThirtyonecharacterspasswordhash $==$==$======================-------------------------------
BCrypt创build一个24字节的二进制散列,使用16字节的盐。 你可以自由地存储二进制散列和盐,不pipe你喜欢什么; 没有什么说你必须将base-64编码成一个string。
但是BCrypt是由在OpenBSD上工作的人创build的。 OpenBSD已经为其密码文件定义了一个格式:
$ [HashAlgorithmIdentifier]
$ [AlgorithmSpecificData]
这意味着“bcrypt规范”与OpenBSD的密码文件格式是不可分割的。 每当有人创build一个“bcrypt hash”,他们总是把它转换成ISO-8859-1格式的string:
$ 2a
$ [Cost]
$ [Base64Salt][Base64Hash]
几点重要的一点:
-
2a
是对数标识符- 1:MD5
- 2:早期的bcrypt,对哪些编码密码在(过时)
- 2a:当前的bcrypt,它将密码指定为UTF-8编码
- 成本是计算散列时使用的成本因素。 “当前”值是10,这意味着内部密钥设置要经过1,024个回合
- 10:2 10 = 1024次迭代
- 11:2 11 = 2048次迭代
- 12:2 12 = 4,096次迭代
-
OpenBSD密码文件使用的base64algorithm与其他人使用的Base64编码不同; 他们有自己的:
Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
所以任何bcrypt的实现都不能使用任何内build或标准的base64库
有了这些知识,你现在可以validation密码correctbatteryhorsestapler
对保存的散列:
$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km