哈希(Hash)算法就是单向散列算法,它把某个较大的集合P映射到另一个较小的集合Q中,假如这个算法叫H,那么就有Q = H(P)。对于P中任何一个值p都有唯一确定的q与之对应,但是一个q可以对应多个p。
作为一个有用的Hash算法,H还应该满足:H(p)速度比较快; 给出一个q,很难算出一个p满足q = H(p);给出一个p1,很难算出一个不等于p1的p2使得 H(p1)=H(p2)。
正因为有这样的特性,Hash算法经常被用来保存密码,我们使用相应的哈希算法对于密码整体P(注意是整体P),计算出它的q,并进行存放。而在密码比对时,使用输入的密码经过哈希函数算出的q和我们已经在存放的该用户的对应的密码经哈希算出的q来进行对比。
这样即使别人知道了q,很难由q推算出p。或者很难推算出一个p使得这个p经过哈希函数算出的q能够和原来的q匹配从而破解密码,————这样不会泄露密码明文,又可以校验输入的密码是否正确。常用的 Hash算法有MD5、SHA1等。
但是需要注意有破解的方法,一种是暴力破解法,就是对于所有的密码情况,我们算出它的q,直到它等于q,这种方式需要计算相当长的时间。第二种就是使用内存换时间,我们先把所有的情况的q都计算出来,存放在一个Tables中,然后一个个去查询,这种方式需要相当大的存储空间。
现在还有第三张折中方法,彩虹表
彩虹表的根本原理就是组合了暴力法和查表法,并在这两者之中取得一个折中,用我们可以承受的时间和存储空间进行破解。它的做法是,对于一个Q = H(P),建立另一个算法R使得 P = R(Q),然后对于一个p,这样进行计算:
p0 -H-> q1 -R->p1 -H-> q2 -R->p2 -H-> q3 -R->p3 … -H-> q(n-1) -R->p(n-1) -H-> qn -R->pn(这里的n使我们自己选取的,如果n很大,那么就代表我们可以用一个p0 pn对记录更多的数据)
简单的说,就是把q用H、R依次迭代运算,最后得到pn,n可能比较大。最后我们把p0和pn都存储下来,把其他的结果都丢弃。然后用不同的p0代入计算,得到多个这样的p的对子。
我们在做破解的时候,给出了一个q,我们来寻找p。我们先把q做一次R运算得到一个值例如叫c1,然后把c1和每一个p对的最后一个做比较,假如和某一个 pn相等,那么有可能这个pn往前推得到的p(n-1)就是我们在追寻的p,为了验证我们把pn对应的p0再做一次链式计算,比对qn是否就是我们之前给出的q,如果是,很明显p(n-1)就是我们在追寻的p,因为 p(n-1) -H-> qn。如果不是就继续寻找直到遍历所有的q0qn对。
事情还刚刚开始,我们再算q -R-> c1 -H-> -R-> c2,再比对c2是否是p(n-1),如果是,那么p(n-2)就可能是p,因为p(n-2)-H-> q(n-1) -R->p(n-1) -H-> qn -R->pn;再算c3、c4直到c(n-1).//该段话有待检验
所以为了阻止黑客们使用彩虹表破解密码,我们考虑使用MD5+salt的方式,这种方式的思路就是既然你可以得到我的密码散列值并通过散列表或是彩虹表破解我的密码,那么我只要我使用某种方式使你的散列表失效就可以了,这里就是给用户输入的明文密码加上一个随机字符串(这里的随机字符串就是salt,我们可以想象成作料)形成一个新的字符串,然后再散列。在存储经散列后的密码的同时也要将salt存储到对应的用户名中去,在下次用户输入密码验证时,就将密码和数据库中的salt相加再散列再和原来用户注册的密码散列值比对。详见
http://blog.sina.com.cn/s/blog_59a133f7010124ee.html
随着计算机的飞速发展,使用CUDA穷举所有情况,快速破解密码称为可能,那么我们该怎么办?我们需要一个不随计算机性能增长而加速的算法,这里就提出了bcrypt算法:
引用
因为bcrypt采用了一系列各种不同的Blowfish加密算法,并引入了一个work factor,这个工作因子可以让你决定这个算法的代价有多大。因为这些,这个算法不会因为计算机CPU处理速度变快了,而导致算法的时间会缩短了。因为,你可以增加work factor来把其性能降下来。
可以参考
http://coolshell.cn/articles/2078.html
分享到:
相关推荐
本篇文章将详细介绍Java中两种常见的密码加密算法:MD5(Message-Digest Algorithm 5)和SHA(Secure Hash Algorithm)。我们将通过`CodeUtil.java`这个代码文件来探讨如何在实际开发中实现这两种加密方式。 首先,...
在IT安全领域,密码的保护至关重要,而MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,常用于密码加密。C#作为一种强大的.NET编程语言,内置了支持MD5加密的类库,使得开发者可以轻松实现密码的加密...
现代实践中,更推荐使用像bcrypt、scrypt或argon2这样的强密码哈希函数,这些函数具有慢速和内存消耗大的特性,能有效抵御彩虹表攻击。 在实际开发中,如果你需要在JavaScript环境中处理密码加密,可以采用以下步骤...
在Java开发中,MD5常用于密码存储,防止明文密码泄露,因为MD5算法是不可逆的,即不能从哈希值推算出原始数据。下面我们将详细探讨Java中实现MD5加密的方法。 1. **MD5的基本原理** MD5算法由Ronald Rivest于1991...
值得注意的是,MD5哈希函数不是安全的密码存储方法,因为它容易受到彩虹表攻击。对于密码存储,通常建议使用更安全的哈希函数,如bcrypt或scrypt,或者使用强加密库如bcrypt.net或argon2net。 总之,C#中实现MD5...
3. **弱安全性**:MD5已不再被视为安全的密码哈希算法,因为它容易受到彩虹表攻击和碰撞攻击。对于密码存储,现在推荐使用更安全的算法,如SHA-256或bcrypt。 在C#中,MD5加密常用于验证文件完整性、临时存储密码...
需要注意的是,MD5并不适合直接用于密码存储,因为它不支持加盐(salt)和迭代,容易受到彩虹表攻击。对于密码存储,应考虑使用加盐的哈希算法,如bcrypt或scrypt。 总的来说,MD5在C#中实现简单,但其安全性已逐渐...
在实际应用中,还应考虑使用加盐的hash值进行验证,以及可能的彩虹表攻击防御策略,例如加盐值的多次hash迭代(如bcrypt或scrypt算法)。总的来说,盐+hash加密是提高密码安全性和保护用户隐私的有效手段。
综上所述,Java中的MD5和SHA-1加密算法主要用于数据校验和密码存储,但鉴于它们的安全性问题,开发者应考虑使用更强大的算法和策略,以确保数据的充分保护。在实际应用中,结合加盐、迭代和其他增强措施,可以大大...
本文将详细探讨Java中用于密码加密的三种主流算法:MD5、SHA256以及SHA512。 MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,能够将任意长度的数据转化为固定长度的摘要信息。它的输出通常是一个128...
在IT行业中,尤其是在网络安全领域,密码的安全存储是至关重要的。...这个项目的源代码应该包含了散列密码、盐值处理以及可能的密钥派生函数的实现,对于理解如何在Java中保护用户密码非常有帮助。
这样,即使两个用户有相同的密码,他们的哈希值也会不同,降低了彩虹表攻击的可能性。 以下是一个简单的C#示例,展示如何使用SHA1算法对字符串进行哈希加密: ```csharp using System; using System.Security....
在IT行业中,密码是网络安全的重要组成部分,特别是在Java编程语言中,处理密码的安全性和有效性是开发者必须面对的关键问题。本文将深入探讨与“密码”相关的Java知识点。 首先,密码的存储是一个敏感话题。为了...
常见的加密算法有MD5、SHA系列、bcrypt、scrypt以及更安全的PBKDF2等。这些算法可以将原始的口令转换为固定长度的哈希值,且不可逆。 在C#中,我们可以使用System.Security.Cryptography命名空间中的类来进行加密...
哈希是一种单向函数,将可读数据转换为不可逆的固定长度的输出,而加盐则是为了增加哈希的复杂性,防止彩虹表攻击。在Python中,我们可以使用`hashlib`库进行哈希操作,例如使用SHA256算法。加盐可以是随机生成的一...
`password_hash()`生成的哈希是不可逆的,且包含盐值,能有效防止彩虹表攻击。但需要注意的是,这种哈希在跨语言数据库迁移时可能不兼容,如Java或.NET。 总结: PHP生成随机码的方法多种多样,可以根据需求选择...