我正在阅读本教程中的simple PHP login system。
最后,它建议您encrypt your password using md5()。
虽然我知道这是一个初学者的教程,你不应该把银行对账单放在这个登录系统后面,这让我想到加密。
所以我继续前进(本网站为新手提供的最有用的问题之一):What should a developer know before building a public web site?
它说(在安全下)你应该:
加密哈希和盐密码 而不是存储纯文本。
它没有更多关于它,没有参考。
所以我继续自己尝试一下:
$pass = "Trufa";
$enc = md5($pass);
echo $enc; #will echo 06cb51ce0a9893ec1d2dce07ba5ba710
这就是让我思考的问题,虽然我知道md5()可能不是最强的加密方式,但任何总能产生相同结果的东西都可以进行逆向工程。
那么使用md5()或任何其他方法加密某些东西的感觉是什么?
如果黑客获取使用md5(),he would just use this page!加密的密码。
现在实际问题:
我知道我没有在这里发现一个巨大的网络漏洞! :)我只是想了解密码加密背后的逻辑。
我确定我理解错了,如果你可以帮助我直接设置我和其他人(我希望),我将不胜感激。
您如何应用密码加密以使其真正有用?
正如我所说,我可能/我的想法是错误的,但是,这种方法是否会在真实环境中增加安全性?
$reenc = array(
"h38an",
"n28nu",
"fw08d"
);
$pass = "Trufa";
$enc = chunk_split(md5($pass),5,$reenc[mt_rand(0,count($reenc)-1)]);
echo $enc;
如您所见,我随机添加了任意字符串($reenc = array()
)到我的md5()密码“使其独一无二”。这当然只是一个愚蠢的例子。
我可能错了,但除非你“亲自加密”,否则它总是很容易逆转。
以上是我的“密码保护”和加密密码的想法,如果黑客得到它,他将无法解密它,除非他能够访问原始.php
我知道这可能没有意义,但我无法弄清楚为什么这是个坏主意!
我希望自己已经说清楚了,但这是一个很长的问题,所以,请询问是否需要澄清!
提前致谢!!
答案 0 :(得分:20)
您应该有encryption
md5
或sha512
。您还应该有两种不同的盐,static salt
(由您编写),然后还有unique salt
用于该特定密码。
一些示例代码(例如registration.php):
$unique_salt = hash('md5', microtime());
$password = hash('md5', $_POST['password'].'raNdoMStAticSaltHere'.$unique_salt);
现在您有一个static salt
,它对所有密码都有效,存储在.php文件中。然后,在注册执行时,您将为该特定密码生成unique hash
。
这一切最终都是:两个拼写完全相同的密码将有两个不同的hashes
。 unique hash
与当前ID一起存储在database
中。如果有人抓住database
,他们将为每个特定密码设置每个unique salt
。但他们没有的是你的static salt
,这使得每个“黑客”都变得更加困难。
这是您在login.php上检查密码有效性的方法,例如:
$user = //random username;
$querysalt = mysql_query("SELECT salt FROM password WHERE username='$user'");
while($salt = mysql_fetch_array($querysalt)) {
$password = hash('md5',
$_POST['userpassword'].'raNdoMStAticSaltHere'.$salt[salt]);
}
这是我过去使用过的。它非常强大和安全。我自己更喜欢sha512
加密。实际上只是将它放在哈希函数中而不是我的例子中的md5
。
如果您想要更加安全,可以将unique salt
存储在一个完全不同的数据库中。
答案 1 :(得分:18)
首先,“散列”(使用加密单向函数)不是“加密”。在加密中,您可以反转过程(解密)。在散列中,(理论上)没有可行的方法来逆转过程。
哈希是一些函数f,使得v不能容易地从f(v)确定。
使用散列进行身份验证的关键是您(或看到散列值的人)没有任何可行的方法(理论上)再次知道密码。但是,您仍然可以验证用户是否知道他的密码。 (基本上,用户证明他知道v使得f(v)是存储的哈希值。)
简单散列的弱点(除了弱散列函数)是人们可以编译密码表及其相应的散列并使用它们(有效地)得到散列函数的逆。 Salting可以防止这种情况,因为哈希的输入值的一部分是受控制的,因此必须为该特定的盐编译表。
实际上,您存储salt和哈希值,并通过散列salt和密码的组合进行身份验证,并将其与哈希值进行比较。
答案 2 :(得分:6)
MD5是一种单向散列函数,可以或多或少安全地保护您的原始密码。
因此,假设您的密码为“Trufa”,其散列版本为06cb51ce0a9893ec1d2dce07ba5ba710
。
例如,当您登录新网页时,他们会询问您的用户名和密码。当您将“Trufa”写为密码时,值06cb51ce0a9893ec1d2dce07ba5ba710
将存储在数据库中,因为它已经过哈希处理。
下次登录并编写“Trufa”时,散列值将与数据库中的值进行比较。如果它们是相同的,那么您将通过身份验证!当然,假设您输入了正确的用户名。
如果您的密码未以数据库中的哈希形式存储,则某些恶意用户可能会以某种方式在该数据库上运行查询并查看所有真实密码。这将是妥协。
此外,由于MD5是128位加密函数,因此有2 ^ 128-1 = 340282366920938463463374607431768211455可能的组合。
由于存在比这更多的可能字符串,因此2个字符串可能会生成相同的哈希值。这称为碰撞。并且它确保散列密码不能进行唯一的逆向工程。
答案 3 :(得分:5)
salting的唯一漏洞是你需要知道salt是什么,以便重建哈希来测试密码。这是通过以<algorithm>$<salt>$<hash>
形式将条目存储在authdb中来实现的。这样,可以访问它的任何代码都可以使用authdb条目。
答案 4 :(得分:4)
你错过了重要的一步 - 盐。这是一个独特的(每个用户,理想情况下)一些额外数据,您可以在对其进行哈希处理之前将其添加到密码中。
答案 5 :(得分:4)
你的想法(salting)是众所周知的,并且实际上在PHP语言中很好地实现了。如果使用the crypt()
function,它允许您指定要散列的字符串,加密的方法(在某些情况下)和salt。例如,
$x = crypt('insecure_password', $salt);
返回准备存储的散列和加密密码。密码破解的方式与我们检查它们是否正确的方式相同:我们检查用户输入的哈希值与数据库中密码的哈希值。如果它们匹配,则对它们进行身份验证(AFAIK这是最常用的方法,如果不是唯一的话)。使用字典单词的不安全密码(如password
)可以通过将其哈希值与常用密码的哈希值进行比较来破解。 安全密码不能以这种方式破解,但仍然可以破解。在密码中添加一个盐使得破解更加困难:因为黑客很可能不知道盐是什么,他的字典攻击将无法工作。
答案 6 :(得分:2)
对于一个体面的哈希,攻击者不会反转哈希,他们将使用彩虹表,如果每个人都使用相同的哈希函数,这本质上是一个强大的方法。
彩虹表的想法是,由于散列很快,我可以散列您可以用作密码的每个可能值,存储结果,并且具有哪个散列连接到哪个密码的映射。如果每个人只需要使用他们的密码并用MD5对它们进行哈希处理,那么我的哈希表适用于任何一组密码哈希值,我可以帮忙!
这就是salting的用武之地。如果我输入用户输入的密码并为每个用户添加一些不同的数据,那么预定的哈希值列表就没用了,因为哈希是密码和一些随机的数据。盐的数据可以存储在密码旁边,即使我得到它们也无法帮助我恢复密码,因为我仍然必须为每个用户分别强制执行哈希 - 我无法形成单个彩虹表一次攻击所有哈希值。
当然,理想情况下,攻击者首先不会获得散列密码列表,但有些员工会有访问权限,因此无法完全保护密码数据库。
答案 7 :(得分:1)
除了提供盐(或种子)之外,md5是一种复杂的散列算法,它使用数学规则来产生一个特别不可逆的结果,因为吞吐量会产生数学变化和数据。
答案 8 :(得分:1)
md5
(或更好的put:一般的哈希算法)用于在数据库中安全地存储密码。关于哈希的最重要的事情是:哈希本身不是加密。(它们最多是单向加密)。如果您对某些内容进行加密,则可以使用您使用的密钥获取数据。哈希从任意输入(如字符串)生成固定长度值,可用于查看是否使用了相同的输入。
哈希用于在存储设备中存储敏感的,重复输入的数据。这样做,没有人可以从哈希数据中重新创建原始输入,但是您可以对传入的密码进行哈希并将其与数据库中的值进行比较,并查看两者是否相同,如果是,则密码是正确的。
您已经指出,有可能通过使用值/哈希对的数据库或产生冲突(导致哈希值的不同值)来破坏算法。你可以通过使用salt来掩盖这一点,从而修改算法。但是如果盐是已知的,它可以用来再次打破算法。
答案 9 :(得分:1)
我喜欢这个问题。但我认为你真的回答了自己。
您引用的网站使用已知的,未加盐的md5的字典查找 - 它不会“破解”任何内容。
您的示例几乎是好的,除了您的应用程序需要能够每次使用相同的盐重新生成md5。
您的示例似乎使用了一种随机盐,如果您尝试将用户密码哈希值与输入值进行比较,则会失败2次中的2次。
人们会告诉你也要使用SHA1或SHA256来获得“更强大”的哈希 - 但人们也会争辩说他们都被打破了。“
答案 10 :(得分:1)
该文档具有误导性 - 它教导了一个“易受攻击”的概念,并将其呈现为某种“安全”,因为它(保存的密码)看起来像胡言乱语。只是互联网垃圾,不会死。以下链接应该清楚(你已经找到了一点点,但似乎。好的工作。)
Enough With The Rainbow Tables: What You Need To Know About Secure Password Schemes谈论MD5(以及为什么不应该使用它)和盐(例如如何阻止彩虹攻击)以及提供有用的见解(例如“使用别人的密码系统。”不要建立你自己的”)。这是一个相当不错的概述。
答案 11 :(得分:0)
这是关于md5碰撞方面的问题,与您的问题略有关系:
Is there any difference between md5 and sha1 in this situation?
重要的一部分是前三行,即:必须你的 密码,如果你想获得更强的保护,不是在之后。
答案 12 :(得分:0)
简单地回答问题的标题,md5现在唯一真正的用途是散列大字符串(如文件)来产生校验和。这些通常用于查看两个字符串是否相同(就文件而言,校验和经常用于安全目的,以确保分发的文件未被篡改,例如)。
解决每个内联问题:
密码加密如何工作? 您将如何应用密码加密以使其真正有用?
安全密码哈希通过以纯文本格式获取密码,然后对其应用昂贵的哈希函数,并使用加密安全随机盐进行加密。有关详细信息,请参阅Secure hash and salt for PHP passwords问题。
这个想法怎么样?
密码散列不需要像这样复杂,也不应该是复杂的。避免考虑自己的算法,并坚持使用已经过试验和测试过的哈希算法。正如上面提到的问题所提到的,密码哈希的md5()
已经过时多年已经过时,所以应该避免使用。
从三种不同盐的阵列中生成“随机”盐的方法并不是您正在寻找的随机性。您需要适合加密安全的独特随机性(即使用加密安全伪随机数生成器(CSPRNG))。如果您使用的是PHP 7及更高版本,则random_bytes函数可用于生成加密安全盐(对于PHP 5用户,可以使用random_compat库。)