Skip to content

Instantly share code, notes, and snippets.

@t0mmyt
Last active March 20, 2018 20:35
Show Gist options
  • Save t0mmyt/ca61d34d13251f79d48e0826ee381348 to your computer and use it in GitHub Desktop.
Save t0mmyt/ca61d34d13251f79d48e0826ee381348 to your computer and use it in GitHub Desktop.
Java AES
package uk.tommyt.kafka.krypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
public class AesUniqueIv {
private static final String CIPHER = "AES/GCM/NoPadding";
private static final String KEY_TYPE = "AES";
private static final int AES_BITS = 256;
private static final int IV_BYTES = 16;
private final SecureRandom secureRandom = new SecureRandom();
private SecretKey secretKey;
private Cipher cipher;
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* Encryptor with random key
*/
public AesUniqueIv() throws NoSuchAlgorithmException, NoSuchPaddingException {
this(newKey());
}
/**
* Encryptor with provided key
*/
public AesUniqueIv(byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException {
this(new SecretKeySpec(key, KEY_TYPE));
}
private AesUniqueIv(SecretKey key) throws NoSuchPaddingException, NoSuchAlgorithmException {
this.secretKey = key;
cipher = Cipher.getInstance(CIPHER);
}
public byte[] getKey() {
return secretKey.getEncoded();
}
public byte[] encrypt(byte[] message) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
IvParameterSpec iv = newIvParameterSpec();
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] encrypted = cipher.doFinal(message);
byte[] encryptedWithIv = new byte[IV_BYTES + encrypted.length];
System.arraycopy(iv.getIV(), 0, encryptedWithIv, 0, iv.getIV().length);
System.arraycopy(encrypted, 0, encryptedWithIv, IV_BYTES, encrypted.length);
return encryptedWithIv;
}
public byte[] decrypt(byte[] message) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] iv = new byte[IV_BYTES];
byte[] encrypted = new byte[message.length - IV_BYTES];
System.arraycopy(message, 0, iv, 0, IV_BYTES);
System.arraycopy(message, IV_BYTES, encrypted, 0, message.length - IV_BYTES);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
return cipher.doFinal(encrypted);
}
private static SecretKey newKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_TYPE);
keyGenerator.init(AES_BITS);
return keyGenerator.generateKey();
}
private IvParameterSpec newIvParameterSpec() {
byte[] iv = new byte[IV_BYTES];
secureRandom.nextBytes(iv);
return new IvParameterSpec(iv);
}
}
package uk.tommyt.kafka.krypto;
import org.junit.Test;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
public class AesUniqueIvTest {
@Test
public void canEncryptAndDecrypt() throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, NoSuchProviderException {
AesUniqueIv in = new AesUniqueIv();
AesUniqueIv out = new AesUniqueIv(in.getKey());
byte[] message = "Hello from the dark side, I must've killed all the jedi, can't say that I'm sorry for blowing up Alderan, We could've ruled the galaxy as father and son".getBytes();
byte[] encrypted1 = in.encrypt(message);
byte[] encrypted2 = in.encrypt(message);
byte[] decrypted1 = out.decrypt(encrypted1);
byte[] decrypted2 = out.decrypt(encrypted2);
assertThat(message, equalTo(decrypted1));
assertThat(message, equalTo(decrypted2));
assertThat(message, not(equalTo(encrypted1)));
assertThat(encrypted1, not(equalTo(encrypted2)));
assertThat(encrypted1.length, equalTo(message.length + 32));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment