代码之家  ›  专栏  ›  技术社区  ›  Vineet Reynolds

在创建帐户时,如何将密码散列安全地存储在内存中?

  •  6
  • Vineet Reynolds  · 技术社区  · 17 年前

    更具体地说,如何确保持有密码的字符串在足够短的时间间隔内被垃圾收集?

    6 回复  |  直到 17 年前
        1
  •  6
  •   craigb    17 年前

    如果您有可能(在web应用程序中可能很困难),那么最好将密码存储在字符数组中,而不是存储在字符串中。如果您完成了密码的存储,您可以使用 Array.fill() 并通过丢弃该引用使其可供垃圾收集器使用:

    Arrays.fill(password, ' ');
    password = null;
    

    我刚刚注意到,取消密码可能有点偏执,但如果它让你放心,你可以这样做:)

        2
  •  5
  •   TofuBeer    17 年前

    您不使用字符串。使用字符[],然后在完成时覆盖字符[]。

    对于垃圾收集,绝对没有任何保证(除了在收集对象之前运行终结器)。GC可能永远不会运行,如果它运行,它可能永远不会GC包含密码的字符串。

        3
  •  3
  •   Mork0075    17 年前

    如果在客户端创建哈希,就不需要考虑这个问题。普通密码永远不会提交到服务器。

        4
  •  2
  •   S.Lott    17 年前

    两个词:局部范围。用于密码处理的声明变量需要具有尽可能小的绝对范围。

    通常,你会从一个请求中挑选一些东西。您需要一个非常非常小的事务来接受请求、散列密码、保持密码并重定向。然后,重定向到的页面可以获取内容并执行应用程序中的所有“其他”处理。

        5
  •  1
  •   Peter Lawrey    17 年前

    在Java中,无法保证从内存中删除明文密码。

    然而,黑客不需要访问程序内存就可以获得明文密码。有更简单的方法(比如嗅探数据包),所以任何人都不太可能依赖这种方法。

    最好的方法是让客户端按照@Mork0075的建议加密密码。然而,虽然这意味着你无法轻松获得密码,但程序仍然可以获得加密版本的密码,从而假装是用户。解决这个问题的一种方法是使用SSL加密整个连接。

    所有这些都是相当学术性的,因为黑客最简单的方法就是监视数据库中的数据包并获取数据库的密码。我想直接访问你的数据库更重要的是。。。或许它不是

        6
  •  0
  •   Andy    17 年前

    使用密码质询:

    1. 服务器选择一个 挑战值 并将其发送到客户端
    2. 服务器使用 还有挑战,例如。 MD5(CONCAT(challenge, password)) 并将其分配给会话。
    3. 纯文本密码现在已超出范围,可以进行垃圾收集。
    4. 客户端还执行相同的转换,并将结果发送到服务器。
    5. 如果服务器和客户机选择相同的最终值,则对客户机进行身份验证。

    重放攻击 非常不可预测(随机)且不经常重复使用(长)。

    纯文本密码仅在处理初始连接请求期间在作用域内,而不是在身份验证期间。单向转换结果在作用域(不是垃圾收集)中的时间长短无关紧要,因为它几乎没有重放值。