patternjavaMinor
Encrypting a payload for transmission over HTTP. AES256 with PBKDF2
Viewed 0 times
pbkdf2withaes256encryptinghttpforoverpayloadtransmission
Problem
I've done some reading about implementing AES256 and deriving a key from a password. If I understand correctly:
I decided to pack everything together in one byte array where the first 16 bytes is the salt, the next 16 bytes is the IV and the rest is the encrypted message. This with a key length of 256 bits and 20000 iterations for generating the key. I also encode the whole thing in Base64 for transmission.
Can this approach be improved? Knowing that I'm limited to 256 bytes for the complete message (salt+iv+message).
```
public class app {
public static void main(String[] args) throws Exception {
int iterations = 20000;
int keyLength = 32;
byte[] salt = getRandomBytes(16);
byte[] iv = getRandomBytes(16);
char[] password = "password_here".toCharArray();
byte[] payload = "payload_here".getBytes();
byte[] key = deriveKey(iterations, keyLength, salt, iv, password);
byte[] encrypted = encrypt(iv, key, payload);
byte[] bytes = concatBytes(salt, iv, encrypted);
String output = Base64.encodeBytes(bytes);
int outputLength = output.getBytes().length;
System.out.println(outputLength + "\n" + output);
}
private static byte[] deriveKey(int iterations, int length, byte[] salt, byte[] iv, char[] password)
throws InvalidKeySpecException, NoSuchAlgorithmException {
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, length * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = skf.generateSecret(spec).getEncoded();
return key;
}
private static byte[] getRandomBytes(int length) throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG")
- I want to generate a new salt (for the key) and a new IV (for the encrypted message) for every new message.
- It should also not be a problem sending the salt and the IV together with the message.
I decided to pack everything together in one byte array where the first 16 bytes is the salt, the next 16 bytes is the IV and the rest is the encrypted message. This with a key length of 256 bits and 20000 iterations for generating the key. I also encode the whole thing in Base64 for transmission.
Can this approach be improved? Knowing that I'm limited to 256 bytes for the complete message (salt+iv+message).
```
public class app {
public static void main(String[] args) throws Exception {
int iterations = 20000;
int keyLength = 32;
byte[] salt = getRandomBytes(16);
byte[] iv = getRandomBytes(16);
char[] password = "password_here".toCharArray();
byte[] payload = "payload_here".getBytes();
byte[] key = deriveKey(iterations, keyLength, salt, iv, password);
byte[] encrypted = encrypt(iv, key, payload);
byte[] bytes = concatBytes(salt, iv, encrypted);
String output = Base64.encodeBytes(bytes);
int outputLength = output.getBytes().length;
System.out.println(outputLength + "\n" + output);
}
private static byte[] deriveKey(int iterations, int length, byte[] salt, byte[] iv, char[] password)
throws InvalidKeySpecException, NoSuchAlgorithmException {
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, length * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = skf.generateSecret(spec).getEncoded();
return key;
}
private static byte[] getRandomBytes(int length) throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG")
Solution
A few, mostly minor notes:
-
-
You have local variable called
-
The
-
According to the Code Conventions for the Java Programming Language class names should start with uppercase letters.
-
"payload_here".getBytes();getBytes() should have been called with a Charset. Otherwise it uses the platform's default charset which can vary from platform to platform and could result to data loss and/or other bugs.-
You have local variable called
salt inside the getRandomBytes method. It's a little bit confusing since the same method is called for iv too:byte[] salt = new byte[length];-
The
encrypt method could throw six different types of exceptions. It's a little bit too much. All of them is a subclass of GeneralSecurityException. I'd use that instead, I don't think that clients want to handle those six different types differently.-
According to the Code Conventions for the Java Programming Language class names should start with uppercase letters.
- Code Conventions for the Java Programming Language, 9 - Naming Conventions
- Effective Java, 2nd edition, Item 56: Adhere to generally accepted naming conventions
Code Snippets
"payload_here".getBytes();byte[] salt = new byte[length];Context
StackExchange Code Review Q#41007, answer score: 5
Revisions (0)
No revisions yet.