· 7 years ago · Nov 21, 2018, 09:40 AM
1package com.voiprec.ui;
2
3import android.util.Base64;
4
5import java.util.Random;
6
7import javax.crypto.Cipher;
8import javax.crypto.spec.IvParameterSpec;
9import javax.crypto.spec.SecretKeySpec;
10
11public class AesCrypto {
12
13 private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";
14
15 private static int CIPHER_KEY_LEN = 16; //128 bits
16
17 /**
18 * Encrypt data using AES Cipher (CBC) with 128 bit key
19 *
20 * @param key - key to use should be 16 bytes long (128 bits)
21 * @param iv - initialization vector
22 * @param data - data to encrypt
23 * @return encryptedData data in base64 encoding with iv attached at end after a :
24 */
25 public static String encrypt(String key, String data) {
26
27 try {
28
29 String iv = getRandomHexString();
30
31 System.out.println("random iv: " + iv);
32
33 IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes("UTF-8"));
34 SecretKeySpec secretKey = new SecretKeySpec(fixKey(key).getBytes("UTF-8"), "AES");
35
36 Cipher cipher = Cipher.getInstance(AesCrypto.CIPHER_NAME);
37 cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
38
39 byte[] encryptedData = cipher.doFinal((data.getBytes()));
40
41
42 String encryptedDataInBase64 = Base64.encodeToString(encryptedData, Base64.NO_WRAP);
43 String ivInBase64 = Base64.encodeToString(iv.getBytes("UTF-8"), Base64.NO_WRAP);
44
45 return encryptedDataInBase64 + ":" + ivInBase64;
46
47 } catch (Exception ex) {
48 throw new RuntimeException(ex);
49 }
50 }
51
52 private static String getRandomHexString(){
53 Random r = new Random();
54 StringBuilder sb = new StringBuilder();
55 while(sb.length() < 16){
56 sb.append(Integer.toHexString(r.nextInt()));
57 }
58
59 return sb.toString().substring(0, 16);
60 }
61
62 private static String fixKey(String key) {
63
64 if (key.length() < AesCrypto.CIPHER_KEY_LEN) {
65 int numPad = AesCrypto.CIPHER_KEY_LEN - key.length();
66
67 for (int i = 0; i < numPad; i++) {
68 key += "0"; //0 pad to len 16 bytes
69 }
70
71 return key;
72 }
73
74 if (key.length() > AesCrypto.CIPHER_KEY_LEN) {
75 return key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
76 }
77
78 return key;
79 }
80
81 /**
82 * Decrypt data using AES Cipher (CBC) with 128 bit key
83 *
84 * @param key - key to use should be 16 bytes long (128 bits)
85 * @param data - encrypted data with iv at the end separate by :
86 * @return decrypted data string
87 */
88
89 public static String decrypt(String key, String data) {
90
91 try {
92 String[] parts = data.split(":");
93
94 IvParameterSpec iv = new IvParameterSpec(Base64.decode(parts[1],Base64.NO_WRAP));
95 SecretKeySpec secretKey = new SecretKeySpec(fixKey(key).getBytes("UTF-8"), "AES");
96
97 Cipher cipher = Cipher.getInstance(AesCrypto.CIPHER_NAME);
98 cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
99
100 byte[] decodedEncryptedData = Base64.decode(parts[0],Base64.NO_WRAP);
101
102 byte[] original = cipher.doFinal(decodedEncryptedData);
103
104 return new String(original);
105 } catch (Exception ex) {
106 throw new RuntimeException(ex);
107 }
108 }
109
110 public static void test() {
111
112 String key = "martin";
113 String plain_text = "catalin";
114
115 System.out.println("key=" + key + " (padded to 16byte/128bits)" + ", data = " + plain_text);
116
117 String encrypted = encrypt(key, plain_text);
118 System.out.println("key:iv = " + encrypted);
119
120 String decrypt = decrypt(key, encrypted);
121 System.out.println("decrypted = " + decrypt);
122 }
123}