2013-06-19 155 views
5

有谁知道从任何长度的密码短语中生成256位密钥值的方法吗?由于需要再次生成加密值并在数据库中进行比较,因此不能加密加密。所以每次加密时必须生成一个相同的加密字符串。生成AES 256位密钥值

目前我正在使用一个32位字符密钥工作在可能不正确的假设这是256位?

所以,我想'快速棕色狐狸'被转换为合适的AES 256位密钥?

+2

“加密不能被加密,因为需要再次生成加密值”这就是为什么通常将salt与散列密码一起存储。这样,如果两个不同的用户具有相同的密码,它会生成不同的哈希值,但对于单个用户,相同的密码将始终生成相同的哈希值。 – svick

+0

坦率地说,没有盐它没有真正加密。不应该可以对加密值进行直接数据库查找。 – Matthew

回答

12

可以构建Rfc2898DeriveBytes Class具有任意大小的密码,然后派生所需大小的关键在这种情况下,256个比特(32个字节):

private static byte[] CreateKey(string password, int keyBytes = 32) 
{ 
    const int Iterations = 300; 
    var keyGenerator = new Rfc2898DeriveBytes(password, Salt, Iterations); 
    return keyGenerator.GetBytes(keyBytes); 
} 

为了产生确定性的输出(即相同的输入将产生相同的输出),您将需要对盐进行硬编码。该盐必须至少为8个字节:

private static readonly byte[] Salt = 
    new byte[] { 10, 20, 30 , 40, 50, 60, 70, 80}; 
+0

请参阅我对上述更多理论描述的解释。请注意''Rfc2898DeriveBytes'实现PBKDF2 :) –

+0

谢谢 - 这是非常有用的。如果keySize是32,但获得一个32字节的键阵列? – bhs

+0

是的,我想这是ByteBlast的一个错误。我还建议你使用UTF-8编码将密码编码为字节,因为Rfc2898DeriveBytes函数没有明确指定它使用的编码。当你使用另一个运行时的函数时,这很棘手。 –

-1

您可以使用一些散列函数,它提供来自任何长度输入的256位输出,例如SHA256。

+1

官方散列不是一个基于密码的密钥派生函数,不应该直接用于这种情况。 –

2

也许最好的方法是使用PBKDF2使用SHA256(其将产生256位的输出)和一个特殊应用盐&迭代计数。您应该知道,使用特定于应用的盐会从PBKDF2中移除相当多的保护,因此您可能需要额外的保护来缓解此问题。一种方法是确保数据库安全,并且可以使用最大尝试次数。

您在规定32字符密码不是256位密钥时是正确的。它不包含足够的熵,有些字节可能甚至没有有效的字符表示。

+0

请参阅ByteBlasts答案以上的实现:) –

+0

感谢 - 所以上述方法的32字节数组是256位密钥? – bhs

+0

这是一个基于密码的密钥派生函数,这就是PBKDF的含义。你输入一个密码,你得到一个密钥(作为字节)。它具有使用盐和多次迭代的保护,这使得计算密钥相对困难(对于您和攻击者而言)。攻击者可能需要做很多事情才能获得关键。但是,最好使用SHA-256或更高版本,因为它需要对超出一个散列输出的任何内容执行全部迭代次数 - 这可能只会影响到您而不是攻击者。 –