更好的方法比播种的SecureRandom创建AES密钥 [英] Better way to create AES keys than seeding SecureRandom

查看:2055
本文介绍了更好的方法比播种的SecureRandom创建AES密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要从的Java 客户端发送加密数据到 C#服务器。现在我正在学习如何使用的数据 AES (要求)进行加密。在此之后接受的答案 Android上的加密/ AES与我做了以下解密:

I need to send encrypted data from a Java client to a C# server. Right now I'm learning how to encrypt data using AES (requirement). Following this accepted answer android encryption/decryption with AES I'm doing the following:

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);

由于算法使用的SecureRandom 使用 keyStart 我不知道这是否可德$ C $在 C# CD,甚至在另一个的Java 程序,而不的SecureRandom

Since the algorithm uses a SecureRandom using the keyStart I am not sure if this can be decoded in C# or even in another Java program, without the SecureRandom.

请问这样的加密/解密只知道 keyStart 的值,或因为我使用的SecureRandom 我的工作仍需要以别的解密传递的东西吗?

Will this encryption/decryption work with just knowing the value of keyStart or since I'm using SecureRandom I still need to pass something else in order to decrypt?

此外,有没有更好的方式来做到这一点或者是这个就好了?

Also, is there a better way to do it or is this one just fine?

推荐答案

没有,那你应该使用整个想法的SecureRandom 从静态数据密钥推导是相当糟糕

No, the whole idea that you should use a SecureRandom for key derivation from static data is rather bad:


  1. SecureRandom的的主要功能是产生随机值,它不应该被用来作为一个密钥流发生器;

  2. 的SecureRandom ,当实例化SHA1PRNG并没有实现一个明确的算法,该算法具有实际被称为改变,甚至从一个Sun JDK到另一个;

  3. 只有Oracle提供的实施SHA1PRNG被定义为只取初始种子为的只有的种子,其他人可能只需添加种子以随机池。

  1. SecureRandom's main function is to generate random values, it should not be used as a generator for a key stream;
  2. SecureRandom, when instantiated with "SHA1PRNG" does not implement a well defined algorithm, and the algorithm has actually be known to change, even from one Sun JDK to another;
  3. Only the Oracle provided implementation of "SHA1PRNG" is defined to only take the initial seed as only seed, others may just add the seed to the random pool.

使用SHA1PRNG作为密钥导出函数已经知道生产Android上的几个版本的问题,并且可能无法在任何其他Java RE。

Using "SHA1PRNG" as key derivation function has been known to produce issues on several versions of Android, and may fail on any other Java RE.

所以,你该怎么办呢?


  1. 使用新的SecureRandom()甚至更好,的 的KeyGenerator 以产生一个真正的随机密钥,没有播种随机数生成器,如果你需要一个全新的随机键;

  2. 直接提供字节[] 已知键 SecretKeySpec ,或者使用十六进制德codeR从十六进制数去code将其(注意,字符串情况下是很难从内存中删除,因此,只有做到这一点,如果没有其他的方式);

  3. 使用 PBKDF2 的,如果你想创建一个从密码密钥(用更高的迭代次数比提供一虽然链接);

  4. 如果你想从一个密钥种子创建多个按键使用基于真正的关键密钥导出机制,例如用香港民主促进会(见下文)。

  1. Use new SecureRandom() or even better, KeyGenerator to generate a truly random key, without seeding the random number generator if you need a brand new random key;
  2. Directly provide a byte[] of a known key to SecretKeySpec, or use a hexadecimal decoder to decode it from hexadecimals (note that String instances are hard to delete from memory, so only do this if there is no other way);
  3. Use PBKDF2 if you want to create a key from a password (use a higher iteration count than the one provided in the link though);
  4. Use a true Key Based Key Derivation Mechanism if you want to create multiple keys from one key seed, e.g. use HKDF (see below).

选项4将pferred $ P $如果是由例如产生的种子一个密钥协议算法等课程的Diffie-Hellman或ECDH

Option 4 would be preferred if the seed was generated by e.g. a key agreement algorithm such as Diffie-Hellman or ECDH of course.

请注意,对于选项3,PBKDF2,你将是明智的保留,只ASCII密码。这是由于一个事实,即甲骨文PBKDF2实现不使用UTF-8编码。

Note that for option 3, PBKDF2, you would be wise to keep to ASCII passwords only. This is due to the fact that the PBKDF2 implementation by Oracle does not use UTF-8 encoding.

至于选项4,我已经帮助与添加都好KBKDF的到充气城堡库所以没有必要自己实现一个KBKDF如果你可以添加充气城堡到类路径中和/或安装的安全提供者列表。也许此刻的最佳KBKDF是香港民主促进会。如果你不能充气城堡添加到您的类路径中,那么你可能想使用SHA-256输出过推导数据的最左边字节为穷人的KDF。

As for option 4, I've helped with adding all good KBKDF's to the Bouncy Castle libraries so there isn't a need to implement a KBKDF yourself if you can add Bouncy Castle to your classpath and/or list of installed security providers. Probably the best KBKDF at the moment is HKDF. If you cannot add Bouncy Castle to your classpath then you might want to use the leftmost bytes of SHA-256 output over the derivation data as a "poor man's" KDF.

这篇关于更好的方法比播种的SecureRandom创建AES密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