Proyectos de Subversion Android Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
package com.cesams.twogetskills.library;
2
 
3
import java.nio.ByteBuffer;
4
import java.security.SecureRandom;
5
 
6
import javax.crypto.Cipher;
7
import javax.crypto.spec.IvParameterSpec;
8
import javax.crypto.spec.SecretKeySpec;
9
 
10
/**
11
 * AesCipher
12
 * <p>Encode/Decode text by password using AES-128-CBC algorithm</p>
13
 */
14
public class AesCipher {
15
    public static final int INIT_VECTOR_LENGTH = 16;
16
    /**
17
     * @see <a href="https://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java">how-to-convert-a-byte-array-to-a-hex-string</a>
18
     */
19
    private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
20
 
21
    /**
22
     * Encoded/Decoded data
23
     */
24
    protected String data;
25
    /**
26
     * Initialization vector value
27
     */
28
    protected String initVector;
29
    /**
30
     * Error message if operation failed
31
     */
32
    protected String errorMessage;
33
 
34
    private AesCipher() {
35
        super();
36
    }
37
 
38
    /**
39
     * AesCipher constructor.
40
     *
41
     * @param initVector   Initialization vector value
42
     * @param data         Encoded/Decoded data
43
     * @param errorMessage Error message if operation failed
44
     */
45
    private AesCipher(String initVector, String data, String errorMessage) {
46
        super();
47
 
48
        this.initVector = initVector;
49
        this.data = data;
50
        this.errorMessage = errorMessage;
51
    }
52
 
53
    /**
54
     * Encrypt input text by AES-128-CBC algorithm
55
     *
56
     * @param secretKey 16/24/32 -characters secret password
57
     * @param plainText Text for encryption
58
     * @return Encoded string or NULL if error
59
     */
60
    public static AesCipher encrypt(String secretKey, String plainText) {
61
        String initVector = null;
62
        try {
63
            // Check secret length
64
            if (!isKeyLengthValid(secretKey)) {
65
                throw new Exception("Secret key's length must be 128, 192 or 256 bits");
66
            }
67
 
68
            // Get random initialization vector
69
            SecureRandom secureRandom = new SecureRandom();
70
            byte[] initVectorBytes = new byte[INIT_VECTOR_LENGTH / 2];
71
            secureRandom.nextBytes(initVectorBytes);
72
            initVector = bytesToHex(initVectorBytes);
73
            initVectorBytes = initVector.getBytes("UTF-8");
74
 
75
            IvParameterSpec ivParameterSpec = new IvParameterSpec(initVectorBytes);
76
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
77
 
78
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
79
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
80
 
81
            // Encrypt input text
82
            byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
83
 
84
            ByteBuffer byteBuffer = ByteBuffer.allocate(initVectorBytes.length + encrypted.length);
85
            byteBuffer.put(initVectorBytes);
86
            byteBuffer.put(encrypted);
87
 
88
            // Result is base64-encoded string: initVector + encrypted result
89
           // String result = Base64.encodeToString(byteBuffer.array(), Base64.DEFAULT);
90
 
91
            String result = new String(Base64.encode(byteBuffer.array()));
92
 
93
 
94
            // Return successful encoded object
95
            return new AesCipher(initVector, result, null);
96
        } catch (Throwable t) {
97
            t.printStackTrace();
98
            // Operation failed
99
            return new AesCipher(initVector, null, t.getMessage());
100
        }
101
    }
102
 
103
    /**
104
     * Decrypt encoded text by AES-128-CBC algorithm
105
     *
106
     * @param secretKey  16/24/32 -characters secret password
107
     * @param cipherText Encrypted text
108
     * @return Self object instance with data or error message
109
     */
110
    public static AesCipher decrypt(String secretKey, String cipherText) {
111
        try {
112
            // Check secret length
113
            if (!isKeyLengthValid(secretKey)) {
114
                throw new Exception("Secret key's length must be 128, 192 or 256 bits");
115
            }
116
 
117
            // Get raw encoded data
118
           // byte[] encrypted = Base64.decode(cipherText, Base64.DEFAULT);
119
 
120
            byte[] encrypted = Base64.decode(cipherText.getBytes());
121
 
122
            // Slice initialization vector
123
            IvParameterSpec ivParameterSpec = new IvParameterSpec(encrypted, 0, INIT_VECTOR_LENGTH);
124
            // Set secret password
125
            SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
126
 
127
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
128
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
129
 
130
            // Trying to get decrypted text
131
            String result = new String(cipher.doFinal(encrypted, INIT_VECTOR_LENGTH, encrypted.length - INIT_VECTOR_LENGTH));
132
 
133
            // Return successful decoded object
134
            return new AesCipher(bytesToHex(ivParameterSpec.getIV()), result, null);
135
        } catch (Throwable t) {
136
            t.printStackTrace();
137
            // Operation failed
138
            return new AesCipher(null, null, t.getMessage());
139
        }
140
    }
141
 
142
    /**
143
     * Check that secret password length is valid
144
     *
145
     * @param key 16/24/32 -characters secret password
146
     * @return TRUE if valid, FALSE otherwise
147
     */
148
    public static boolean isKeyLengthValid(String key) {
149
        return key.length() == 16 || key.length() == 24 || key.length() == 32;
150
    }
151
 
152
    /**
153
     * Convert Bytes to HEX
154
     *
155
     * @param bytes Bytes array
156
     * @return String with bytes values
157
     */
158
    public static String bytesToHex(byte[] bytes) {
159
        char[] hexChars = new char[bytes.length * 2];
160
        for (int j = 0; j < bytes.length; j++) {
161
            int v = bytes[j] & 0xFF;
162
            hexChars[j * 2] = hexArray[v >>> 4];
163
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
164
        }
165
        return new String(hexChars);
166
    }
167
 
168
    /**
169
     * Get encoded/decoded data
170
     */
171
    public String getData() {
172
        return data;
173
    }
174
 
175
    /**
176
     * Get initialization vector value
177
     */
178
    public String getInitVector() {
179
        return initVector;
180
    }
181
 
182
    /**
183
     * Get error message
184
     */
185
    public String getErrorMessage() {
186
        return errorMessage;
187
    }
188
 
189
    /**
190
     * Check that operation failed
191
     *
192
     * @return TRUE if failed, FALSE otherwise
193
     */
194
    public boolean hasError() {
195
        return this.errorMessage != null;
196
    }
197
 
198
    /**
199
     * To string return resulting data
200
     *
201
     * @return Encoded/decoded data
202
     */
203
    public String toString() {
204
        return getData();
205
    }
206
}