这种基于哈希的个人密码方案有多安全?

信息安全 密码 哈希 bcrypt
2021-09-08 03:50:00

我使用密码方案,我保留少量易于记忆的个人密码。我没有直接为每个服务使用密码,而是首先通过散列算法运行它们,作为一种种子,以及实际服务的名称。然后,我使用生成的哈希作为我的服务的实际密码。(还有更多内容,我添加了一些额外的固定字母以满足一些正常的密码要求,但让我们在这个问题中避开它。)

模式看起来像这样(使用 SHA512,只保留结果哈希的前 12 个字符):

"my_p4SSWord!"      
      +             =>        SHA512        =>   "d4679b768229" 
  "Facebook"

"my_p4SSWord!"      
      +             =>        SHA512        =>   "182c5c2d4a2c" 
  "LinkedIn"

该模式让我不必记住我所有的在线密码,而是记住如何在需要时轻松地重新创建它们。

有很多用于计算哈希的在线服务,我目前使用这个(它只是 javascript,因此纯粹是客户端):

https://emn178.github.io/online-tools/sha512.html

我对安全专家的问题是,我的这个个人计划到底有多安全?我将散列截断为12 个字符这对我的密码的真正可破解性有何影响?另外,我使用SHA512与使用例如bcrypt相比,它如何影响我的方案?

任何意见?

编辑:我在这里得到了一些下意识的反应,对此我很感激。在这可能被关闭之前,我会做一些简短的评论。

我特别询问了我正在使用的哈希的加密属性,以及由于我正在做的截断而对它们进行成功的蛮力攻击的可能性增加。

此外,很多人提到可用性。要记住的是,您实际上不必输入大多数密码,但可能是您的操作系统的密码。就我而言,我只记得我的操作系统的散列密码,仅此而已。其余的,每次我必须查找并重新生成哈希时,这只是一个小小的不便。它很快,而且工具是标准化的并且随处可用。

此外,对于确实需要更改特定站点的密码的情况,您可以使用一些简单的规则。您可以轻松记住并且无需写下的规则。

最后,我的意思是这主要是作为什么都不做的替代方案,毕竟,这是大多数人在他们订阅的所有在线服务中不分青红皂白地重复使用相同密码时所做的事情!

最后,最后,善良!

编辑2:答案中的方法很多,而不是哈希的加密属性,这是我在原始问题中的意图。

由于重点是方法,我将只添加一条额外的信息,即我确实在旁边保留了一个小文本文件。据我所知,该文本文件根据 Kerckhoffs 的原则,它揭示了一些东西,但没有揭示密钥。这就是为什么我最初的问题集中在哈希的加密属性及其强度上。

4个回答

SHA-512

优点:

  • 由于雪崩效应,对后缀的每一次修改都会完全改变 SHA512 和。这意味着从一个散列的 N 个首字母中,您无法说出另一个散列的 N 个首字母,从而使您的密码非常独立。
  • SHA512是一种单向压缩函数,所以不能从hash中推断出密码;您可以尝试给出相同 SHA512 总和的蛮力密码。由于您只使用部分哈希,因此有更多机会找到多个匹配的密码。

缺点:

  • 您认为您有一个强密码,因为它有 12 个字符长并且包含字母和数字,但实际上它+字符集非常有限(它是一个十六进制数字)。这仅给出ie的熵位,小于 + 的 10 个字符,接近8 个+ +的字符0-9a-f16^12log2(16^12)=48a-z0-9a-zA-Z0-9
  • 在线服务可以保存您创建的哈希值。改为使用本地工具进行散列。
  • 您可能无法在所有情况下都回忆起您的种子,这可能会导致您丢失密码。
    • 如果您想要或被要求更改密码会怎样?种子变成my_p4SSWord!Sitename2了还是别的什么?你如何跟踪计数?
    • 站点/服务名称并不总是明确的。是您的 Gmail 密码后缀Google还是Gmail您第一次使用的密码YouTube您的 Microsoft 帐户是Microsoft还是LiveOffice365
    • 这些组合使事情变得更加丑陋。
  • 如果站点有密码复杂性要求,您必须在散列后手动添加字符和/或将某些字符转换为大写。如何跟踪这些修改?
  • 有人仍然可以通过查看您创建/使用单个密码等方式找出您的程序。这将立即破坏您的所有密码。

bcrypt

虽然 bcrypt 会

  • 使用 64 个字符的 Radix-64编码 提供更多的熵;
    ASCII 32 (空格)到 95 _
    ( !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_)
  • 计算较慢
  • 使用用户定义的迭代计数,您可以利用它来使其尽可能慢

...它与您当前的程序不兼容,因为它包含了盐渍并且每次都会给您不同的哈希值:

$ htpasswd -nbBC 12 Elling my_p4SSWord\!Sitename

