1 package com.powercreator.cms.util; 2 3 import java.security.SecureRandom; 4 import javax.crypto.Cipher; 5 import javax.crypto.KeyGenerator; 6 import javax.crypto.SecretKey; 7 import javax.crypto.spec.IvParameterSpec; 8 import javax.crypto.spec.SecretKeySpec; 9 /** 10 * @author vijoz 11 * @version 創建時間:2016-6-30 12 */ 13 public class AESUtils { 14 public static final String TAG = "AESUtils"; 15 16 public static String encrypt(String seed, String clearText) { 17 // Log.d(TAG, "加密前的seed=" + seed + ",內容為:" + clearText); 18 byte[] result = null; 19 try { 20 byte[] rawkey = getRawKey(seed.getBytes()); 21 result = encrypt(rawkey, clearText.getBytes()); 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } 25 String content = toHex(result); 26 // Log.d(TAG, "加密后的內容為:" + content); 27 return content; 28 } 29 30 public static String decrypt(String seed, String encrypted) { 31 // Log.d(TAG, "解密前的seed=" + seed + ",內容為:" + encrypted); 32 byte[] rawKey; 33 try { 34 rawKey = getRawKey(seed.getBytes()); 35 byte[] enc = toByte(encrypted); 36 byte[] result = decrypt(rawKey, enc); 37 String coentn = new String(result); 38 // Log.d(TAG, "解密后的內容為:" + coentn); 39 return coentn; 40 } catch (Exception e) { 41 e.printStackTrace(); 42 return null; 43 } 44 45 } 46 47 private static byte[] getRawKey(byte[] seed) throws Exception { 48 KeyGenerator kgen = KeyGenerator.getInstance("AES"); 49 SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 50 sr.setSeed(seed); 51 kgen.init(128, sr); 52 SecretKey sKey = kgen.generateKey(); 53 byte[] raw = sKey.getEncoded(); 54 return raw; 55 } 56 57 private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { 58 SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 59 // Cipher cipher = Cipher.getInstance("AES"); 60 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 61 cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( 62 new byte[cipher.getBlockSize()])); 63 byte[] encrypted = cipher.doFinal(clear); 64 return encrypted; 65 } 66 67 private static byte[] decrypt(byte[] raw, byte[] encrypted) 68 throws Exception { 69 SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 70 // Cipher cipher = Cipher.getInstance("AES"); 71 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 72 cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( 73 new byte[cipher.getBlockSize()])); 74 byte[] decrypted = cipher.doFinal(encrypted); 75 return decrypted; 76 } 77 78 public static String toHex(String txt) { 79 return toHex(txt.getBytes()); 80 } 81 82 public static String fromHex(String hex) { 83 return new String(toByte(hex)); 84 } 85 86 public static byte[] toByte(String hexString) { 87 int len = hexString.length() / 2; 88 byte[] result = new byte[len]; 89 for (int i = 0; i < len; i++) 90 result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 91 16).byteValue(); 92 return result; 93 } 94 95 public static String toHex(byte[] buf) { 96 if (buf == null) 97 return ""; 98 StringBuffer result = new StringBuffer(2 * buf.length); 99 for (int i = 0; i < buf.length; i++) { 100 appendHex(result, buf[i]); 101 } 102 return result.toString(); 103 } 104 105 private static void appendHex(StringBuffer sb, byte b) { 106 final String HEX = "0123456789ABCDEF"; 107 sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); 108 } 109 }
上面的實現貌似有些問題,待調試!
下面是轉發的另一個實現:
1 import java.io.UnsupportedEncodingException; 2 import java.security.InvalidKeyException; 3 import java.security.Key; 4 import java.security.NoSuchAlgorithmException; 5 import javax.crypto.BadPaddingException; 6 import javax.crypto.Cipher; 7 import javax.crypto.IllegalBlockSizeException; 8 import javax.crypto.KeyGenerator; 9 import javax.crypto.NoSuchPaddingException; 10 import javax.crypto.spec.SecretKeySpec; 11 12 public class AES { 13 14 static final String algorithmStr = "AES/ECB/PKCS5Padding"; 15 16 private static final Object TAG = "AES"; 17 18 static private KeyGenerator keyGen; 19 20 static private Cipher cipher; 21 22 static boolean isInited = false; 23 24 private static void init() { 25 try { 26 /**為指定算法生成一個 KeyGenerator 對象。 27 *此類提供(對稱)密鑰生成器的功能。 28 *密鑰生成器是使用此類的某個 getInstance 類方法構造的。 29 *KeyGenerator 對象可重復使用,也就是說,在生成密鑰后, 30 *可以重復使用同一 KeyGenerator 對象來生成進一步的密鑰。 31 *生成密鑰的方式有兩種:與算法無關的方式,以及特定於算法的方式。 32 *兩者之間的惟一不同是對象的初始化: 33 *與算法無關的初始化 34 *所有密鑰生成器都具有密鑰長度 和隨機源 的概念。 35 *此 KeyGenerator 類中有一個 init 方法,它可采用這兩個通用概念的參數。 36 *還有一個只帶 keysize 參數的 init 方法, 37 *它使用具有最高優先級的提供程序的 SecureRandom 實現作為隨機源 38 *(如果安裝的提供程序都不提供 SecureRandom 實現,則使用系統提供的隨機源)。 39 *此 KeyGenerator 類還提供一個只帶隨機源參數的 inti 方法。 40 *因為調用上述與算法無關的 init 方法時未指定其他參數, 41 *所以由提供程序決定如何處理將與每個密鑰相關的特定於算法的參數(如果有)。 42 *特定於算法的初始化 43 *在已經存在特定於算法的參數集的情況下, 44 *有兩個具有 AlgorithmParameterSpec 參數的 init 方法。 45 *其中一個方法還有一個 SecureRandom 參數, 46 *而另一個方法將已安裝的高優先級提供程序的 SecureRandom 實現用作隨機源 47 *(或者作為系統提供的隨機源,如果安裝的提供程序都不提供 SecureRandom 實現)。 48 *如果客戶端沒有顯式地初始化 KeyGenerator(通過調用 init 方法), 49 *每個提供程序必須提供(和記錄)默認初始化。 50 */ 51 keyGen = KeyGenerator.getInstance("AES"); 52 } catch (NoSuchAlgorithmException e) { 53 e.printStackTrace(); 54 } 55 // 初始化此密鑰生成器,使其具有確定的密鑰長度。 56 keyGen.init(128); //128位的AES加密 57 try { 58 // 生成一個實現指定轉換的 Cipher 對象。 59 cipher = Cipher.getInstance(algorithmStr); 60 } catch (NoSuchAlgorithmException e) { 61 e.printStackTrace(); 62 } catch (NoSuchPaddingException e) { 63 e.printStackTrace(); 64 } 65 //標識已經初始化過了的字段 66 isInited = true; 67 } 68 69 private static byte[] genKey() { 70 if (!isInited) { 71 init(); 72 } 73 //首先 生成一個密鑰(SecretKey), 74 //然后,通過這個秘鑰,返回基本編碼格式的密鑰,如果此密鑰不支持編碼,則返回 null。 75 return keyGen.generateKey().getEncoded(); 76 } 77 78 private static byte[] encrypt(byte[] content, byte[] keyBytes) { 79 byte[] encryptedText = null; 80 if (!isInited) { 81 init(); 82 } 83 /** 84 *類 SecretKeySpec 85 *可以使用此類來根據一個字節數組構造一個 SecretKey, 86 *而無須通過一個(基於 provider 的)SecretKeyFactory。 87 *此類僅對能表示為一個字節數組並且沒有任何與之相關聯的鑰參數的原始密鑰有用 88 *構造方法根據給定的字節數組構造一個密鑰。 89 *此構造方法不檢查給定的字節數組是否指定了一個算法的密鑰。 90 */ 91 Key key = new SecretKeySpec(keyBytes, "AES"); 92 try { 93 // 用密鑰初始化此 cipher。 94 cipher.init(Cipher.ENCRYPT_MODE, key); 95 } catch (InvalidKeyException e) { 96 e.printStackTrace(); 97 } 98 try { 99 //按單部分操作加密或解密數據,或者結束一個多部分操作。(不知道神馬意思) 100 encryptedText = cipher.doFinal(content); 101 } catch (IllegalBlockSizeException e) { 102 e.printStackTrace(); 103 } catch (BadPaddingException e) { 104 e.printStackTrace(); 105 } 106 return encryptedText; 107 } 108 109 private static byte[] encrypt(String content, String password) { 110 try { 111 byte[] keyStr = getKey(password); 112 SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); 113 Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr 114 byte[] byteContent = content.getBytes("utf-8"); 115 cipher.init(Cipher.ENCRYPT_MODE, key);// ʼ 116 byte[] result = cipher.doFinal(byteContent); 117 return result; // 118 } catch (NoSuchAlgorithmException e) { 119 e.printStackTrace(); 120 } catch (NoSuchPaddingException e) { 121 e.printStackTrace(); 122 } catch (InvalidKeyException e) { 123 e.printStackTrace(); 124 } catch (UnsupportedEncodingException e) { 125 e.printStackTrace(); 126 } catch (IllegalBlockSizeException e) { 127 e.printStackTrace(); 128 } catch (BadPaddingException e) { 129 e.printStackTrace(); 130 } 131 return null; 132 } 133 134 private static byte[] decrypt(byte[] content, String password) { 135 try { 136 byte[] keyStr = getKey(password); 137 SecretKeySpec key = new SecretKeySpec(keyStr, "AES"); 138 Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr 139 cipher.init(Cipher.DECRYPT_MODE, key);// ʼ 140 byte[] result = cipher.doFinal(content); 141 return result; // 142 } catch (NoSuchAlgorithmException e) { 143 e.printStackTrace(); 144 } catch (NoSuchPaddingException e) { 145 e.printStackTrace(); 146 } catch (InvalidKeyException e) { 147 e.printStackTrace(); 148 } catch (IllegalBlockSizeException e) { 149 e.printStackTrace(); 150 } catch (BadPaddingException e) { 151 e.printStackTrace(); 152 } 153 return null; 154 } 155 156 private static byte[] getKey(String password) { 157 byte[] rByte = null; 158 if (password!=null) { 159 rByte = password.getBytes(); 160 }else{ 161 rByte = new byte[24]; 162 } 163 return rByte; 164 } 165 166 /** 167 * 將二進制轉換成16進制 168 * @param buf 169 * @return 170 */ 171 public static String parseByte2HexStr(byte buf[]) { 172 StringBuffer sb = new StringBuffer(); 173 for (int i = 0; i < buf.length; i++) { 174 String hex = Integer.toHexString(buf[i] & 0xFF); 175 if (hex.length() == 1) { 176 hex = '0' + hex; 177 } 178 sb.append(hex.toUpperCase()); 179 } 180 return sb.toString(); 181 } 182 183 /** 184 * 將16進制轉換為二進制 185 * @param hexStr 186 * @return 187 */ 188 public static byte[] parseHexStr2Byte(String hexStr) { 189 if (hexStr.length() < 1) 190 return null; 191 byte[] result = new byte[hexStr.length() / 2]; 192 for (int i = 0; i < hexStr.length() / 2; i++) { 193 int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); 194 int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 195 16); 196 result[i] = (byte) (high * 16 + low); 197 } 198 return result; 199 } 200 201 //注意: 這里的password(秘鑰必須是16位的) 202 private static final String keyBytes = "abcdefgabcdefg12"; 203 204 /** 205 *加密 206 */ 207 public static String encode(String content){ 208 //加密之后的字節數組,轉成16進制的字符串形式輸出 209 return parseByte2HexStr(encrypt(content, keyBytes)); 210 } 211 212 /** 213 *解密 214 */ 215 public static String decode(String content){ 216 //解密之前,先將輸入的字符串按照16進制轉成二進制的字節數組,作為待解密的內容輸入 217 byte[] b = decrypt(parseHexStr2Byte(content), keyBytes); 218 return new String(b); 219 } 220 221 //測試用例 222 public static void test1(){ 223 String content = "hello abcdefggsdfasdfasdf"; 224 String pStr = encode(content ); 225 System.out.println("加密前:"+content); 226 System.out.println("加密后:" + pStr); 227 228 String postStr = decode(pStr); 229 System.out.println("解密后:"+ postStr ); 230 } 231 232 public static void main(String[] args) { 233 test1(); 234 } 235 }
第三個,說實測兼容所有版本的:
1 import android.annotation.SuppressLint; 2 import java.security.SecureRandom; 3 4 import javax.crypto.Cipher; 5 import javax.crypto.KeyGenerator; 6 import javax.crypto.SecretKey; 7 import javax.crypto.spec.IvParameterSpec; 8 import javax.crypto.spec.SecretKeySpec; 9 10 /** 11 * 12 * 13 * Author:sunger 14 */ 15 public class AESUtils { 16 17 public static String encrypt(String seed, String cleartext) 18 throws Exception { 19 20 byte[] rawKey = getRawKey(seed.getBytes()); 21 22 byte[] result = encrypt(rawKey, cleartext.getBytes()); 23 24 return toHex(result); 25 26 } 27 28 public static String decrypt(String seed, String encrypted) 29 throws Exception { 30 31 byte[] rawKey = getRawKey(seed.getBytes()); 32 33 byte[] enc = toByte(encrypted); 34 35 byte[] result = decrypt(rawKey, enc); 36 37 return new String(result); 38 39 } 40 41 @SuppressLint("TrulyRandom") 42 private static byte[] getRawKey(byte[] seed) throws Exception { 43 44 KeyGenerator kgen = KeyGenerator.getInstance("AES"); 45 46 SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto"); 47 48 sr.setSeed(seed); 49 50 kgen.init(128, sr); // 192 and 256 bits may not be available 51 52 SecretKey skey = kgen.generateKey(); 53 54 byte[] raw = skey.getEncoded(); 55 56 return raw; 57 58 } 59 60 private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception { 61 62 SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 63 64 Cipher cipher = Cipher.getInstance("AES"); 65 66 cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec( 67 new byte[cipher.getBlockSize()])); 68 69 byte[] encrypted = cipher.doFinal(clear); 70 71 return encrypted; 72 73 } 74 75 private static byte[] decrypt(byte[] raw, byte[] encrypted) 76 throws Exception { 77 78 SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 79 80 Cipher cipher = Cipher.getInstance("AES"); 81 82 cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec( 83 new byte[cipher.getBlockSize()])); 84 85 byte[] decrypted = cipher.doFinal(encrypted); 86 87 return decrypted; 88 89 } 90 91 private static byte[] toByte(String hexString) { 92 93 int len = hexString.length() / 2; 94 95 byte[] result = new byte[len]; 96 97 for (int i = 0; i < len; i++) 98 99 result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 100 16).byteValue(); 101 102 return result; 103 104 } 105 106 private static String toHex(byte[] buf) { 107 108 if (buf == null) 109 110 return ""; 111 112 StringBuffer result = new StringBuffer(2 * buf.length); 113 114 for (int i = 0; i < buf.length; i++) { 115 116 appendHex(result, buf[i]); 117 118 } 119 120 return result.toString(); 121 122 } 123 124 private final static String HEX = "0123456789ABCDEF"; 125 126 private static void appendHex(StringBuffer sb, byte b) { 127 128 sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); 129 130 } 131 132 }
相關連接:http://blog.csdn.net/xinzheng_wang/article/details/9159969
http://blog.csdn.net/randyjiawenjie/article/details/6587986
http://blog.csdn.net/wuchuanpingstone/article/details/6715196