C# 有人能解释一下BCrypt是如何验证散列的吗?
我正在使用C#和BCrypt.Net散列我的密码 例如:C# 有人能解释一下BCrypt是如何验证散列的吗?,c#,bcrypt,bcrypt.net,C#,Bcrypt,Bcrypt.net,我正在使用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 BCryp
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没有在任何地方保存salt,那么它如何使用哈希验证密码。我唯一的想法是,它不知怎么地在散列的末尾加了盐
这是正确的假设吗
如果BCrypt没有在任何地方保存salt,它如何使用哈希验证密码
显然,它没有做任何这样的事情。盐必须保存在某个地方
让我们在维基百科上查找密码加密方案。发件人:
函数的输出不仅仅是散列:它是一个文本字符串,它还对salt进行编码并标识所使用的散列算法
或者,在回答您关于这个主题的问题时,会包含一个链接到。源代码的相关部分是:
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();
StringBuilder rs=new StringBuilder();
卢比(“$2”);
如果(次要>='a'){
卢比(小调);
}
rs.Append(“$”);
如果(轮数<10){
rs.Append('0');
}
卢比(轮);
rs.Append(“$”);
rs.Append(EncodeBase64(saltBytes,saltBytes.Length));
rs.Append(EncodeBase64(散列,(bf_crypt_ciphertext.Length*4)-1);
返回rs.ToString();
显然,返回的字符串是版本信息,后面是使用的轮数,后面是编码为base64的salt,后面是编码为base64的哈希。BCrypt hash字符串类似于:
$2a$10$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm
\__/\/ \____________________/\_____________________________/
| | Salt Hash
| Cost
Version
在哪里
:算法标识符(BCrypt,UTF8编码密码,以null结尾)2a
:成本系数(210
=1024轮)10
:OpenBSD-Base64编码的salt(22个字符,16个字节)Ro0CUfOqk6cXEKf3dyaM7O
:OpenBSD-Base64编码哈希(31个字符,24个字节)hSCvnwM9s4wIX9JeLapehKK5YdLxKcm
$2a$10$TwentytwocharactersaltThirtyonecharacterspasswordhash
$==$==$======================-------------------------------
BCrypt使用16字节的salt创建24字节的二进制哈希。你可以随意存储二进制散列和盐;没有人说你必须用base-64编码成一个字符串 但是BCrypt是由从事OpenBSD工作的人创建的OpenBSD已经为其密码文件定义了一种格式: $
[HashAlgorithmIdentifier]
$[AlgorithmSpecificData]
这意味着“bcrypt规范”与OpenBSD密码文件格式有着不可分割的联系。每当有人创建“bcrypt哈希”时,他们总是将其转换为ISO-8859-1格式的字符串:
$2a
<成本]$[Base64Salt][Base64Hash]
有几点很重要:
是算法标识符2a
- 1:MD5
- 2:早期的bcrypt,对哪些编码密码存在混淆(过时)
- 2a:当前bcrypt,它将密码指定为UTF-8编码
- 成本是计算哈希时使用的成本因子。“当前”值为10,这意味着内部按键设置要经过1024轮
- 10:210=1024次迭代
- 11:211=2048次迭代
- 12:212=4096次迭代
- OpenBSD密码文件使用的base64算法与其他人使用的base64编码不同;他们有自己的:
因此,bcrypt的任何实现都不能使用任何内置的或标准的base64库Regular Base64 Alphabet: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ BSD Base64 Alphabet: ./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
有了这些知识,您现在可以根据保存的哈希验证密码
correctbatteryhorsestapler
:
$2a$12$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km
BCrypt变异体
关于bcrypt版本有很多混淆
$2$
BCrypt是由OpenBSD人员设计的。它被设计成散列密码以存储在OpenBSD密码文件中。哈希密码以前缀存储,以识别所使用的算法。BCrypt获得前缀$2$
这与其他算法前缀不同:
:MD5$1$
:SHA-256$5$
:SHA-512$6$
- 字符串必须是UTF-8编码的
- 必须包括空终止符
在骗子中发现了一个错误:22个字符对31个字符(复数)。幸运的是,Salt以s开头,所以你可以说它在两个词之间是共享的。尽管如此,它仍然很棒…很好的回答@Ian Boyd,一个问题,成本意味着你想要迭代生成随机值的次数?我的意思是,如果成本是10,它将进行1024次迭代,直到生成hast为止?@Skizo ozᴉʞS从技术上讲,它花费2^n次迭代来生成加密“密钥”。然后使用该密钥对文本“OrpheanBeholderCryQuestion”进行64次加密。但是是的,您可以想象它在生成哈希之前必须运行多少次迭代。