1

目前我只是在玩 PHP,但我遇到了一个我想扩展的想法,并且需要知道它在您看来有多安全,以及我如何改进它以使其可以被实际使用。

这就是我在数据库中存储密码的方式:

纯文本密码-> 哈希密码(我使用漩涡,但任何方法实际上都可以)-> 随机/加扰哈希密码(使用 str_shuffle() 函数)。

我像这样将用户密码存储在数据库中,以确保如果数据库受到破坏,攻击者将无法反转数据库内损坏的密码哈希。(因为从某种意义上说,您如何反转曾经是散列的随机文本?-尽管我确信您可以通过比较共享相同字符的散列列表来创建可能性列表。)

我检查他们在登录表单上输入的用户密码是否正确(与数据库中损坏的哈希相比)的方法是计算两个字符串/密码中的单个字母+数字(af & 0-9),看看是否他们匹配,如果匹配,我假设他们正确登录。

再一次,我想知道您认为这有多安全,以及如何改进它以使其在实际使用中可以接受。(如果可能的话。)&我也想尽我所能避免“可逆”哈希。(即创建我自己的方法来确保密码匹配的想法,我想让它更像是一个最佳猜测假设,以完全帮助确保攻击者不可能反转数据库中的密码。

是的,我知道这很愚蠢,因为它很可能会导致更多的安全漏洞,而不是帮助修复它们。但这只是我在玩弄的东西,也许希望使它实用。


其他信息:

1) 密码用唯一的盐存储(所以不是 1 个帐户共享相同的盐)

2)密码盐总是在变化(每次用户帐户成功登录时,它都会更改数据库中的用户盐。我这样做是为了更改数据库中的哈希值,从而减少密码冲突的频率(希望) 以及防止不需要的用户多次使用相同的错误密码登录(如果他们设法遇到一个,实现此目的的唯一方法是通过暴力破解或“猜测”,任何登录系统都容易受到攻击)。

当我说密码冲突时,我的意思是“你好”和“蓝色”这个词有最小的机会共享相同的确切字符数(正如我解释的那样,我计算了单个字符 + 数字,并比较它们,假设它是正确的密码.)

3) 我也可能会保留散列密码的前 3 个字符/数字不受 str_shuffle 的影响,以帮助确保密码正确。(通过创建 2 个检查,1)检查两个字符串是否共享相同的 FIRST 3 CHARS/Numbers & 2)然后比较每个字符串中的字符数。(希望再次减少密码冲突)。

4) 显然将添加其他安全措施(即最大登录尝试次数、验证码等。以帮助防止自动暴力破解,使黑客更难找到可能的密码或真实密码。

我已经成功地完成了这个 PoC,它就像一个魅力,虽然我还没有针对字典攻击/蛮力攻击测试 PoC,以查看密码冲突的可能性。& 他们的频率。

如果我说了很多“无用”的信息,请忽略它。我只是尽力合理地解释这一点。

4

4 回答 4

2

这对我来说似乎非常无效和不安全。

最值得注意的是:碰撞。您已经在其他信息中提到了这一点。

只需检查散列和加扰中的字符数,碰撞概率就会飙升。您可以使一个密码对其 hash 的所有排列也有效。考虑到漩涡哈希中 128 个字符的长度,这是一个非常大的数字。

因此,基本上,通过允许这一点,您允许潜在的暴力破解者通过输入一个密码来一次检查数千个密码。

他们不会获得对系统的永久访问权限,因为您说您在每次登录后更改哈希,但是他们获得一次访问权限的可能性大大增加。

关于变盐……你是怎么做到的?除非您在散列之后而不是之前应用盐,否则我想不出办法,这不是盐在散列中的工作方式。

如果你想让它更安全,那么只需使用多个哈希迭代。存储散列密码和散列迭代次数。每次用户登录时再次哈希哈希,存储它,并增加迭代次数。这将充分改变存储的哈希值,而不会引入太多的加密弱点。

于 2014-01-29T09:12:29.830 回答
0

加密强散列函数的输出对于所有意图和目的来说都是伪随机的。试图通过扰乱它来增加熵什么都不做。它不会使散列不那么“可逆”,因为“反转”散列的唯一方法是选择一个输入,对其进行散列,将其与散列进行比较;这与登录用户时必须做的事情相同,攻击者必须做的事情相同,更改比较算法不会更改此基本操作。(正如其他人所指出的,您削弱的比较算法实际上有助于攻击者。)

处理这个问题的公认方法已经足够了:

  1. 通过使用(伪)随机噪声对其进行加盐,确保您的输入是唯一的,这会迫使攻击者进行实际的蛮力散列。
  2. 选择一个较慢的哈希(最好是 bcrypt 或 scrypt,具有足够高的成本因素,使您可以执行一次,但攻击者无法执行数十亿次),这使得攻击者在计算上不可行进行暴力破解在他的一生中强制进行哈希。

如果两个步骤都正确完成,那么“反转”散列已经不可行了。不需要额外的智力游戏。

于 2014-01-29T09:31:58.063 回答
0

不要再摆弄你的想法了。这是不安全的。

只有大约两种密码安全方法可以提供足够的防篡改能力:

  1. 使用执行 HMAC-SHA1 之类的硬件安全模块。模块是外部硬件,外界不知道模块内部的内部秘密(只能通过物理访问模块获得),没有该模块,生成的哈希将永远不会被重建。作为具有“快速”散列算法的专用硬件,这使其成为大量密码检查的可行解决方案。有关详细信息,请参阅http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
  2. 使用非常慢的散列算法。诸如“scrypt”或“bcrypt”之类的东西将执行得非常慢,从而阻碍了密码列表对已知哈希列表的快速暴力扫描。PHP 目前只支持“bcrypt”。

您可能想知道为什么要使用封装秘密的外部硬件。很简单:任何可以从进行散列的机器访问的东西都可能被窃取。窃取秘密就像对所有密钥使用相同的盐(或根本不使用):您最终“仅”拥有一个非常快速的散列算法,并且所有其他组件都已知,并且可以立即开始暴力破解密码。

因此,如果没有专用硬件,唯一的其他选择就是慢速密码哈希算法。

PHP 有一个解决方案:password_compat是一个库,它为 PHP 5.5 之前的版本重新实现了 PHP 密码哈希 API。如果您已经在使用 5.5,您只需使用这些功能

于 2014-01-29T17:58:12.880 回答
0

您的改组方案会使密码的安全性降低。在洗牌后比较字母和数字的实例数量会增加两个人具有相同密码值的机会(如您所说的冲突)。

重新加盐是你可以使用的东西。用户每次登录成功后,可以重新加盐密码并再次保存。如果您修改 PHP 密码程序以使用高分辨率时间值,这可能会更好,从而增加唯一性。本质上,您正在不断地旋转密码的盐。您必须保存清除密码,将其哈希与保存的密码进行比较,重新加盐并哈希清除密码并再次保存。

于 2014-01-29T09:20:06.637 回答