在内部保持密码长度统一并保持盐的秘密?

时间:2012-04-28 20:55:49

标签: security cryptography passwords salt sha

存储密码时,有人说Salt不需要保密,唯一的目的是保持所有Hash的唯一性。还有人说限制密码长度不是一个好习惯,但请考虑这个例子:

在散列之前,我们确保纯文本版本在内部始终为128个字符,方法是将用户输入修改为最大值100,然后添加其他字符作为我们的盐。

因此,如果用户输入20个字符,我们会添加108个随机字符作为salt。如果用户输入100,我们追加28,依此类推。关键是,纯文本版本的长度应为128个字符。在代码中它可能如下所示:

$salt   = generate_salt($pass); // length varies as explained above
$hash   = hash('sha512', $pass.$salt);

这样我们在哈希之前的“纯文本”总是128个字符。

我们在服务器A上存储$ hash并在服务器B上存储$ salt。

现在让我们假设攻击者可以访问哈希数据库(服务器A)并设法反转哈希值。对他来说看起来不错,但他看到的纯文本版本(或反向哈希)仍然看起来像哈希,因为它是128个字符。由于他不知道盐,他永远不会知道原始密码。

作为一个额外的挑战,由于SHA512产生128个字符的事实,他也永远不会确定他是否已经到达纯文本版本(因为已经提到过),纯文本版本看起来像哈希。很明显,他可能认为这是一个迭代版本,如果是这样,他可能会继续迭代,可能是无限期。

这种方法有什么问题,因为在哈希反转的情况下,保持盐的秘密可以提供额外的安全性,并且保持纯文本长度统一可以说会增加混淆层吗?

注意:这当然假设您的应用有多个登录检测/预防失败。

3 个答案:

答案 0 :(得分:3)

首先,除非你真的知道自己在做什么,否则不要发明自己的加密系统。

使用现有的(如PBKDF2bcrypt或scrypt),它比简单的盐渍哈希更有优势,因为它们使用更多的CPU时间(全部三个)和/或内存(后两个) ),这使并行化成本高昂。

散列中的salt仅保护彩虹表,而不是防止暴力攻击!

如果攻击者设法撤消哈希,他将获得$pass.$salt的知识(因此,密码)。

salt的目的是避免廉价创建彩虹表,也就是说,攻击者必须为每个不同的盐执行此操作,而不是仅仅计算每个可能密码的哈希并将它们与数据库进行比较。 / p>

保持盐的秘密具有使攻击更加昂贵的理论优势,因为攻击者还必须为每个可能的密码尝试所有可能的盐。

但实际上,一旦他有权访问服务器A,他就可能能够访问服务器B.

如果看起来像哈希可能并不重要。一旦服务器受到攻击,攻击者就可能会发现使用了哪些混淆技术。

旁注:SHA-512产生512位输出,即64个ASCII字符。

答案 1 :(得分:1)

此方法的第一个问题是您正在实施自己的加密代码。这几乎总是一个坏主意;加密很难,并且很容易以微妙的方式搞砸,而其他人已经投入了大量的时间和精力来实现构建在它们之上的加密原语和服务,这样你就不必这么做了。但是我们假设你真的需要这样做: - )。

第二件事是你正在截断用户的输入 - 抛弃宝贵的熵 - 根本没有任何好处。你准备生成多达128个字符的盐;为什么不总是这样做并将它们(连同密码)一起提供给你的哈希?你通过截断获得了什么?我看到的唯一答案是,据说原始密码“看起来像哈希,因为它是128个字符”,但这根本不是真的;你的盐渍密码仍然以实际密码数据开头,这通常看起来与哈希不同。

第三件事 - 这可能只是我无法正确阅读你的思想 - 是不清楚你的这些盐来自哪里。你把它描述为“随机”,并说攻击者不会知道它们;但是你的身份验证系统如何获得它们呢?看起来它们来自密码,但在这种情况下,salting-plus-hashing只是一个稍微复杂的哈希函数,你还没有真正获得任何东西。

您显然拒绝(或可能未遇到)的一般原则是:始终设计加密系统,假设攻击者知道他们可能知道的一切,包括所有源代码。这是一个很好的原则,你不应该拒绝它。依靠一小部分“额外的混淆”对你不利;在最坏的情况下,它会使错误更容易发生(通过使系统复杂化)并引起虚假安全感。

答案 2 :(得分:0)

Salt不需要保密,唯一的目的是保持所有Hash的唯一性

它还使得对哈希表进行暴力破解变得“慢”,因为每个哈希+盐组合需要每行尝试一次,而不是仅为整个表尝试一个哈希('select * from passwords where hash ='xxx'')

保持盐的秘密提供了额外的安全性,并且保持纯文本长度统一可以说会增加混淆层?

你的'反向哈希'看起来像哈希的事实并没有增加真正的额外安全性(它实际上只是默默无闻的安全性)。您的网络服务器需要连接到服务器A 服务器B(用于验证用户/密码组合),以便当该服务器遭到入侵时,所有希望都将丢失。

您感兴趣的文章是this blog post by Jeff Atwood。 (编辑:发布错误的编码错误链接)