为什么不使用MD5进行密码散列?

我有一位朋友是白帽黑客。 他说md5并不是真的那么糟糕,而且确实很安全,只要我们正确使用它。

我相信他是对的。 据我所知,有三种方法可以打破哈希:

  • 使用彩虹表(可以通过长时间/随机盐进行保护)
  • 碰撞(可以通过多种盐或散列来防止 - 如下面的示例所示)
  • 生成时间(如果我们为每个用户使用足够长的盐值 - AFAIK,这并不重要)
  • 我和我的朋友相信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;
    }
    

    MD5的抗碰撞性能已经被打破了很长一段时间。 请注意,原像阻抗和第二原像阻力尚未破解,但由于有更好的算法(SHA-2),转移到这些算法是明智的,而不是依赖于已经开始丢失其加密哈希的算法密码属性。 注意:存储哈希密码时,碰撞抵抗属性并不重要 - 您需要确保的是,图像抗阻性是健全的 - 在给定某个哈希值(和盐)的情况下找到原始密码在计算上是不可行的。 正如我所提到的那样,由于其中一个加密属性已经被破坏,我会担心其他人会很快跟进。

    当您存储密码散列时,您应该构建一些保护措施,以便在攻击者设法提取这些散列时,无法检索原始密码。 这一点很重要,因为如果攻击者设法检索密码表,则他们可以使用这些数据直接登录到系统,或者登录到其他用户重新使用相同密码的系统。

    存储密码时,使用慢速算法很重要,例如bcrypt,scrypt或pbkdf2。 首次登录时,合法用户只需要经历一次延迟。 攻击者必须经历他们猜测的每个密码的延迟 - 记住彩虹表不会在这里被使用,因为密码是盐渍的。 攻击者会根据您选择的算法和迭代次数散列每个密码猜测。

    调整系统的迭代次数非常重要,因此在登录系统时使用正确的“强度”不会导致合法用户产生任何真正的烦恼。 这被称为“轮数”或“迭代次数”。 例如,迭代大约一秒就足够了。 假设攻击者可以以系统硬件速度的十倍运行哈希,这可能是安全的。 因此,这限制了攻击者每秒10次的猜测,而不是MD5的20亿次。

    关于DoS攻击

    是的,您的应用程序执行额外的登录操作可能成为攻击者向您的应用程序提交真正长的密码的目标,或者通过登录请求反复打击它以消耗服务器上的CPU和内存资源。 你有权担心。

    这些类型的攻击可通过以下方式进行缓解:

  • 记录每次登录尝试的用户名和IP地址。 在说出6次失败的尝试之后,如果该用户名或IP再次重复,则在您的应用程序的响应中引入延迟。 这也将有助于缓解一般的密码猜测攻击。
  • 例如,您可以人为延迟1秒,然后2秒然后4并且达到合理值(例如16秒)。
  • 这样做的好处是攻击者无法锁定另一个帐户,因为合法用户只需等待16秒。
  • 攻击者可以使用僵尸网络和随机用户名绕过这些检查,但是他们需要大量的IP地址,而不需要这种控制,并且更偶然的攻击者也不会意识到延迟响应是人为的。
  • 监视系统上的登录尝试次数。 一旦超过设定的阈值(例如每秒10次),引入验证码来解决登录过程。 您选择的阈值率取决于系统的用户基础和容量。
  • 实施双因素认证。 只有在验证了一次性密码后才能通过哈希验证密码。

  • MD5的问题恰恰在于它速度如此之快,您可以使用通用硬件计算约9 Giga MD5 / s。 用大约20万字强力整个英文字典,你只需要几分之一毫秒。

    这就是为什么像BCrypt这样的合适的散列算法提供成本因素的原因。 成本因素定义了需要多少时间来计算散列,并且可以在将来被减少。 登录50毫秒并不是一个障碍,但对于蛮力来说这是致命的。


    你认为减缓验证是一个问题,但它是抵御泄漏散列和蛮力攻击的唯一防御措施。 现代解决方案反复散列该值(即:数千次)以提高计算成本。

    链接地址: http://www.djcxy.com/p/21577.html

    上一篇: Why not use MD5 for password hashing?

    下一篇: MD5, password hashing and salt position