0

好吧,我一直看到(和关注)人们说使用散列机制将密码存储在数据库中。我真的很担心它安全吗?

让我们举个例子。

假设我是黑客,我得到了你的数据库名称、ID 和密码。现在我可以完全访问您的数据库。

人们所说的密码应该被散列,因为如果有人入侵,黑客就可以看到它们。

所以如果我运行查询,select id, password FROM userDetails我将得到如下数据

选项1:没有哈希

++++++++++++++++++++++++++++
+   id    +    password    +
++++++++++++++++++++++++++++
+  id01    +  password01   +
+  id02    +  password02   +
++++++++++++++++++++++++++++

选项 2:使用哈希

++++++++++++++++++++++++++++
+   id    +    password    +
++++++++++++++++++++++++++++
+  id01    +  hasValue01   +
+  id02    +  hasValue02   +
++++++++++++++++++++++++++++

好吧,我还是要说,散列是不安全的。为什么我会在下面用Java代码告诉你。

PreparedStatement pst = conn.prepareStatement("SELECT id, password FROM userDetails");
ResultSet rs = pst.executeQuery();
String randomPassword = "";
StringBuffer sb;
boolean myPassCheck = true;
while (rs.next()) {
    myPassCheck = true;
    while (myPassCheck) {
        // this will generate random password
        randomPassword = generateRandomPassword();
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(randomPassword.getBytes());
        sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
            sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
        }
        if (sb.toString().equals(rs.getString(2))) {
            // this is password
            myPassCheck = false;
            System.out.print("id=" + rs.getString(1) + ", password=" + sb.toString());
        }
    }
}

这样,我可以打印用户名和密码。(我知道我必须生成随机密码,直到我没有找到密码)。然而这样一来,散列密码机制也失效了。

另外我相信这个世界上有解密器可以将散列数据转换为实际数据。

因此,我在想

散列机制是否安全?


编辑 1

我说的不仅仅是 MD5。我选择 MD5 仅用于示例目的。我说的是任何安全密码机制

4

4 回答 4

4

不,仅使用哈希,尤其是仅将 MD5 应用于密码时,是不安全的,因为:

  • 如果您只是转换密码(通常几乎是一个常用词),则使用常用密码数据库很容易对其进行测试。所以总是使用盐,最好是用户记录的其他常量部分的组合。有时您甚至可以通过在 Google 中输入哈希来找到哈希的来源...
  • MD5 容易发生冲突,因此即使使用哈希,也更喜欢 SHA 256 或更好
  • MD5 计算速度很快,在蛮力攻击中测试速度也很快

使用散列机制但是:

  • 采用更好的哈希函数,例如SHA-256 或 SHA-512
  • 散列一个构造的字符串,例如用户名++密码(你可以使用一个常量盐,只要它不被其他程序使用,对于大多数用途来说已经足够了)

当您注册某人(或某人更改他的密码)时的过程是

1) 将字符串 s 构建为 s=username+salt+password (或类似函数)

2) 将哈希构建为 SHA256(s)

3) 将用户名、salt(如果不是常量)和哈希值存储在数据库中

在对用户进行身份验证时,您以相同的方式构建哈希(使用用户提供的用户名和密码以及您在数据库中拥有的盐)并将用户名和哈希与您在数据库中的内容进行比较。你不要反转散列函数,因为那是不可行的。


现在关于您的代码:您的方法似乎是生成所有可能的密码,直到一个具有与您尝试猜测的密码相同的 MD5 为止。这不适用于合理的密码,因为没有足够的时间来测试 15 个字符的所有组合。

于 2012-11-10T15:07:16.180 回答
3

密码永远不会以明文形式存储。至少他们不应该这样,除非你正在使用世界上最天真的程序员构建世界上最不安全的系统。

相反,密码存储为哈希函数的输出。即使攻击者获得了您密码的散列版本的访问权限,也不可能仅从散列值重构密码。

但是可以使用彩虹表攻击密码的散列值:每个可能的字符组合的巨大的、预先计算的散列值。攻击 PC 肯定可以即时计算所有这些哈希值,但是利用预先计算的大量哈希值表可以使攻击的速度提高几个数量级——假设攻击机有足够的 RAM 来存储整个表(或至少大部分)在内存中。像这样的表称为rainbow table

这是一个经典的时间记忆权衡,正是你期望黑帽攻击者采取的那种作弊捷径。

用于以下字符集的数据库:ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~[]{}|\:;"'<>,.?/ 最大密码长度为 14 的数据库大小为 64GB。

如果您对密码哈希进行了加盐处理,攻击者将无法rainbow table对您使用一般攻击,“密码”和“美味咸密码”的哈希结果将不匹配。除非你的黑客不知何故知道你所有的散列都是“美味的咸”。

即使这样,他或她也必须专门为您生成自定义彩虹表。

请阅读 Thomas Ptacek关于此主题的出色且内容丰富的文章。它更详细地介绍了密码散列的具体细节。

最后是您问题的答案:

不,它不安全,但您可以尽最大努力使其尽可能安全。

于 2012-11-10T15:08:53.067 回答
1

不。散列密码不安全,但比不这样做更安全。如您所见,如果您有足够的时间和硬件资源,此类散列密码可能很容易被解密。这就是为什么我们经常使用盐来使我们的密码更安全。盐是以某种方式与真实密码合并的东西,您存储此类字符串的哈希码。攻击者可能能够破解加密,但他会收到混合了盐的密码。对于使用所谓的“彩虹表”来解密密码的人来说,这是一个很好的保护。不幸的是,它仍然是易碎的。在这里您可以找到更多信息: http: //arstechnica.com/security/2012/08/passwords-under-assault/

于 2012-11-10T15:07:29.237 回答
1

不,它们不是 100% 安全的,特别是如果攻击者有哈希数据库。更好的方法是使用加盐密码,因为这会使哈希数据库变得毫无用处。

使密码更安全的另一种方法是对其进行多次哈希处理,这也会降低哈希数据库的有效性。

正如其他帖子所提到的,选择一种更安全、更昂贵的算法,如 sha-512。

于 2012-11-10T15:09:03.553 回答