【发布时间】:2011-01-11 18:39:27
【问题描述】:
我正在努力将哈希摘要生成功能添加到我们的代码库中。我想将字符串用作哈希盐,以便可以将预先知道的密钥/密码短语添加到需要哈希的任何内容之前。我误解了这个概念吗?
【问题讨论】:
-
你用什么语言写的?
-
我正在用 Java 写这篇文章
我正在努力将哈希摘要生成功能添加到我们的代码库中。我想将字符串用作哈希盐,以便可以将预先知道的密钥/密码短语添加到需要哈希的任何内容之前。我误解了这个概念吗?
【问题讨论】:
您完全理解了这个概念。只需确保每次添加的盐都是可重复的。
【讨论】:
如果我对您的理解正确,那么听起来您是对的。该过程的伪代码如下所示:
string saltedValue = plainTextValue + saltString;
// or string saltedalue = saltString + plainTextValue;
Hash(saltedValue);
Salt 只是为试图获取您的信息的人们增加了另一层复杂性。
【讨论】:
如果每个加密短语的盐不同,那就更好了,因为每个盐都需要自己的彩虹表。
【讨论】:
盐是添加到加密函数输入的随机元素,目的是在每次调用时以不同的方式影响处理和输出。与“密钥”相反,盐并不意味着保密。
一个世纪前,用于加密或身份验证的加密方法是“秘密”的。然后,随着计算机的出现,人们意识到将方法完全保密是很困难的,因为这意味着要对软件本身保密。定期写入磁盘或体现为某些专用硬件的内容难以保密。因此,研究人员将“方法”分为两个不同的概念:算法(公开并成为软件和硬件)和密钥(算法的参数,目前仅在处理期间在易失性 RAM 中)。密钥集中秘密,是纯数据。当密钥存储在人类的大脑中时,它通常被称为“密码”,因为人类更擅长记住单词而不是位。
然后密钥本身随后被拆分。事实证明,为了获得适当的密码安全性,我们需要两件事:机密参数和可变参数。基本上,为不同的用途重复使用相同的密钥往往会造成麻烦。它经常泄露信息。在某些情况下(尤其是流密码,也用于散列密码),它会泄漏太多并导致成功的攻击。因此,通常需要可变性,每次加密方法运行时都会发生变化。现在好的部分是大多数时候,可变性和秘密不需要合并。也就是说,我们可以将机密与变量分开。所以key被拆分成:
只有密钥需要保密。变量元素需要所有相关方都知道,但它可以是公开的。这是一种祝福,因为共享密钥很困难;用于分发此类秘密的系统会发现容纳每次算法运行时都会发生变化的可变部分的成本很高。
在存储散列密码的上下文中,上面的解释变成如下:
由于验证者必须可以访问盐但不需要保密,因此习惯上将盐值与哈希值一起存储。例如,在 Linux 系统上,我可能会使用这个命令:
openssl passwd -1 -salt "zap" "blah"
这会计算一个散列密码,使用散列函数 MD5,适合在 /etc/password 或 /etc/shadow 文件中使用,用于密码 "blah" 和盐 "zap"(这里,我明确选择盐,但在实际条件下应随机选择)。那么输出是:
$1$zap$t3KZajBWMA7dVxwut6y921
其中美元符号用作分隔符。初始 "1" 标识散列方法 (MD5)。盐就在那里,以明文表示。最后一部分是哈希函数输出。
有一个规范(某处)关于如何将盐和密码作为输入发送到散列函数(至少在 glibc 源代码中,可能在其他地方)。
编辑:在“登录名和密码”用户身份验证系统中,“登录名”可以充当可通过的盐(两个不同的用户将有不同的登录名),但这不会捕获给定用户更改密码的情况(新密码是否与旧密码相同会泄漏)。
【讨论】:
/etc/shadow 不公开可读);额外的安全性来自隐藏哈希输出,而不是隐藏盐。无论哪种方式,验证者都必须仍然可以访问盐和哈希输出。
值得一提的是,即使每个密码使用的盐值应该不同,但绝对不能根据密码本身计算盐值!这种事情的实际结果是完全使您的安全失效。
【讨论】: