我想问一些有关PBKDF2函数以及通常基于密码的派生函数的问题。

实际上,我们将派生函数与salt结合使用可以抵抗字典攻击,对吗?一个示例是UNIX加密方案。

我的第一个问题:例如,如果要对卡中的数据进行加密,而我通常使用PBKDF2函数使用密码来派生新密钥。盐是未加密存储的,对吗?

但是,如果攻击者能够访问卡并找到盐,那么我们唯一的安全措施就是再次输入密码,不是吗?那么,为什么我们要在盐中储存盐?我知道这会使字典攻击变得更加困难,但是如果有人可以访问该卡,那么我们将是第一个唯一的预防措施,就是密码的长度,对吗?

此外,我们情况相同:我们有密码,我们想生成一个新密钥,我们使用PBKDF2或任何其他函数(我知道它具有HMAC作为生成器)。到现在为止,我还没有找到解释该功能的结果是否存储了实际密钥的地方?

还给定了密码,我们怎么知道密码是否正确,以便得出实际的密钥?

评论

stackoverflow.com/q/1219899/639891的可能重复项

我的问题是:1)盐必须以无色或加密形式存储? 2)从PBKDF2派生的密钥存储在某个地方? 3)我们怎么知道我们提供的密码是执行PBKDF2功能的正确密码?

#1 楼

首先,认识到PBKDF2是PKCS#5是RFC 2898,即http://www.ietf.org/rfc/rfc2898.txt

本质上是一种算法,它可以将密码安全地散列多次您想要的,带有所需的任何哈希值。 OWASP建议根据https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet

,在2012年至少对密码进行64,000次哈希,并每两年翻一番。 ),每个用户的可变迭代次数也有帮助。不必总是运行PBKDF2 64,000次,而是生成一个随机盐和一个介于1和20,000之间的随机数I。为该特定用户名运行PBKDF2 64,000 + I次。这使得破解起来稍微困难一些,并且可能阻止破解代码中的某些优化有用。


实际上,我们将派生函数与salt结合使用以提供对字典的抵抗力攻击,对吗?


基本上-我们在对明文密码进行哈希处理之前先对其加盐。


我的第一个问题:...通常,盐未存储在加密了吧?


在更简单的实现中,较长的(8字节或更多)加密随机盐未经加密存储,并且每次更改密码都会重新生成。 OWASP(上面的链接)建议采取其他预防措施,包括将其他盐存储在配置文件中的某个位置(即未存储在数据库中),在源代码中进行硬编码的另一部分,以及将每个用户的盐存储在与密码不同的位置,也许是平面文件还是数据库(反之亦然)。请注意,理想情况下,这还要求将密码和盐也备份到不同的位置-目标是使一次盗窃更难于窃取盐和密码。


