我有一个白帽子黑客的朋友。他说md5并不是那么糟糕,实际上是非常安全的,只要我们正确使用它。
我相信他是对的。据我所知,有三种方法可以打破哈希:
我和我的朋友认为Blowfish并不是真的有需要,也可能是有害的,因为它可以减慢密码验证过程,并且它可以与DDOS攻击一起使用,即使使用较少的资源也可以分解服务器。
所以,我想确保遵循算法真的安全吗?并且,是否有真正的理由选择Blowfish哈希算法?
// return a 256 bit salt + 128 bit md5 binary hash value
function hash(password, salt=null)
{
salt = (salt != null) ? salt : Random256BitBinaryValueGenerator();
// What about using another user-specified parameter, like email address as salt?
return salt + md5(salt + password) + md5(password + salt);
// Or just use a non-cryptographic hash algorithm like crc32 to prevent collisions:
// return salt + md5(salt + password) + crc32(salt + password);
// Or even use two different salts:
// return salt + md5(salt + password) + md5('C' + salt + password);
}
// check password
function check(password, hash_value)
{
return hash(password, substring(hash_value, 0, 32)) == hash_value;
}
答案 0 :(得分:15)
MD5的collision resistance属性已经被打破了很长时间。请注意,preimage resistance和第二个原像抗性尚未被破解,但是因为有更好的算法(SHA-2),移动到这些算法是明智的,而不是依赖于已经开始的加密哈希失去其加密属性。注意:当存储散列密码时,碰撞阻力属性无关紧要< - 你需要确定的是,前映像电阻属性是合理的 - 在某些情况下找到原始密码在计算上是不可行的哈希值(和盐)。正如我所提到的,由于其中一个加密属性已被破坏,我担心其他人将很快跟进。
当您存储密码哈希时,您应该建立一些保护,以便在攻击者设法提取这些哈希值时无法检索原始密码。这很重要,因为如果攻击者设法检索密码表,那么他们就可以使用这些数据直接登录到您的系统,或者登录到用户重复使用相同密码的其他系统。
存储密码时,使用慢速算法非常重要,例如bcrypt,scrypt或pbkdf2。合法用户在首次登录时只需要经历一次延迟。攻击者必须经历他们猜测的每个密码的延迟 - 记住彩虹表将不会在这里使用,因为密码被腌制。攻击者将根据您选择的算法和迭代计数对每个密码进行散列扫描。
调整系统的迭代次数非常重要,因为正确的&#34;强度&#34;用于登录系统时不会给合法用户带来任何真正的烦恼。这被称为&#34;轮数&#34;或者#34;迭代计数&#34;。例如,迭代大约一秒应该就足够了。可以安全地假设攻击者可以以系统硬件速度的十倍速度运行哈希值。因此,这限制了攻击者每秒10次猜测,而不是MD5的20亿次。
是的,您的应用程序在登录时执行的额外处理可能是攻击者向您的应用程序提交真正长密码的目标,或者是为了消耗服务器上的CPU和内存资源而反复使用登录请求命中它。 You are right to be concerned
可以通过以下方式减轻这些类型的攻击:
答案 1 :(得分:5)
MD5的问题正是如此之快,您可以使用通用硬件计算9 Giga MD5/s。要用大约200000个单词来强制整个英语词典,你只需要几分之一毫秒。
这就是像BCrypt这样的适当哈希算法提供成本因素的原因。成本因子定义了计算哈希所需的时间,并且可以在将来添加。登录50毫秒并不是一个障碍,但对于暴力破解它是致命的。
答案 2 :(得分:0)
你说减慢验证是一个问题,但它是防止泄露哈希和蛮力攻击的唯一防御。现代解决方案重复散列值(即:数千次)只是为了提高计算成本。