/** * Encrypt the bytes using given password. * @param input the bytes that are intended to be encrypted * @param pwd the password * @return */ public static byte[] cryptEncrypt(byte[] input, String pwd) { javax.crypto.Cipher cipher = cryptGetCipher(pwd, false); byte[] result = null; try { result = cipher.doFinal(input); } catch (javax.crypto.IllegalBlockSizeException ex) { Ts.printErr(ex); } catch (javax.crypto.BadPaddingException ex) { Ts.printErr(ex); } return result; } /** * Decrypt the bytes using given password. * @param cipherText bytes that are intended to be decrypted * @param pwd the password * @return */ public static byte[] cryptDecrypt(byte[] cipherText, String pwd) { javax.crypto.Cipher cipher = cryptGetCipher(pwd, true); byte[] result = null; try { result = cipher.doFinal(cipherText); } catch (javax.crypto.IllegalBlockSizeException ex) { Ts.printErr(ex); } catch (javax.crypto.BadPaddingException ex) { Ts.printErr(ex); } return result; } /** * Common part for encryption and decryption. * @param pwd the password * @param isDecryption <tt>true</tt> if this method is for decryption and <tt>false</tt> if this is for encryption * @return */ private static javax.crypto.Cipher cryptGetCipher(String pwd, boolean isDecryption) { //--- Get the hash algorithm java.security.MessageDigest md5 = null; try { md5 = java.security.MessageDigest.getInstance("MD5"); } catch (java.security.NoSuchAlgorithmException ex) { Ts.printErr(ex); } //--- Hash the pwd to make a 128bit key byte[] key = md5.digest(pwd.getBytes()); //--- Create a key suitable for AES javax.crypto.spec.SecretKeySpec skey = new javax.crypto.spec.SecretKeySpec(key, "AES"); javax.crypto.spec.IvParameterSpec ivSpec = new javax.crypto.spec.IvParameterSpec(md5.digest(key)); javax.crypto.Cipher cipher = null; try { cipher = javax.crypto.Cipher.getInstance("AES/CTR/NoPadding", "SunJCE"); } catch (java.security.NoSuchAlgorithmException ex) { Ts.printErr(ex); } catch (java.security.NoSuchProviderException ex) { Ts.printErr(ex); } catch (javax.crypto.NoSuchPaddingException ex) { Ts.printErr(ex); } try { if (isDecryption) { cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skey, ivSpec); } else { cipher.init(javax.crypto.Cipher.DECRYPT_MODE, skey, ivSpec); } } catch (java.security.InvalidKeyException ex) { Ts.printErr(ex); } catch (java.security.InvalidAlgorithmParameterException ex) { Ts.printErr(ex); } return cipher; } /** * It is for validating whether the encryption and decryption work well. * It is also the example about how to encrypt and decrypt. * @param size the number of bytes that is encrypted and decrypted * @param password the password * @return <tt>true</tt> if the original bytes are equal to the bytes that is the result of encryption and decryption */ public static boolean cryptValidate(int size, String password) { byte[] bytes = new byte[size]; r.nextBytes(bytes); byte[] byte_en = Ts.cryptEncrypt(bytes, password); byte[] byte_de = Ts.cryptDecrypt(byte_en, password); int diff = Ts.arrayCompare(bytes, byte_de, false); int diff2 = Ts.arrayCompare(bytes, byte_en, false); if (diff == 0 && diff2 != 0) { return true; } else { return false; } } /** * Compare two byte arrays. * @param orig * @param recon * @param isPrint * @return the number of bytes that are not equal. */ public static int arrayCompare(byte[] orig, byte[] recon, boolean isPrint) { int numError = 0; for (int i = 0; i < orig.length; i++) { if (orig[i] != recon[i]) { if (isPrint) { System.out.println("error on " + i + " :: " + orig[i] + " :: " + recon[i]); } numError++; } } if (isPrint) { System.out.println("number or error :: " + numError); } return numError; } public static void printErr(java.lang.Exception ex) { printErr(ex.getMessage()); }