Skip to content

Commit 7e59795

Browse files
authored
feat(jans-core): add AES utility class #3215 (#3242)
1 parent 9f38c6a commit 7e59795

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

jans-core/util/pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@
9999
<groupId>jakarta.xml.bind</groupId>
100100
<artifactId>jakarta.xml.bind-api</artifactId>
101101
</dependency>
102+
103+
<dependency>
104+
<groupId>org.testng</groupId>
105+
<artifactId>testng</artifactId>
106+
</dependency>
107+
102108
</dependencies>
103109

104110
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package io.jans.util.security;
2+
3+
import javax.crypto.*;
4+
import javax.crypto.spec.GCMParameterSpec;
5+
import javax.crypto.spec.IvParameterSpec;
6+
import javax.crypto.spec.PBEKeySpec;
7+
import javax.crypto.spec.SecretKeySpec;
8+
import java.security.InvalidAlgorithmParameterException;
9+
import java.security.InvalidKeyException;
10+
import java.security.NoSuchAlgorithmException;
11+
import java.security.SecureRandom;
12+
import java.security.spec.AlgorithmParameterSpec;
13+
import java.security.spec.InvalidKeySpecException;
14+
import java.security.spec.KeySpec;
15+
import java.util.Base64;
16+
17+
public class AESUtil {
18+
19+
public static final int IV_LENGTH = 16;
20+
public static final int GCM_TAG_LENGTH = 16;
21+
22+
private AESUtil() {
23+
}
24+
25+
public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
26+
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
27+
keyGenerator.init(n);
28+
return keyGenerator.generateKey();
29+
}
30+
31+
public static SecretKey getKeyFromPassword(String password, String salt)
32+
throws NoSuchAlgorithmException, InvalidKeySpecException {
33+
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
34+
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
35+
return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
36+
}
37+
38+
public static IvParameterSpec generateIv() {
39+
return generateIv(IV_LENGTH);
40+
}
41+
42+
public static IvParameterSpec generateIv(int size) {
43+
byte[] iv = new byte[size];
44+
new SecureRandom().nextBytes(iv);
45+
return new IvParameterSpec(iv);
46+
}
47+
48+
public static GCMParameterSpec generateGcmSpec() {
49+
return new GCMParameterSpec(GCM_TAG_LENGTH * 8, generateIv().getIV());
50+
}
51+
52+
public static String encrypt(String algorithm, String input, SecretKey key, AlgorithmParameterSpec spec) throws NoSuchPaddingException, NoSuchAlgorithmException,
53+
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
54+
55+
Cipher cipher = Cipher.getInstance(algorithm);
56+
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
57+
byte[] cipherText = cipher.doFinal(input.getBytes());
58+
return Base64.getEncoder().encodeToString(cipherText);
59+
}
60+
61+
public static String decrypt(String algorithm, String cipherText, SecretKey key, AlgorithmParameterSpec spec) throws NoSuchPaddingException, NoSuchAlgorithmException,
62+
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
63+
Cipher cipher = Cipher.getInstance(algorithm);
64+
cipher.init(Cipher.DECRYPT_MODE, key, spec);
65+
byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
66+
return new String(plainText);
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.jans.util.security;
2+
3+
import org.testng.annotations.Test;
4+
5+
import javax.crypto.BadPaddingException;
6+
import javax.crypto.IllegalBlockSizeException;
7+
import javax.crypto.NoSuchPaddingException;
8+
import javax.crypto.SecretKey;
9+
import javax.crypto.spec.GCMParameterSpec;
10+
import javax.crypto.spec.IvParameterSpec;
11+
import java.security.InvalidAlgorithmParameterException;
12+
import java.security.InvalidKeyException;
13+
import java.security.NoSuchAlgorithmException;
14+
15+
import static io.jans.util.security.AESUtil.generateGcmSpec;
16+
import static org.testng.Assert.assertEquals;
17+
18+
/**
19+
* @author Yuriy Z
20+
*/
21+
public class AESUtilTest {
22+
23+
@Test
24+
public void cbc_whenEncryptAndDecrypt_shouldProduceCorrectOutput() throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
25+
String input = "textToEncrypt";
26+
SecretKey key = AESUtil.generateKey(128);
27+
IvParameterSpec ivParameterSpec = AESUtil.generateIv();
28+
29+
String algorithm = "AES/CBC/PKCS5Padding";
30+
String cipherText = AESUtil.encrypt(algorithm, input, key, ivParameterSpec);
31+
String plainText = AESUtil.decrypt(algorithm, cipherText, key, ivParameterSpec);
32+
33+
assertEquals(input, plainText);
34+
}
35+
36+
@Test
37+
public void gcm_whenEncryptAndDecrypt_shouldProduceCorrectOutput() throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
38+
String input = "textToEncrypt";
39+
SecretKey key = AESUtil.generateKey(128);
40+
41+
String algorithm = "AES/GCM/NoPadding";
42+
final GCMParameterSpec gcmSpec = generateGcmSpec();
43+
44+
String cipherText = AESUtil.encrypt(algorithm, input, key, gcmSpec);
45+
String plainText = AESUtil.decrypt(algorithm, cipherText, key, gcmSpec);
46+
47+
assertEquals(input, plainText);
48+
}
49+
}

0 commit comments

Comments
 (0)