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

问题描述

我需要从 Java 客户端发送加密数据到一个 C#服务器。现在我正在学习如何使用 AES (要求)加密数据。遵循这个接受的答案我正在做以下: / p>

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#中解码,甚至在另一个 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. The Oracle provided implementation of "SHA1PRNG" uses 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()甚至更好,生成一个真正的随机密钥,如果您需要一个全新的随机密钥,不播放随机数生成器;

  2. 直接向 SecretKeySpec 提供已知密钥的字节[] 或使用十六进制解码器从十六进制解码(请注意, String 实例难以从内存中删除,因此只有在没有其他方式的情况下才能执行此操作);

  3. 如果要从密码创建密钥,请使用(使用较高的迭代次数比链接中提供的那些);

  4. 如果要从一个关键种子创建多个键,请使用真正的基于键的键导出机制,例如使用HKDF(见下文)。

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

如果种子是由例如一个密钥协商算法,如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.

请注意,对于选项3,PBKDF2,您将是明智的仅保留ASCII密码。这是由于Oracle的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添加到,因此没有如果您可以将Bouncy Castle添加到您的类路径和/或已安装的安全提供程序列表中,则需要自行实施KBKDF。目前最好的KBKDF是HKDF。如果您不能将Bouncy Castle添加到您的类路径中,那么您可能希望将派生数据中最左边的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密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 14:41