同样,我们有相同的情况:我们有密码,并且我们想要生成一个新的密钥...直到现在,我还没有找到任何地方解释该函数的结果(实际的密钥(是否存储了?)。


这取决于。如果仅在此会话期间使用PBKDF2生成用于实时加密的密钥,则否,它应该仅保留在内存中,并在最后丢弃。正在使用PBKDF2生成哈希(在N次迭代之后),以便稍后对用户进行身份验证,那么您必须保存该哈希。


我知道这样做会使字典攻击更加困难,但是如果有人要访问我存储的卡,我们首先要做的是,唯一的预防措施是密码长度正确。


不,唯一的预防措施是密码的强度。” P @ ssw0rdP @ ssw0rdP @ ssw0rd”是错误的密码,即使它是24个字符长且“复杂”的。如果要“注册”用户或让他们选择密码,则需要拒绝任何密码rd在最常见的破解词典中。此外,在测试拒绝时,您需要应用与基于规则的字典破解者(如Elcomsoft或Hashcat)使用的规则相同的规则-转换为1337语音,在语音之后加1至1000,在正面和背面添加随机字符,将其加倍,等等。在前端,这很容易,因为您可以简单地对1337语音进行反向翻译并将其小写,因此P @ ssw0rd和Passw0rd都以“ password”结尾,应该过滤掉。 Melinda2006始终是错误的密码,就像12345一样。


另外,给定密码,我们如何知道该密码是否是正确的密码才能导出实际密钥? >

您事先不知道;你只要试试看。如果可行,那是对的。如果不起作用,那就错了。现在,再次取决于“作品”。
对于实时解密,您将尝试解密消息。然后,您将保存的HMAC与消息(在加密之前)与值进行比较;如果HMAC不匹配,则是伪造的,部分消息已被更改,您有错误或密码错误。
要进行身份验证,请收集应使用的盐值,然后重新哈希密码相同的次数。如果获得相同的哈希结果,则输入必须相同,因此是正确的。

评论


$ \ begingroup $
我认为“随机迭代次数”的东西并没有真正增加任何安全性,并且使代码更加复杂。
$ \ endgroup $
–PaŭloEbermann
2012年8月10日在8:24

$ \ begingroup $
@ paulo-ebermann为什么您认为“随机迭代次数”没有增加任何安全性?您能详细说明一下吗?
$ \ endgroup $
–富兰克林
2012年11月5日19:53

$ \ begingroup $
@Franklin这只会使各个密码输入之间的破解时间有所不同,因此,攻击者首先会攻击数量较小的数字(如果该数字明显较低的话)。可以只使用最大数目的所有密码,而不是这种“稍微困难一点”,这对所有攻击者来说都更加困难。
$ \ endgroup $
–PaŭloEbermann
2012年11月5日在20:29

$ \ begingroup $
@ paulo-ebermann有趣。但是,如果(假设地说)密码是5位数的PIN,而要进行的额外“随机迭代次数”(除了64,000次迭代)又是中间3位数的绝对值呢?
$ \ endgroup $
–富兰克林
2012年11月5日在20:50

$ \ begingroup $
@Franklin:由于攻击者只是试图猜测密码,因此每次尝试都知道此附加号码。是的,它需要一些额外的代码(对于攻击者和合法验证者而言),但是不需要大量的额外计算。
$ \ endgroup $
–PaŭloEbermann
2012年11月12日20:54



#2 楼

基于密码的密钥派生功能会根据给定的密码生成适用于密码的密钥。它仅取决于原始密码被保密。

盐的目的仅仅是为了防止使用彩虹桌。必须为每种盐制作一个彩虹表,并且如果(按照惯例)每个用户都有自己的盐,则必须为该特定用户构造一个彩虹表。通常,不假定它是秘密的。

PBKDF函数中使用了盐和更多次迭代,以阻止创建彩虹表的任何尝试。


从PBKDF2派生的密钥存储在某个地方


我认为您可能已经混淆了用于身份验证和PBKDF的密码的加密哈希(可以使用底层的密码哈希)以“拉伸密码”以用于加密。

不应将生成的密钥存储在任何地方(除非对其进行适当的加密)。生成的密钥用于加密。当要解密数据时,应提示用户输入密码,然后再次生成密钥。然后,该生成的密钥用于解密数据。


我们如何知道我们提供的密码是执行PBKDF2功能的正确密码?


加密数据时,还应包括消息身份验证(MAC)。这通常意味着加密message || MAC。您将使用(可能为假)密钥解密数据。然后检查MAC和消息是否对应。如果不是,则密钥为假,否则密文已被篡改。

或者,您可以对密码进行哈希处理。尽管可以使用PBKDF,但应该清楚的是必须使用不同的盐(即使您不使用相同的算法)也是如此。当用户输入密码时,您对它进行哈希处理,并与存储的哈希进行检查,如果它们匹配,则继续生成加密密钥并解密数据。

评论


$ \ begingroup $
将PBKDF2用于身份验证和密码扩展(假设使用不同的盐)是否不合适?
$ \ endgroup $
–Eyal
2012年8月16日上午10:12

$ \ begingroup $
@Eyal-您可以再问一个问题吗?基于此备忘录(第3节),我相信您可以仅使用PBKDF2生成一个(假设)256位密钥,并将其拆分为2个128位密钥,一个用于MAC和另一个加密。但是我想知道别人的想法。还是您是说使用它生成密钥以及用于存储密码的哈希?无论如何,我认为这值得一个新问题。
$ \ endgroup $
–斯蒂芬·哈里斯(Stephen Harris)
2012年8月16日10:32



$ \ begingroup $
我正在这样做。我有一个随机盐,它在注册时生成以哈希进行身份验证,而另一个盐是在登录时生成一个加密密钥。
$ \ endgroup $
–citizenslave
19年7月2日在13:23

#3 楼

我发现Stephen Harris和PBKDF2 Answers提供的回复非常有用。我只想在身份验证的加密和密文的验证上加上两美分,而无需实际解密。

在PBKDF2中,建议在加密之前使用Answers的响应计算HMAC:


对于实时解密,您将尝试对消息进行解密。然后,您将保存的HMAC与消息(在加密之前)与值进行比较;如果HMAC不匹配,则是伪造的,部分消息已被更改,您有错误或密码错误。


但是,在我的搜索中,我发现加密-然后-身份验证比身份验证-然后-加密效果更好:


摘要...我们证明,旨在与安全加密的任何组合一起使用的任何安全通道协议(针对选定的纯文本)攻击)和安全的MAC必须使用crypto-then-authenticate方法。HugoKrawczyk-加密和身份验证的顺序
,用于保护通信(或者:SSL的安全性如何?)


