2010-02-01 78 views
11

我正在为我们的代码库添加哈希摘要生成功能。我希望使用一个字符串作为散列盐,以便可以将预先知道的密钥/密码短语预置为需要散列的任何内容。我误解了这个概念吗?我误解了哈希盐是什么?

+0

你在写什么语言? – 2010-02-01 15:38:21

+0

我正在用Java编写这个 – 2010-02-01 16:11:04

回答

18

salt是一个随机元素,它被添加到密码函数的输入中,目的是在每次调用时以不同的方式影响处理和输出。盐,而不是“钥匙”,并不意味着保密。一个世纪前,用于加密或认证的加密方法是“秘密的”。然后,随着计算机的出现,人们意识到保持一种完全秘密的方法是困难的,因为这意味着保持软件本身的机密性。一些定期写入磁盘的东西,或者作为一些专用硬件而化身,难以保密。因此,研究人员将“方法”分为两个不同的概念:(它是公开的并成为软件和硬件)和(该算法的参数,仅在处理期间存在于易失性RAM中)。密钥集中了秘密并且是纯数据。当密钥存储在人的大脑中时,通常称其为“密码”,因为人类比单词更擅长记忆单词。

然后密钥本身在稍后分裂。事实证明,为了正确的加密安全性,我们需要两件事:一个机密参数和一个可变参数。基本上,重复使用相同的密钥用于不同的用途往往会造成麻烦;它经常泄露信息。在某些情况下(特别是流密码,但也用于哈希密码),它泄漏太多并导致成功的攻击。所以经常需要可变性,每次密码方法运行时都会发生变化。现在最好的部分是大多数时候,变化和秘密不需要合并。也就是说,我们可以将机密变量分开。因此,密钥分为:

  • 密钥,通常被称为“密钥”;
  • 一个变量元素,通常随机选择,并根据算法类型将其称为“salt”或“IV”(如“初始值”)。

只有钥匙需要保密。可变元素需要所有相关方都知道,但它可以是公开的。这是一件幸事,因为分享密钥是困难的;用来分发这种秘密的系统会发现,容纳每次运行算法时都会改变的可变部分是很昂贵的。

在存储散列密码的情况下,上述说明中变为:

  • “重用键”是指两个用户碰巧选择了相同的密码。如果密码只是散列,那么两个用户将获得相同的散列值,并显示。这是泄漏。
  • 同样,没有散列,攻击者可以使用预先计算的表进行快速查找;他也可以同时攻击数千个密码。这仍然使用相同的泄漏,只是以一种方式来证明为什么这种泄漏是不好的。
  • Salting意味着将一些变量数据添加到散列函数输入。那个可变数据就是盐。盐的要点是两个不同的用户应该尽可能使用不同的盐。但密码验证者需要能够重新计算密码中的相同散列,因此他们必须有权访问salt。

由于盐必须能够被验证者访问,但不一定是保密的,所以通常将salt值与散列值一起存储。例如,在Linux系统上,我可以使用这个命令:

openssl passwd -1 -salt "zap" "blah" 

此计算一个散列密码,用散列函数MD5,适合于在/etc/password/etc/shadow文件的使用,对于密码"blah"和盐(在这里,我明确选择盐,但在实际条件下应该随机选择)。输出是:

$1$zap$t3KZajBWMA7dVxwut6y921 

其中美元符号作为分隔符。最初的"1"标识哈希方法(MD5)。盐在那里,用明文表示。最后一部分是散列函数输出。

关于如何将salt和密码作为哈希函数的输入发送(至少在glibc源代码中,可能在别处),有一个规范(某处)。

编辑:在“登录和密码”的用户认证系统,“登录”可以作为一个差强人意盐(两个不同的用户会有不同的登录),但是这并没有抓住给定的情况用户更改密码(新密码是否与旧密码相同将会泄漏)。

+1

“盐,而不是”钥匙“,并不意味着保密。” - 使用像MD5或SHA-1这样的众所周知的单向散列函数,你必须保持盐的机密性,否则强制颠倒你的散列函数就容易多了。 – Paolo 2010-02-01 16:33:00

+0

如果盐是保密的,它不是盐,而是盐的一部分。现在恰好在哈希密码设置中,盐可以完成它的工作(它可以防止相同的密码和并行攻击泄漏),但这不够好,因为人们在选择和记住好的密码时很可悲。因此,习惯上试图保持整个输出为“受保护”('/ etc/shadow'不公开可读);额外的安全来自隐藏散列输出,而不是隐藏盐。无论哪种方式,验证者必须仍然可以访问salt和散列输出。 – 2010-02-02 13:31:30

3

你正在理解这个概念。只要确保预先加入的盐每次都是可重复的。

2

如果我正确地理解了你的话,这听起来就像你说得对。该过程的伪代码看起来像这样:

string saltedValue = plainTextValue + saltString; 
// or string saltedalue = saltString + plainTextValue; 

Hash(saltedValue); 

盐只是为试图获取您的信息的人增加了另一层级的复杂性。

0

如果盐对于每个加密短语都不同,它会更好,因为每个盐都需要自己的彩虹表。

0

值得一提的是,即使盐的密码用法不同,您的盐也不应该从密码本身计算出来!这类事情的实际结果是完全无效的安全性。