哈希机制真的安全吗?

时间:2012-11-10 15:04:55

标签: java passwords md5 password-hash

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

让我们举个例子。

我们说我是黑客,我得到了您的数据库名称,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 个答案:

答案 0 :(得分:4)

不,只是使用哈希,特别是在将MD5应用于密码时,并不安全,因为:

  • 如果您只是转换密码(通常几乎是常用词),可以使用常用密码数据库轻松测试。所以总是使用salt,最好是用户记录的其他常量部分的组合。有时您甚至可以通过在Google中键入哈希来找到哈希的起源......
  • MD5 is prone to collisions,所以即使使用哈希,也更喜欢SHA 256或更好
  • MD5计算速度快,在暴力攻击中测试速度非常快

使用散列机制但是:

  • 采用更好的哈希函数,例如SHA-256 or SHA-512
  • 哈希一个构造的字符串,例如用户名+ salt +密码(你可以使用一个恒定的盐,只要它没有被其他程序使用,它足以满足大多数用途)。

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

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

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

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

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


现在关于你的代码:你的方法似乎是生成所有可能的密码,直到一个人拥有与你想要猜测的密码相同的MD5。 这对于合理的密码不起作用,因为没有足够的时间来测试15个字符的所有组合。

答案 1 :(得分:3)

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

相反,密码存储为散列函数的输出。即使攻击者获得了密码的哈希版本的访问权限,也无法仅通过哈希值重新构建密码。

但是可以使用彩虹表来攻击密码的散列值:每个可能的字符组合都有大量的预先计算的哈希值。攻击PC当然可以动态计算所有这些哈希值,但利用大量预先计算的哈希值表可以使攻击速度提高几个数量级 - 假设攻击计算机有足够的RAM来存储整个表(或至少大部分)在记忆中。像这样的表叫做rainbow table

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

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

如果您使用密码哈希值,则攻击者无法使用针对您的常规rainbow table攻击,“密码”和“deliciously-salty-password”的哈希结果将不匹配。除非你的黑客以某种方式知道你所有的哈希都是“精致咸”的。

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

请阅读Thomas Ptacek关于此主题的excellent and informative article。关于密码散列的细节,它更加贬低。

最后回答你的问题:

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

使密码更安全的另一种方法是多次散列密码,这也会降低散列数据库的效率。

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

相关问题