Last active
March 20, 2018 20:35
-
-
Save t0mmyt/ca61d34d13251f79d48e0826ee381348 to your computer and use it in GitHub Desktop.
Java AES
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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