不,您应该使用a
SecureRandom来从静态数据中派生密钥的想法非常糟糕:
SecureRandom
的主要功能是生成随机值,不应将其用作密钥流的生成器;SecureRandom
,当实例化为时,"SHA1PRNG"
并不能实现定义良好的算法,并且实际上已经知道该算法会发生变化,甚至从一个Sun JDK更改为另一个。- Oracle提供的
"SHA1PRNG"
使用初始种子作为 唯一 种子的实现,其他人可能只是 将 种子 添加 到随机池中。
使用
"SHA1PRNG"的密钥导出函数已经知道生产Android上的几个版本的问题,并且可能无法在任何其他Java RE。
那么,您应该怎么做呢?
- 使用
new SecureRandom()
或什至更好KeyGenerator
地生成真正的随机密钥,如果您需要全新的随机密钥,则无需播种随机数生成器; byte[]
将已知密钥直接提供给SecretKeySpec
,或使用十六进制解码器从十六进制对其进行解码(请注意,String
实例很难从内存中删除,因此,只有在没有其他方法的情况下,才可以这样做);- 如果要通过密码创建密钥,请使用PBKDF2(尽管使用的迭代次数要比链接中提供的次数高);
- 如果要从一个密钥种子中创建多个密钥,请使用真正的基于密钥的密钥派生机制,例如,使用HKDF(请参见下文)。
如果种子是通过例如密钥协商算法(例如Diffie-Hellman或ECDH)生成的,则首选选项4。
请注意,对于选项3 PBKDF2,明智的做法是仅保留ASCII密码。这是由于Oracle的PBKDF2实现不使用UTF-8编码这一事实。
至于选项4,我已经帮助将所有好的KBKDF添加到BouncyCastle库中,因此,如果您可以将BouncyCastle添加到您的类路径和/或已安装的安全提供程序列表中,则无需自己实现KBKDF。目前最好的KBKDF可能是HKDF。如果无法将BouncyCastle添加到类路径中,则可能需要将派生数据上SHA-256输出的最左边字节用作“穷人” KDF。



