【发布时间】:2011-11-20 00:49:38
【问题描述】:
是否可以编写一个方法从 AES-128、AES-192 和 AES-256 的密码生成有效密钥?
我在想这样的事情:
SecretKeyFactory f;
try {
f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
throw new Exception("Key derivation algorithm not available.", e);
}
KeySpec ks = new PBEKeySpec(password.toCharArray());
SecretKey s;
try {
s = f.generateSecret(ks);
} catch (InvalidKeySpecException e) {
throw new Exception("Key generation failed.", e);
}
Key k = new SecretKeySpec(s.getEncoded(),"AES");
我使用类似的方法为 AES-256 生成加盐密钥。但是,现在我必须仅从密码生成密钥(没有盐和迭代),并且我需要它们适用于 AES-128、AES-192 和 AES-256。我的问题是,此代码是否返回与每种 AES-XXX 尺寸兼容的密钥,还是应该为每种尺寸编写不同的代码?
另外,是否有更好的(在安全性或简单性方面)从密码生成密钥的方法?
更新:最后我做了一些测试,结果证明这个构造函数:
KeySpec ks = new PBEKeySpec(password.toCharArray());
总是在这个块上抛出一个InvalidKeySpecException:
try {
s = f.generateSecret(ks);
} catch (InvalidKeySpecException e) {
throw new Exception("Key generation failed.", e);
}
所以我坚持使用另一个需要盐作为参数的构造函数:
KeySpec ks = new PBEKeySpec(password.toCharArray(), "somepredefinedsalt".getBytes(), numIters, keySizeInBits);
由于我没有盐,我考虑过硬编码一个预定义的盐。现在我不知道哪个选项更安全,编码预定义盐并使用 PBKDF2 或使用截断哈希。
【问题讨论】:
-
加盐的、加长的散列非常强。在生成 256 位后,您可以将结果截断为所需的任何长度。
-
@bdares 如果我使用 256 位哈希的一部分来获得 128 位或 192 位的密钥,那么两个不同的密码可能会生成相同的截断密钥。
-
那,唉,太真实了。不幸的是,无限数量的密码可以使用散列函数生成相同的密钥。你只需要安慰一下,故意这样做真的很难。
-
每个位都很难预测,因此仅预测和碰撞前 128 位、低 128 位或其他所有位同样困难(每位)。这就是为什么它是加密哈希的理想属性。如果您认为从攻击者的角度来看它们实际上是随机的,那么随机数字集的子集仍然是随机的,并且与另一个更小、不同生成的随机数字集一样好。
-
@MisterSmith "那么两个不同的密码可能会生成相同的截断密钥" 这不太可能。如果你关心这样的几率,为什么不假设你的对手可以通过随机尝试 128 位数字来找到 128 位密钥呢? ;)
标签: java encryption aes