最近,我编写了一个包装器类,用于使用AesCryptoServiceProvider .NET类对文件进行加密和解密。在我的实现中,使用密码随机数生成器生成了三个盐saltAuthsaltHMACsaltEncrypt,然后:




PBKDF2(password, saltAuth, iterations1)给出hashAuth


PBKDF2(password, saltHMAC, iterations2)给出keyHMAC


如果加密数据按以下顺序存储:


PBKDF2(password, saltEncrypt, iterations2)
keyEncrypt

saltAuth,'|'意味着串联
hashAuth
HMAC(saltHMAC | saltEncrypt | ciphertext, keyHMAC)
saltHMAC

然后,在请求解密数据时:




可以生成saltEncrypt并进行比较以验证解密的权限。
通过验证权限,可以生成ciphertext以计算HMAC,然后将其与存储的值进行比较以检测篡改。
如果未检测到篡改,则可以生成hashAuth并可以执行解密。


#4 楼


1)盐必须以清晰或加密的方式存储吗?


要么,盐只是保护的一部分,如果黑客不知道它是什么,它会有所帮助,但即使这样做,也无法使用Rainbow表。如果您对其进行加密,则还必须对其进行解密,这意味着仅当黑客破坏了您的[user]表但不破坏您的代码库时才添加防御。使用密码哈希(因此您最终会得到类似salt + salted hash的格式)-这足以强制每个密码的重新生成并停止使用任何彩虹表。


2)密钥从PBKDF2派生而来的存储在某个地方


不,PBKDF2无法解密,这就是重点。您是说结果哈希吗?将其存储在您喜欢的位置,但是如果很容易受到破坏,则可以使用更多的迭代。


3)我们如何知道我们提供的密码是执行PBKDF2的正确密码功能吗?


通过重新哈希它。

PBKDF2实现的示例如下所示:

用户设置密码:


生成随机定长盐(通常128位)
盐加到密码中
盐和密码通过哈希算法(通常是SHA变体)运行至少1000次,但经常更多。
未加密的盐和哈希加在一起并编码为用于存储的字符串。

您针对用户检查密码:


获取保存的哈希值。
读取前128位(或其他内容) )作为存储的盐。
将盐添加到新的潜在密码中,并通过相同的哈希算法运行。
如果密码匹配,则检查它是否与保存的哈希匹配。

请注意,盐未加密,而是与散列结果一起存储。您在任何地方都没有可以解密哈希的密钥-黑客可以进入的唯一方法是强行使用密码,而PBKDF2的设计速度很慢,很难做到这一点。

评论


$ \ begingroup $
您有讨论任何问题的电子邮件帐户吗?或类似的东西,以便进行更好的对话?
$ \ endgroup $
– thrylos_7
2012年8月9日在12:03

$ \ begingroup $
给定密码,PBKDF2将从盐和密码的哈希值中派生密钥,对吗?该密钥将对一些我想要保护的数据进行加密。您在第二个问题中回答的是,密钥必须存储在某个位置。我的问题是:如果该密钥存储在没有任何保护的地方,那么如果攻击者可以访问我存储的位置,那么他拥有实际的密钥,对吗?
$ \ endgroup $
– thrylos_7
2012年8月9日12:16

$ \ begingroup $
@ thrylos_7-PBKDF2并不是真的。如果要保护和加密/解密数据,则需要一个公共-私有密钥对。 PBKDF2专为使用密码而设计-它创建单向哈希值,很难进行暴力附加,但是可以在用户输入密码时进行检查。由于PBKDF2无法反转其算法,因此无需存储密码。解密密钥。如果要解密数据,则需要将解密密钥保存在某处,但这可以是公共密钥。
$ \ endgroup $
–基思
2012年8月9日13:09

$ \ begingroup $
@ thrylos_7-而且,由于PBKDF2设计用于密码,所以它非常慢(这不需要花费很多密码检查,但会使蛮力攻击更加困难)。如果要创建大量哈希(例如在安全通信中),则需要一种更快的算法,例如SHA256。
$ \ endgroup $
–基思
2012年8月9日在13:17

$ \ begingroup $
实际上,虽然PBKDF2可以用于简单的密码哈希处理(并且实际上非常有用),但其实际目的是从密码派生加密密钥。这就是首字母缩写词“ PBKDF2”的意思:“基于密码的密钥派生功能,版本2”。
$ \ endgroup $
–伊尔马里·卡洛宁(Ilmari Karonen)
2012年8月14日在21:34

#5 楼

引用NIST 800-132:


盐的目的是允许为固定的迭代次数生成与每个密码相对应的大量密钥。


换句话说,如果两个人碰巧在使用相同迭代次数的实现中使用相同密码,那么他们很可能会获得不同的密钥-这是一件非常好的事情。 >