【问题标题】:PHP & MySQL security: one-way encryption Vs two-way encryptionPHP & MySQL 安全性:单向加密与双向加密
【发布时间】:2011-04-23 05:11:12
【问题描述】:
【问题讨论】:
标签:
php
mysql
security
aes
【解决方案1】:
单向加密意味着您只能加密。 (例如,您加密密码并存储结果。每当用户进行身份验证时,您将用户输入的内容加密并进行比较。在这种情况下不需要解密函数。)
双向加密方式,有加解密功能。在 PHP 中,这是通过 mcrypt_encrypt() 和 mcrypt_decrypt() 函数完成的。
更新! mcrypt 在 PHP 7.1 中被弃用并在 7.2 中被删除。请参阅 OpenSSL 或 Sodium 来了解加密和解密功能。
【讨论】:
-
更新! mcrypt 在 PHP 7.1 中被弃用并在 7.2 中被移除。请参阅 OpenSSL 或 Sodium 以获取加密和解密功能。
【解决方案2】:
双向加密本质上不太安全,因为真实数据存储在某个地方。也就是说,您有一个密码“你好”。然后你散列它,你得到 5d41402abc4b2a76b9719d911017c592。这对普通人来说毫无意义,如果不知道正确的加密算法,他们将不知道如何解密。他们也不能使用这个,因为只使用了原始密码。您通过散列密码并将其与散列值(也存储)进行比较来检查密码。 5d41402abc4b2a76b9719d911017c592 散列为 69a329523ce1ec88bf63061863d9cb14,因此它们不匹配。即使用户知道哈希密码,他也无法从中获取任何信息。
所以你可以存储加密的数据,但是如果你在取出它的时候解密它,那么任何人都可以使用它。
与向用户提供密码相比,向用户发送链接的安全性是一个不同的问题。如果您通过电子邮件发送密码,它将以纯文本形式打印出来供所有人查看(和使用)。给他们一个链接以允许他们输入新密码意味着没有人会看到它,这更安全一些,但如果有人进行欺诈,无论如何都可以访问该链接,这将导致问题。
关于 AES,我一眼就无法找到太多关于它的信息,但看起来你加密什么并不重要。因此,如果您使用 AES_DECRYPT(AES_ENCRYPT('x', 'b'), 'b');它将返回“x”。您必须跟踪密钥。
【解决方案3】:
哈希和加密这两个概念有根本的区别:
加密可以逆转,散列不能(至少是这样)。
如果恶意用户访问数据库中的密码并且知道您用来加密它们的密钥,他们将能够恢复所述密码。如果他们被哈希,他们将无法做到这一点。
这就是为什么密码应该总是被散列(和加盐),从不加密。
例如,密钥的长度重要吗?或者我可以简单地使用 '123123@123123' 作为我的密钥吗?
AFAIK MySQL 的AES_ENCRYPT 可以采用任意长度的键;但显然较短的密钥会使攻击者更容易暴力破解它(即:尝试所有可能的组合)
【解决方案4】:
对于密码,单向哈希几乎总是可行的方法。单向哈希意味着除了用户之外的任何人都不太可能知道他们的密码。
如果您选择单向路线,则需要设置密码重置方法。如果这样做正确,对于大多数用途来说应该是相当安全的。为了获得更好的安全性,您可以添加安全问题(例如,“您最喜欢的颜色是什么?”),用户在收到电子邮件中的密码重置链接之前必须回答这些问题。
至于 AES_ENCRYPT/DECRYPT 的密钥——MySQL 将接受函数的 key 参数的可变长度,但无论如何它都会使用 128 位密钥,因此传递至少 128 位对您有利值得。
【解决方案5】:
如果您在使用对称加密的服务器上存储密码,则必须对存储的密码进行解码,以根据用户提交的密码对其进行测试。这意味着密钥也必须存储在服务器上。这意味着任何破坏您的 web 应用程序的人都可以检索和解密每个用户的密码。 (并使用它们来破坏用户使用相同密码的其他帐户。)
散列密码意味着您不能将密码泄露给攻击者,因为您甚至不知道密码是什么。您仍然可以通过使用相同的算法和盐对提交的密码进行散列来检查提交的密码是否与原始密码相同,因此您仍然可以判断提交的密码是对还是错,而无需知道密码是什么。
使用散列密码确实意味着您无法在“恢复密码”选项中告诉用户他们的密码是什么。但无论如何你都不想这样做,尤其是在电子邮件等不安全的机制上。一次性、有时间限制的重置密码链接具有相同的目的,但潜在的损害较小。