我想问一些关于PBKDF2函数的问题,以及关于基于密码的派生函数的一般问题。
实际上,我们使用派生函数和salt一起来抵抗字典攻击,对吗?一个例子是UNIX加密方案。
我的第一个问题是:
例如,如果要加密卡中的数据,而我使用密码使用PBKDF2函数派生新密钥,则通常不加密存储salt,对吗?
但是如果攻击者访问了这张卡并找到了盐,那么我们唯一的安全措施就是密码,不是吗?那么,我们为什么要把盐储存在透明的地方呢?我知道这会增加字典攻击的难度,但是如果有人访问了这张卡,那么我们就在第一位,唯一的预防措施是密码的长度,对吗?
此外,我们也有同样的场景:
我们有密码,我们想要生成一个新的密钥,我们使用PBKDF2或任何其他函数(我知道它有HMAC作为生成器)。直到现在,我还没有找到任何地方解释函数的结果,实际的密钥是否被存储?
此外,给定密码,我们如何知道密码是否正确,以便得到实际的密钥?
发布于 2012-08-09 23:58:14
首先,认识到PBKDF2是PKCS #5是RFC 2898,即http://www.ietf.org/rfc/rfc2898.txt。
它本质上是一种算法,可以根据需要安全地散列密码多少次,并使用任何您想要的散列。OWASP建议在2012年对密码进行至少64,000次哈希,并且每两年将这一数字翻一番,每https://www.owasp.org/index.php/Password_存储_作弊_板材一次
请注意,存储(也是在明文中)每个用户的可变迭代次数也有帮助。而不是总是运行PBKDF2 64,000次,而是生成一个随机盐,以及一个介于1到20,000之间的随机数I。对特定的用户名运行PBKDF2 64,000 +I次。这使得破解代码变得更加困难,并且可能会阻止破解代码中的某些优化操作。
实际上,我们使用派生函数和salt一起来抵抗字典攻击,对吗?
本质上-我们在散列之前先对明文密码进行盐化。
我的第一个问题:..。通常盐是未经加密储存的,对吧?
在更简单的实现中,长(8字节或更多)的加密随机盐未经加密存储,并随每次密码更改而重新生成。OWASP (上面的链接)建议采取更多的预防措施,包括将额外的盐存储在某个配置文件中(即不存储在数据库中),在源代码中硬编码的另一部分,以及将每个用户的salt存储在与密码不同的位置,可能是平面文件与数据库(反之亦然)。请注意,理想情况下,还需要将密码和盐类备份到不同的位置--目的是通过一次盗用使盗取盐类和密码变得更加困难。
另外,我们有相同的场景:我们有密码,我们想要生成一个新的密钥.直到现在,我还没有找到任何地方解释函数的结果(实际的键(它是存储的还是不存储)?
这要看情况了。如果您仅在此会话期间使用PBKDF2生成用于实时加密的密钥,则不会,它只应留在内存中,并在结束时被丢弃。如果以后使用PBKDF2生成哈希(经过N次迭代后)来验证用户,则必须保存该哈希。
我知道这会使字典攻击变得更加困难,但是如果有人访问了我存储的卡片,那么我们就处于第一步,唯一的预防措施是密码的长度正确。
不,唯一的预防措施是密码的强度。"P@ssw0rdP@ssw0rdP@ssw0rd“是一个错误的密码,即使它是24个字符长和”复杂“。如果您要“注册”用户,或者让他们选择密码,那么您需要在最常见的破解字典中拒绝任何密码。此外,当您测试拒绝时,您需要应用与基于规则的字典破解器(如Elcomsoft或Hashcat )使用的规则相同的规则--翻译到1337 back,在它之后添加1到1000,在前面和后面添加随机字符,翻倍,等等。这在前端容易得多,因为您可以简单地反向翻译1337 back和小写它,所以P@ssw0rd和Passw0rd都以“密码”结尾,这应该是可怕的。Melinda2006总是一个错误的密码,就像12345一样。
此外,给定密码,我们如何知道密码是否是正确的密码,以获得实际的密钥?
你事先不知道,你只要试一试。如果成功的话,那是对的。如果不起作用,那就错了。现在,由“工作”,再一次,这取决于。对于实时解密,您将尝试解密消息;然后将保存的HMAC与消息(加密之前)与值进行比较;如果HMAC不匹配,则是伪造的,消息的一部分被更改,您有错误,或者密码是错误的。对于身份验证,您收集应该使用的盐值,然后按相同的次数重新散列密码。如果获得相同的散列结果,则输入肯定是相同的,因此是正确的。
发布于 2012-08-09 14:30:27
基于密码的密钥派生函数从给定的密码生成适合密码器的密钥。它只依赖于被保密的原始密码。
盐的目的只是为了防止彩虹桌的使用。必须为每个盐制作彩虹表,如果(通常的做法)每个用户都有自己的盐,则必须为该特定用户构建彩虹表。一般来说,它并不是秘密的。
盐类与PBKDF函数中更多的迭代一起使用,以阻止创建彩虹表的任何尝试。
从PBKDF2派生的密钥存储在某个地方。
我认为您可能混淆了存储用于身份验证的密码的密码散列和用于加密的PBKDF (可以使用底层加密哈希)来“扩展密码”。
生成的密钥不应存储在任何地方(除非其本身经过适当加密)。生成的密钥用于加密。当数据被解密时,应该提示用户输入密码,并再次生成密钥。然后使用这个生成的密钥来解密数据。
为了执行PBKDF2函数,我们如何知道我们提供的密码是正确的?
在加密数据时,还应该包括消息身份验证(MAC)。这通常意味着加密message || MAC。您将使用(可能为false)密钥解密数据。然后检查MAC和消息是否对应。如果他们不这样做,要么密钥是假的,要么密码文本被篡改了。
或者,您可以散列密码。尽管可以使用PBKDF,但显然必须使用不同的salt (即使不使用相同的算法)存储.This哈希。当用户输入密码时,您将其散列,并使用存储的哈希进行检查,如果它们匹配,则继续生成加密密钥,并对数据进行解密。
发布于 2012-09-12 23:14:43
我发现斯蒂芬·哈里斯和PBKDF2 2答案提供的响应非常有用。我只是想把我的两分钱加到认证加密和密文验证上,而不是真正地解密它。
在PBKDF2 2答案的反应计算中,有人建议在加密之前使用HMAC:
对于实时解密,您将尝试解密消息;然后将保存的HMAC与消息(加密之前)与值进行比较;如果HMAC不匹配,则是伪造的,消息的一部分被更改,您有错误,或者密码是错误的。
然而,在我的搜索中,我发现加密-然后认证比身份验证-然后加密更好:
摘要..。我们表明,任何设计用于安全加密(针对所选明文攻击)和安全MAC的组合的安全通道协议都必须使用加密-然后认证方法。 雨果·克劳奇克-保护通信的加密和身份验证顺序(或者:SSL有多安全?)
最近,我编写了一个包装类,用于使用AesCryptoServiceProvider .NET类加密和解密文件。在我的实现中,使用密码随机数生成器生成三个盐类saltAuth、saltHMAC和saltEncrypt,然后:
PBKDF2(password, saltAuth, iterations1)给出hashAuthPBKDF2(password, saltHMAC, iterations2)给出keyHMACPBKDF2(password, saltEncrypt, iterations2)给出keyEncrypt如果加密数据按以下顺序存储:
saltAuthhashAuthHMAC(saltHMAC | saltEncrypt | ciphertext, keyHMAC)”一词意味着级联saltHMACsaltEncryptciphertext然后,在请求解密数据时:
hashAuth,以验证解密的权限。keyHMAC来计算HMAC,然后将其与存储的值进行比较,以检测篡改。keyEncrypt并执行解密。https://crypto.stackexchange.com/questions/3484
复制相似问题