好吧,我一直看到(及以下)人们说使用散列机制将密码存储在数据库中。我真的担心它安全吗?
让我们举个例子。
我们说我是黑客,我得到了您的数据库名称,ID和密码。现在我可以完全访问您的数据库。
人们说密码应该被删除,因为如果有人黑客攻击,黑客就可以看到它们。
所以如果我将查询作为select id, password FROM userDetails
运行,我将获得如下数据
++++++++++++++++++++++++++++
+ id + password +
++++++++++++++++++++++++++++
+ id01 + password01 +
+ id02 + password02 +
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
+ 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());
}
}
}
这样,我可以打印用户名和密码。 (我知道在找不到密码之前我必须生成随机密码)。但是这样,哈希密码机制也失败了。
我相信在这个世界中存在解密器,它会将哈希数据转换为实际数据。
因此,我在想
我不是只讨论MD5。我只选择MD5作为示例。我说的是安全密码的任何机制
答案 0 :(得分:4)
不,只是使用哈希,特别是在将MD5应用于密码时,并不安全,因为:
使用散列机制但是:
当您注册某人(或某人更改其密码)时的过程是
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。