diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/CryptoDriver.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/CryptoDriver.java new file mode 100644 index 0000000000..552bd5d474 --- /dev/null +++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/CryptoDriver.java @@ -0,0 +1,86 @@ +package com.baeldung.crypto; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; +import java.security.GeneralSecurityException; + +import com.baeldung.crypto.utils.CryptoUtils; + +public class CryptoDriver { + + public byte[] ecbEncrypt(SecretKey key, byte[] data) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, key); + return cipher.doFinal(data); + } + + public byte[] ecbDecrypt(SecretKey key, byte[] cipherText) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, key); + return cipher.doFinal(cipherText); + } + + public byte[] cbcEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + return cipher.doFinal(data); + } + + public byte[] cbcDecrypt(SecretKey key, IvParameterSpec iv, byte[] cipherText) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + return cipher.doFinal(cipherText); + } + + public byte[] cfbEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + return cipher.doFinal(data); + } + + public byte[] cfbDecrypt(SecretKey key, IvParameterSpec iv, byte[] cipherText) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + return cipher.doFinal(cipherText); + } + + public byte[] ofbEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/OFB32/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + return cipher.doFinal(data); + } + + public byte[] ofbDecrypt(SecretKey key, IvParameterSpec iv, byte[] cipherText) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/OFB32/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + return cipher.doFinal(cipherText); + } + + public byte[][] ctrEncrypt(SecretKey key, IvParameterSpec iv, byte[] data) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + return new byte[][] { cipher.getIV(), cipher.doFinal(data) }; + } + + public byte[] ctrDecrypt(SecretKey key, byte[] iv, byte[] cipherText) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); + return cipher.doFinal(cipherText); + } + + public byte[][] gcmEncrypt(SecretKey key, byte[] iv, byte[] data) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv)); + byte[] ciphertext = cipher.doFinal(data); + return new byte[][] { iv, ciphertext }; + } + + public byte[] gcmDecrypt(SecretKey key, byte[] iv, byte[] ciphertext) throws GeneralSecurityException { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv)); + byte[] plaintext = cipher.doFinal(ciphertext); + return plaintext; + } +} diff --git a/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/utils/CryptoUtils.java b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/utils/CryptoUtils.java new file mode 100644 index 0000000000..2d3df231ff --- /dev/null +++ b/core-java-modules/core-java-security-3/src/main/java/com/baeldung/crypto/utils/CryptoUtils.java @@ -0,0 +1,53 @@ +package com.baeldung.crypto.utils; + +import java.security.AlgorithmParameters; +import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidParameterSpecException; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; + +public class CryptoUtils { + + public static SecretKey generateKey() throws GeneralSecurityException { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + keyGenerator.init(256); + return keyGenerator.generateKey(); + } + + public static IvParameterSpec getIV() { + SecureRandom secureRandom = new SecureRandom(); + byte[] iv = new byte[128 / 8]; + byte[] nonce = new byte[96 / 8]; + secureRandom.nextBytes(nonce); + System.arraycopy(nonce, 0, iv, 0, nonce.length); + return new IvParameterSpec(nonce); + } + + public static IvParameterSpec getIVSecureRandom(String algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException { + SecureRandom random = SecureRandom.getInstanceStrong(); + byte[] iv = new byte[Cipher.getInstance(algorithm) + .getBlockSize()]; + random.nextBytes(iv); + return new IvParameterSpec(iv); + } + + public static IvParameterSpec getIVInternal(Cipher cipher) throws InvalidParameterSpecException { + AlgorithmParameters params = cipher.getParameters(); + byte[] iv = params.getParameterSpec(IvParameterSpec.class) + .getIV(); + return new IvParameterSpec(iv); + } + + public static byte[] getRandomIVWithSize(int size) { + byte[] nonce = new byte[size]; + new SecureRandom().nextBytes(nonce); + return nonce; + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-security-3/src/test/java/com/baeldung/crypto/CryptoDriverIVUnitTest.java b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/crypto/CryptoDriverIVUnitTest.java new file mode 100644 index 0000000000..f3bed310dd --- /dev/null +++ b/core-java-modules/core-java-security-3/src/test/java/com/baeldung/crypto/CryptoDriverIVUnitTest.java @@ -0,0 +1,86 @@ +package com.baeldung.crypto; + +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import java.security.GeneralSecurityException; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import com.baeldung.crypto.utils.CryptoUtils; + +public class CryptoDriverIVUnitTest{ + private CryptoDriver driver = new CryptoDriver(); + private String TEST_DATA = "Encrypt this for testing"; + + @Test + public void givenString_whenAesEcb_thenSuccess() throws GeneralSecurityException { + SecretKey key = CryptoUtils.generateKey(); + byte[] plaintext = TEST_DATA.getBytes(); + + byte[] ciphertext = driver.ecbEncrypt(key, plaintext); + byte[] decryptedtext = driver.ecbDecrypt(key, ciphertext); + + Assertions.assertEquals(new String(decryptedtext), TEST_DATA); + } + + @Test + public void givenString_whenAesCbc_thenSuccess() throws GeneralSecurityException { + SecretKey key = CryptoUtils.generateKey(); + IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES"); + byte[] plaintext = TEST_DATA.getBytes(); + + byte[] ciphertext = driver.cbcEncrypt(key, iv, plaintext); + byte[] decryptedtext = driver.cbcDecrypt(key, iv, ciphertext); + + Assertions.assertEquals(new String(decryptedtext), TEST_DATA); + } + + @Test + public void givenString_whenAesCfb_thenSuccess() throws GeneralSecurityException { + SecretKey key = CryptoUtils.generateKey(); + IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/CFB/NoPadding"); + byte[] plaintext = TEST_DATA.getBytes(); + + byte[] ciphertext = driver.cfbEncrypt(key, iv, plaintext); + byte[] decryptedtext = driver.cfbDecrypt(key, iv, ciphertext); + + Assertions.assertEquals(new String(decryptedtext), TEST_DATA); + } + + @Test + public void givenString_whenAesOfb_thenSuccess() throws GeneralSecurityException { + SecretKey key = CryptoUtils.generateKey(); + IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/OFB32/PKCS5Padding"); + byte[] plaintext = TEST_DATA.getBytes(); + + byte[] ciphertext = driver.ofbEncrypt(key, iv, plaintext); + byte[] decryptedtext = driver.ofbDecrypt(key, iv, ciphertext); + + Assertions.assertEquals(new String(decryptedtext), TEST_DATA); + } + + @Test + public void givenString_whenAesCtr_thenSuccess() throws GeneralSecurityException { + SecretKey key = CryptoUtils.generateKey(); + IvParameterSpec iv = CryptoUtils.getIVSecureRandom("AES/CTR/NoPadding"); + byte[] plaintext = TEST_DATA.getBytes(); + + byte[][] ciphertext = driver.ctrEncrypt(key, iv, plaintext); + byte[] decryptedtext = driver.ctrDecrypt(key, ciphertext[0], ciphertext[1]); + + Assertions.assertEquals(new String(decryptedtext), TEST_DATA); + } + + @Test + void givenString_whenAesGcm_thenSuccess() throws GeneralSecurityException { + SecretKey key = CryptoUtils.generateKey(); + byte[] iv = CryptoUtils.getRandomIVWithSize(12); + byte[] plaintext = (TEST_DATA).getBytes(); + + byte[][] ciphertext = driver.gcmEncrypt(key, iv, plaintext); + byte[] decryptedtext = driver.gcmDecrypt(key, ciphertext[0], ciphertext[1]); + + Assertions.assertEquals(new String(decryptedtext), TEST_DATA); + } +} diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 872161c2bd..c3d17e7637 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -99,6 +99,7 @@ core-java-reflection-2 core-java-security core-java-security-2 + core-java-security-3 core-java-streams core-java-streams-2 core-java-streams-3