Elling:$2y$12$jTkZQqYzWueA5EwKU1lLT.jbLLXUX.7BemHol.Q4SXhoJyeCVhcri
Elling:$2y$12$c1lDwR3W3e7xlt6P0yCe/OzmZ.ocKct3A6Fmpl8FynfA.fDS16bAa
Elling:$2y$12$eAciSW6iGxw/RJ7foywZgeAb0OcnH9a.2IOPglGGk.wL9RkEl/Gwm
Elling:$2y$12$EU/UDJaZYvBy6Weze..6RuwIjc4lOHYL5BZa4RoD9P77qwZljUp22

...除非您专门指定静态盐(可能在PyPI bcrypt等某些实现上)。

密码管理器

所有的缺点都在密码管理器中解决,创建的密码是

  • 随机的
  • 完全不相关
  • 可以有不同的要求(不同的字符集和最小/最大长度)。

从可用性的角度来看,这很糟糕。每次登录时都需要生成一个哈希值。即使使用密码管理器来查找真正随机的字符串,工作量也会减少。

从安全的角度来看,您已经结合了散列客户端和使用密码模式的问题:

  1. 是的,在客户端使用密码哈希意味着您的明文密码受到保护,不受服务器端功能弱点的影响。但是,如果您在客户端有妥协,那就没有好处了。

  2. 它不符合Kerckhoffs 的原则如果攻击者知道这是您的进程,那么您对任何给定服务的密码只是my_p4SSWord!. 一旦我知道这一点,我就可以登录您的每个帐户。一旦已知密码,重复使用该模式就会暴露您的所有密码。

您的计划的主要目的之一是防止在一个密码被泄露时访问您的所有帐户。虽然它比简单的密码重用要好,但它仍然很容易被攻击者绕过,而且恕我直言,它没有增加足够的价值来证明增加的复杂性是合理的。

正如您提到的,您希望专注于加密属性:

sha512 是一个非常快速的函数,不适合作为密码存储的加密哈希函数。

尝试从泄露的密码 [*] 中获取密钥时,截断哈希无关紧要。它会增加冲突,但攻击者会想要正确的密钥 ( my_p4SSWord!),而不仅仅是产生散列的任何输入。

因此,如果我们假设攻击者 [**] 知道您的方法,并且他们能够在一个网站 [***] 上破解明文密码,那么他们现在可能会sha512([key_guess]compromisedwebsite)在合理的时间内破解并获得访问您在其他网站上的所有帐户。

我链接到的工具只有 JavaScript,因此只有客户端

你验证过这个吗?您是否每次都验证没有进行任何更改(由所有者进行,或者因为站点或 JS 依赖项之一已被破坏)?

就个人而言,如果您的密码方案无论如何都需要第三方依赖项,我宁愿相信专门用于保护密码安全的在线密码管理器(或者它是可行的可用性方面的离线密码管理器)。

[*] 当攻击者只能访问密码的散列版本并且需要首先破解它时,它确实具有相关性,所以我会跳过截断,因为它似乎没有必要。

[**] 现在是这样的:)

[***] 也许他们设置了一个你注册的假网站,也许你注册了一个以明文形式存储/记录/发送密码的网站,也许攻击者在你注册的网站上有一个 RCE,并按原样记录所有密码进入

评论四处乱跳,让人很难看清整体。而不是玩打地鼠,这里是一个总结。

首先,让我们记住,任何密码方案都必须改进最佳实践。最佳实践是使用具有良好密码生成器的良好密码管理器。

我们还要记住,安全性的强弱取决于其最薄弱的环节。如果我能从窗户进去,不管你的门有多棒。任何一个弱点都会使整个方案无效。必须解决所有弱点。

最后,系统的安全性不是作为一种理想来评估的,而是它是如何被实际使用的。OP 的问题提出了一个理想,但在评论和编辑过程中,我们发现它在实践中的使用方式截然不同。

密码的强度与密钥一样强,每个密码都会将密钥暴露给攻击。

该系统的主要缺陷是每个密码都将密钥暴露给攻击,所有密码的强度取决于暴力破解密钥的难度。

要暴力破解密钥,需要密码、盐、前缀和过程。

您无法控制密码的安全性,必须假设它们会泄漏。根据设计,很容易猜到。可以通过比较多个密码来发现前缀。Kerckhoffs 的原则说我们必须假设该过程是公开的。

选择不合适的哈希算法会使暴力破解变得比应有的更容易。而且,正如我们将看到的,一旦你开始制作密码,修复起来就会变得越来越困难。同样,密钥不能改变;你被一个越来越弱的键困住了。

密码管理器没有这些缺陷。

理想与实践

该方案的理想版本对其可用性提出了这些要求。

  1. 一个人只需要记住钥匙。
  2. 它是无国籍的,不需要写下来。
  3. 选择盐的过程简单易记。
  4. 不需要信任第三方。
  5. 它可以处理“我所有的在线密码”。

这些在实践中是站不住脚的。

  1. 需要记住两件事,键和前缀。
  2. 写下盐和前缀是因为...
  3. 极端情况意味着加盐很复杂,需要多个前缀。
  4. 人们可以选择使用密钥、前缀和密码来信任不安全的服务。
  5. 它无法在不影响安全性和可用性的情况下处理所有在线密码。

