我很想使用“.NET Encryption Simplified”年描述的Jeff Atwood的加密类,因为它很容易理解.它有一个哈希类 – 但是我不知道如何“登录”并比较散列之后的哈希值.这是Jeff使用他的加密类演示他的哈希方法:
Sub DemoHash() Dim d As New Encryption.Data( _ "{ts '2004-10-09 08:10:04'}The world is beautiful and needs caring by its children") Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA1) Dim hash2 As New Encryption.Hash(Encryption.Hash.Provider.SHA256) Dim hash3 As New Encryption.Hash(Encryption.Hash.Provider.SHA384) Dim hash4 As New Encryption.Hash(Encryption.Hash.Provider.SHA512) Dim hash5 As New Encryption.Hash(Encryption.Hash.Provider.MD5) Dim hash6 As New Encryption.Hash(Encryption.Hash.Provider.CRC32) hash.Calculate(d) hash2.Calculate(d) hash3.Calculate(d) hash4.Calculate(d) hash5.Calculate(d) Console.WriteLine("SHA1: " & hash.Value.Hex) Console.WriteLine("SHA256: " & hash2.Value.Hex) Console.WriteLine("SHA384: " & hash3.Value.Hex) Console.WriteLine("SHA512: " & hash4.Value.Hex) Console.WriteLine("MD5: " & hash5.Value.Hex) Console.WriteLine("CRC32: " & hash6.Calculate(d).Hex) Console.WriteLine() Dim salt As New Encryption.Data("salty!") Console.WriteLine("Salted CRC32: " & hash6.Calculate(d,salt).Hex) Console.WriteLine("Press ENTER to continue...") Console.ReadLine() End Sub
所以我的问题是:
>我可以加密密码(虽然我没有存储的意图)和哈希字符串.如果我有一个名为“barry”的用户使用“fishlegs”的密码,那么存储他的密码和检索它的最好方式是什么?
>在sql Server中;是二进制还是nvarchar存储哈希的最佳选择?
>基于’barry’和他的密码有效的哈希存储?它是附加在盐上的“鱼鳞”的加密
密码学很难!
感谢任何人谁可以协助…
解决方法
您要用于存储密码的内容是称为“单向散列”的功能.这意味着,对于您提供功能的任何输入,相同的输入将始终给出相同的结果.但是,没有数学过程可以让您获取该结果字符串,并找出原始输入.
我们以MD5作为散列函数的例子.如果我在字符串“password”上运行MD5,我将总是得到结果“5f4dcc3b5aa765d61d8327deb882cf99”.但是,如果你只是给某个结果字符串(“5f4d …”)给他人,那么他们不可能应用一些数学过程来“反转”该函数,并确定它来自“密码”.
这意味着当用户首次设置密码时,您可以对其应用散列函数,并存储结果.所以不要存储“密码”,而是存储“5f4dcc3b5aa765d61d8327deb882cf99”.然后,当用户尝试登录时,您可以在登录表单中的密码框中输入任何内容,并应用相同的哈希功能.如果您获得与数据库中存储的结果相同的结果,则必须输入与其最初选择的密码相同的密码,即使您不知道该原始密码是什么.
现在,尽管不可能“反转”散列函数,但是相同的输入总是给出相同的输出的事实意味着有人可以简单地建立一个输入/输出对的大数据库,并且使用它来有效地反转散列.这被称为“彩虹表”.互联网上有许多可用的,所以使用简单的哈希算法是不安全的,以防万一你的数据库遭到破坏.也就是说,即使在数学上不可能采取“5f4dcc3b5aa765d61d8327deb882cf99”,并且弄清楚它是从“密码”上运行MD5,在实践中很容易确定.所有你需要做的是通过MD5运行字典中的每个单词并存储结果,您可以轻松地反转简单的密码.
这是“盐渍”的地方.如果您为每个用户生成一个随机的“盐”字符串,并将其附加到其密码,则会有效地破坏彩虹表.例如,假设上述同一用户将其密码注册为“密码”.我们生成一个随机的8个字符的盐,以便在它们之前附加密码.假设是“A4BR82QX”.现在,我们哈希的“A4BR82QX密码”代替散列“密码”.这给出了结果“87a4ba071c8bcb5efe457e6c4e6c4490”,所以我们把它存储在数据库中,连同盐串.那么当这个用户尝试登录时,而不是直接哈希和比较他们在登录表单中输入的密码,我们把它们输入的内容,再次将“A4BR82QX”放在前面,哈希.就像以前一样,如果它与存储的哈希匹配,我们知道他们输入了正确的密码.
有效地,您在这里做的是使得预先生成的彩虹表对于尝试破解数据库中的密码是无用的.由于盐是随机的,并且每个用户具有不同的(通常),攻击者将必须为每个用户重新生成其彩虹表.这更困难.
然而,还有一个问题,那就是生成MD5哈希快.即使这样的盐渍需要他们重新生成彩虹台,因为MD5的速度有多快,所以可以很快地创建一些完整的彩虹表.所以如果他们只想在您的网站上破解一个高价值的帐户,那么花费一些时间来生成彩虹表来尝试和扭转该密码并不是一件大事.如果高价值帐户的原始密码本身不够安全,即使使用盐渍,仍然会很快发现.
所以下一步是找到一个缓慢的散列函数,并使用这个代替像MD5这样的快速函数.让您的网站花费额外的几秒钟来检查登录并不是什么大不了的事情.但是当有人试图生成彩虹表以破解密码时,每个条目需要几秒钟就是绝对的杀手.我在这里写得足够好,所以我刚刚完成链接到这篇文章,这有关于选择一个好的,缓慢的哈希函数的详细信息:Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes.
这是一个非常大的答案,如果有什么不清楚,请让我知道在一个评论,我会编辑细节.