微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – 比播种SecureRandom更好的创建AES密钥的方法

我需要将加密数据从 Java客户端发送到C#服务器.现在我正在学习如何使用AES(要求)加密数据.按照这个接受的答案 android encryption/decryption with AES,我正在做以下事情:
byte[] keyStart = "qweroiwejrwoejlsifeoisrn".getBytes(); // Random character string

byte[] toEncrypt = myMessageString.getBytes();

keyGen = KeyGenerator.getInstance("AES");
sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
keyGen.init(128,sr);
SecretKey secretKey = keyGen.generateKey();
byte[] secretKeyByte = secretKey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(secretKeyByte,"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
cipher.doFinal(toEncrypt);

由于该算法使用keyStart使用SecureRandom,我不确定这是否可以在C#中解码,甚至在没有SecureRandom的情况下在其他Java程序中解码.

这个加密/解密是否只需要知道keyStart的值,或者因为我使用的是SecureRandom,我还需要传递其他内容才能解密?

还有,有更好的方法来做这个还是这个好吗?

解决方法

不,你应该使用SecureRandom从静态数据中获取密钥的整个想法是相当糟糕的:

> SecureRandom的主要功能生成随机值,它不应该用作密钥流的生成器;
> SecureRandom,当用“SHA1PRNG”实例化时,没有实现一个定义良好的算法,实际上已经知道算法会发生变化,甚至从一个Sun JDK到另一个;
> Oracle提供的“SHA1PRNG”实现使用初始种子作为种子,其他人可能只是将种子添加随机池中.

已知使用“SHA1PRNG”作为密钥派生函数会在多个版本的Android上产生问题,并且可能在任何其他Java RE上失败.

那么你该怎么做呢?

>使用新的SecureRandom()甚至更好的,KeyGenerator生成一个真正的随机密钥,如果你需要一个全新的随机密钥,不需要播种随机生成器;
>直接向SecretKeySpec提供已知密钥的byte [],或者使用十六进制解码器从十六进制解码它(请注意,String实例很难从内存中删除,所以只有在没有其他方法时才这样做);
>如果要从密码创建密钥,请使用PBKDF2(使用的迭代次数高于链接中提供的次数);
>如果要从一个密钥种子创建多个密钥,请使用真正的基于密钥的密钥派生机制,例如:使用HKDF(见下文).

如果通过例如种子生成种子,则优选备选方案4.密钥协商算法,如Diffie-Hellman或ECDH.

请注意,对于选项3,PBKDF2,您最好只保留ASCII密码.这是因为Oracle的PBKDF2实现不使用UTF-8编码.

至于选项4,我帮助将所有优秀的KBKDF添加Bouncy Castle libraries,因此如果您可以将Bouncy Castle添加到类路径和/或已安装的安全提供程序列表中,则无需自己实现KBKDF.目前最好的KBKDF可能是HKDF.如果您不能将Bouncy Castle添加到类路径中,那么您可能希望使用SHA-256输出的最左边字节而不是派生数据作为“穷人”KDF.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