相比之下,一个好的密码管理器...

  1. 只需要记住主密码。
  2. 有状态,但都是加密的。
  3. 没有要记住的算法。
  4. 由专业人员审核
  5. 可以处理所有的秘密。

用户必须做出太多重要的决定。

用户必须选择散列算法、散列方法、密钥、前缀和盐程序。所有这些都会影响可用性和安全性。这些都不应该由用户进行。

例如,OP 选择了不合适的哈希算法,使得暴力破解密钥更容易。他们使用不受信任的站点进行散列处理,暴露所有内容。他们的加盐过程不足以涵盖所有需要写下一些服务名称而降低可用性的情况。所选前缀可能不足以涵盖所有密码要求。

该方案可以通过让专业人员为用户推荐选择来改进,但用户仍然可以忽略它们。

一个好的密码管理器没有这些缺陷。整个过程由专业人员创建,不断审查和改进,并由软件处理。

糟糕的选择是无法解决的。

在这个方案中,一个密码依赖于四个部分。

  • 钥匙
  • 前缀
  • 盐的过程
  • 哈希算法

更改其中任何一项,所有密码都必须更改。这使得系统非常脆弱,并对安全性和可用性产生许多影响。

不用说,一个好的密码管理器没有这些缺陷。

对于其余部分,为简洁起见,当我说“它无法更改”时,请阅读“如果不更改所有密码就无法更改”。如果更改很困难,用户很可能会对其安全性做出妥协。

哈希算法无法更改。

如果一个弱点暴露出来,能够改变你的哈希算法是很重要的。一个好的系统将能够悄悄地为未来的密码交换更好的算法。

SHA-512 是一个不合适的选择,它更容易暴力破解已经过度暴露的密钥。

密码管理器会为您处理这个问题。

密钥将越来越受到损害。

虽然强制密码轮换已经过时,但它仍然是一个安全基石,您需要能够在任何怀疑被泄露时更改您的密钥。过程越简单,您就越有可能在任何提示漏洞的情况下使用新密钥。

如果您选择了弱键,则无法选择更好的键。随着计算能力变得更强,您将需要更强大的密钥。

使用密码管理器,您可以根据需要随时更改主密码。

腌制过程将是不充分的。

为了避免写下盐,为服务获取盐的过程必须足够灵活以适应所有情况,但又要简单到可以记住并在您的脑海中完成。

用户很可能会选择一个简单的方案并发现它越来越不够用。这里有几个角落案例......

  • github.com 是“Github”还是“GitHub?
  • 如果 foo.com 是“Foo”,那么 foo.us 是什么?
  • 你如何存储 foo.github.io?
  • 你会意识到 foo.io 曾经是 foo.github.io 吗?

该程序无法预测所有情况,或者它非常复杂,无法在您的脑海中可靠地完成。不可避免的结果是必须写下一些服务名称,从而降低可用性和安全性。

加盐过程也可能随着时间的推移而漂移,因为它被巧妙地改变以适应更多的边缘情况。它可能与旧密码不兼容。

密码管理器不需要这样的过程。

一个前缀并不适合所有。

虽然密码策略最终会消失,但它们仍然存在,而且它们通常是荒谬和矛盾的。使用此方案,必须预先选择一个涵盖所有可能情况的前缀。这不太可能,也许是不可能的。

边缘案例只需要一个站点的特殊前缀,要求将它们写下来,从而降低可用性和安全性。

一个好的密码生成器可以适应大多数策略。如果没有,您可以手动更改生成的密码。

它不能安全地共享。

比方说,我想要一组共享的密码。也许是为了工作、一个项目或与家人。

有了一个好的密码管理器,我可以创建三级密钥,分发它们,最重要的是,撤销它们。可以通过云或简单地复制它来提供保险库。我可以创建共享保管库并选择共享哪些密码。

使用这种方案,必须共享密钥、前缀、哈希算法,并解释加盐过程。接收者必须愿意跳过该系统独有的所有这些障碍。这些都不能撤销。所有密码都会被公开,包括未来的密码。如果一个人泄露了密钥或前缀,那么一切都会被泄露。如果您只想共享特定密码,您需要想出并记住新的密钥和前缀,并记住使用哪个密钥和前缀生成的密码。

难以备份。

可以将密钥和前缀以及特殊的盐和哈希算法存储在安全的位置。但是,人们还必须写下对日益复杂的腌制过程的准确描述。任何阅读文档的人都知道这是多么困难。

使用好的密码管理器,可以将保管库密钥存储在安全位置并备份保管库。由于保管库已加密,因此可以在任何地方进行备份。

这种基于哈希的个人密码方案有多安全?

它比重复使用几个容易记住的密码更安全。与一个好的密码管理器和随机生成的密码相比,它更难使用,功能更少,安全性也更低。

如果您对商业软件过敏,请使用开源软件。如果您不信任云存储,请将保管库存储在本地。如果您希望它可以在任何地方使用,请将保管库和软件存储在钥匙圈上的拇指驱动器上。