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);
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
.
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?
KeyGenerator keyGen = KeyGenerator. getInstance("AES"); keyGen. init(256); // for example SecretKey secretKey = keyGen. generateKey();
AES-256, which has a key length of 256 bits, supports the largest bit size and is practically unbreakable by brute force based on current computing power, making it the strongest encryption standard.
An AES key is a random bitstring of the right length. For a 128-bit AES key you need 16 bytes. For a 256-bit AES key you need 32 bytes.
No, the whole idea that you should use a SecureRandom
for key derivation from static data is rather bad:
SecureRandom
's main function is to generate random values, it should not be used as a generator for a key stream;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;"SHA1PRNG"
uses the initial seed as only seed, others may just add the seed to the random pool.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.
So what should you do instead?
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;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);Option 4 would be preferred if the seed was generated by e.g. a key agreement algorithm such as Diffie-Hellman or ECDH.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With