AutorÃa | Ultima modificación | Ver Log |
package com.cesams.twogetskills.library;import java.nio.ByteBuffer;import java.security.SecureRandom;import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;/*** AesCipher* <p>Encode/Decode text by password using AES-128-CBC algorithm</p>*/public class AesCipher {public static final int INIT_VECTOR_LENGTH = 16;/*** @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>*/private final static char[] hexArray = "0123456789ABCDEF".toCharArray();/*** Encoded/Decoded data*/protected String data;/*** Initialization vector value*/protected String initVector;/*** Error message if operation failed*/protected String errorMessage;private AesCipher() {super();}/*** AesCipher constructor.** @param initVector Initialization vector value* @param data Encoded/Decoded data* @param errorMessage Error message if operation failed*/private AesCipher(String initVector, String data, String errorMessage) {super();this.initVector = initVector;this.data = data;this.errorMessage = errorMessage;}/*** Encrypt input text by AES-128-CBC algorithm** @param secretKey 16/24/32 -characters secret password* @param plainText Text for encryption* @return Encoded string or NULL if error*/public static AesCipher encrypt(String secretKey, String plainText) {String initVector = null;try {// Check secret lengthif (!isKeyLengthValid(secretKey)) {throw new Exception("Secret key's length must be 128, 192 or 256 bits");}// Get random initialization vectorSecureRandom secureRandom = new SecureRandom();byte[] initVectorBytes = new byte[INIT_VECTOR_LENGTH / 2];secureRandom.nextBytes(initVectorBytes);initVector = bytesToHex(initVectorBytes);initVectorBytes = initVector.getBytes("UTF-8");IvParameterSpec ivParameterSpec = new IvParameterSpec(initVectorBytes);SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);// Encrypt input textbyte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));ByteBuffer byteBuffer = ByteBuffer.allocate(initVectorBytes.length + encrypted.length);byteBuffer.put(initVectorBytes);byteBuffer.put(encrypted);// Result is base64-encoded string: initVector + encrypted result// String result = Base64.encodeToString(byteBuffer.array(), Base64.DEFAULT);String result = new String(Base64.encode(byteBuffer.array()));// Return successful encoded objectreturn new AesCipher(initVector, result, null);} catch (Throwable t) {t.printStackTrace();// Operation failedreturn new AesCipher(initVector, null, t.getMessage());}}/*** Decrypt encoded text by AES-128-CBC algorithm** @param secretKey 16/24/32 -characters secret password* @param cipherText Encrypted text* @return Self object instance with data or error message*/public static AesCipher decrypt(String secretKey, String cipherText) {try {// Check secret lengthif (!isKeyLengthValid(secretKey)) {throw new Exception("Secret key's length must be 128, 192 or 256 bits");}// Get raw encoded data// byte[] encrypted = Base64.decode(cipherText, Base64.DEFAULT);byte[] encrypted = Base64.decode(cipherText.getBytes());// Slice initialization vectorIvParameterSpec ivParameterSpec = new IvParameterSpec(encrypted, 0, INIT_VECTOR_LENGTH);// Set secret passwordSecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);// Trying to get decrypted textString result = new String(cipher.doFinal(encrypted, INIT_VECTOR_LENGTH, encrypted.length - INIT_VECTOR_LENGTH));// Return successful decoded objectreturn new AesCipher(bytesToHex(ivParameterSpec.getIV()), result, null);} catch (Throwable t) {t.printStackTrace();// Operation failedreturn new AesCipher(null, null, t.getMessage());}}/*** Check that secret password length is valid** @param key 16/24/32 -characters secret password* @return TRUE if valid, FALSE otherwise*/public static boolean isKeyLengthValid(String key) {return key.length() == 16 || key.length() == 24 || key.length() == 32;}/*** Convert Bytes to HEX** @param bytes Bytes array* @return String with bytes values*/public static String bytesToHex(byte[] bytes) {char[] hexChars = new char[bytes.length * 2];for (int j = 0; j < bytes.length; j++) {int v = bytes[j] & 0xFF;hexChars[j * 2] = hexArray[v >>> 4];hexChars[j * 2 + 1] = hexArray[v & 0x0F];}return new String(hexChars);}/*** Get encoded/decoded data*/public String getData() {return data;}/*** Get initialization vector value*/public String getInitVector() {return initVector;}/*** Get error message*/public String getErrorMessage() {return errorMessage;}/*** Check that operation failed** @return TRUE if failed, FALSE otherwise*/public boolean hasError() {return this.errorMessage != null;}/*** To string return resulting data** @return Encoded/decoded data*/public String toString() {return getData();}}