【问题标题】:Password security密码安全
【发布时间】:2013-05-19 11:43:03
【问题描述】:

目前我正在使用一种特定的方案来保护密码,我认为我有一些需要改进的地方。使用 Java 实现,所以我更喜欢使用 SHA-2 512 作为加密形式。

目前我有一个客户端-服务器模型,所以这些事情可能会发生:

  • 客户想要登录,他通过网络发送了一次普通 SHA-2 512 加密的密码。
  • 服务器将密码存储在数据库中,例如 SHA-2_512(SHA-2_512(password) + salt),内部 SHA-2_512(password) 是它通过网络接收的“加密”密码。
  • 密码检查是在服务器端完成的,没有任何东西可以从服务器泄漏,唯一可能的漏洞是如果有人可以读取我认为的 RAM。

我有这些问题:

  • 攻击者在想要破解密码时通常会发起冲突攻击。然而,碰撞攻击如何足够?如果密码需要用于其他应用程序,如 Outlook.com、Facebook 或其他应用程序(可能使用另一种盐,因为它们与我的应用程序无关),那么碰撞攻击如何足够呢?你不需要真正的密码吗?

  • SHA-2 512 是否已经使用迭代?即使是这样,我是否应该更改我的加密方法以自动使用多次迭代以及首选多少次迭代?我还阅读了有关使用随机迭代次数(在一个范围内)的信息,如何确定性地存储随机因子?

  • 我应该在服务器代码中存储每次迭代的系统机密吗?见http://blog.mozilla.org/webappsec/2011/05/10/sha-512-w-per-user-salts-is-not-enough/。我可以存储一个数组,该数组将为每次迭代保存一个静态机密,第 n 个机密用于第 n 次迭代。没有人知道这些秘密,它们被计算一次(我猜是加密一些随机字符串),然后基本上存储在服务器的 RAM 中。

  • 目前我将输入的密码从客户端发送到服务器只是 SHA-2_512(密码),这个过程是否应该改进,如果是,如何改进?我不能使用盐,因为客户端没有可用的盐。

问候。

【问题讨论】:

    标签: security passwords sha


    【解决方案1】:

    TLDR:您需要使用加密通道(例如 TLS)发送密码。考虑使用bcrypt 进行密码散列。

    SHA-2 512 不是加密算法,它是一种消息摘要算法。加密算法需要密钥和消息来加密。它产生密文。重要的是加密算法有解密算法。

    ciphertext = E(key, plaintext);
    plaintext = D(key, ciphertext);
    

    消息摘要采用一段明文并生成消息摘要。没有相应的反向机制来获取消息摘要并检索原始消息。也没有秘钥。

    digest = hash(plaintext);
    

    如果攻击者能够使用哈希访问数据库,则攻击者可以通过暴力破解检索原始密码,并尝试使用哈希算法进行大量猜测。

    digest1 = hash(guess1);
    digest2 = hash(guess2);    //repeat with lots of guesses
    

    首先,通过网络发送散列是安全的。它需要通过 SSL 等安全通信机制发送。如果攻击者能够截获通信中的哈希值,他们或许能够计算出原始密码。

    hash collision 与暴力破解密码不同。当两个不同的消息产生相同的消息摘要时,会导致哈希冲突。

    digest1 = hash(plaintext1);
    digest2 = hash(plaintext2);
    if ( ( plaintext1 != plaintext2 ) && ( digest1 == digest2 ) )  
        // hash collision
    

    SHA-512 没有旨在防止暴力破解的迭代。 SHA 算法集旨在提高效率。在散列密码时添加迭代的原因是增加暴力破解密码所需的时间。与拥有数百万个密码的攻击者相比,执行合法登录尝试和执行 100 次迭代的成本很小,每个密码都需要 100 次迭代。添加更多迭代有助于减少提高处理器速度的影响(这将有助于攻击者更快地尝试更多迭代)。

    您应该将迭代次数设为针对每个用户存储的可配置限制。因此,您存储每个用户的密码哈希、盐和迭代计数。这意味着将来您可以增加迭代次数以考虑增加的硬件功率。

    以明文形式发送 SHA-2 512 并不安全。您应该在加密通道中发送它,例如 SSL。

    话虽如此,SHA-2 并非设计为密码散列算法。它是为消息验证而设计的,并且是高效的。考虑使用专门构建的密码哈希算法。一个例子是bcrypt。它被设计成计算困难,并且内置了盐和迭代。

    【讨论】:

    • 我研究了一下,我认为这是一个需要补充的重要说明:BCrypt 应该在客户端进行授权(并且在服务器端进行一次注册/密码更改)。所以服务器上的压力真的很低。如果错了,请纠正我。有没有办法确定一个好的工作因素?
    • @skiwi 我认为您不应该在客户端执行 bcrypt 计算。你能分享你的参考吗?使用 bcrypt 对服务器的压力仍然很低,但尝试通过尝试 1000 次猜测来暴力破解它的攻击者的压力非常大。
    • 可以安全地使用 BCrypt,而无需向您要散列的密码添加额外的盐(我自己)吗?我知道它已经加入了盐,这足以胜任这项工作吗? Java也从JPasswordField中给出了char[],但BCrypt强制我使用String,这意味着密码在内存中浮动,这是一个问题吗?
    • 是的,它足以胜任这项工作。您无需在其中添加另一个。
    猜你喜欢
    • 1970-01-01
    • 2018-01-02
    • 2013-08-09
    • 2012-07-05
    • 2015-06-19
    • 2016-07-28
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多