寫在前面
安全測試ECB模式過於簡單需要改為CBC模式加密以下為工具類及測試
AESUtils.java
package com.sgcc.mobile.utils; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.*; /** * AES加密128位CBC模式工具類 */ public class AESUtils { //算法/加密模式/填充方式 private static final String ALGORITHMSTR = "AES/CBC/PKCS5Padding";//"算法/模式/補碼方式" //解密密鑰(自行隨機生成) public static final String KEY = "qxhzngy266a186ke";//秘鑰key public static final String IV = "1ci5crnda6ojzgtr";//偏移量iv //認證密鑰(自行隨機生成) public static final String AK = "s2ip9g3y3bjr5zz7ws6kjgx3ysr82zzw";//AccessKey public static final String SK = "uv8zr0uen7aim8m7umcuooqzdv8cbvtf";//SecretKey //加密 public static String encrypt(String content) throws Exception { byte[] raw = KEY.getBytes("utf-8"); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance(ALGORITHMSTR); //使用CBC模式,需要一個向量iv,可增加加密算法的強度 IvParameterSpec ips = new IvParameterSpec(IV.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ips); byte[] encrypted = cipher.doFinal(content.getBytes()); return new BASE64Encoder().encode(encrypted); } //解密 public static StringBuffer decrypt(String content) throws Exception { try { byte[] raw = KEY.getBytes("utf-8"); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance(ALGORITHMSTR); IvParameterSpec ips = new IvParameterSpec(IV.getBytes()); cipher.init(Cipher.DECRYPT_MODE, skeySpec, ips); byte[] encrypted1 = new BASE64Decoder().decodeBuffer(content); try { byte[] original = cipher.doFinal(encrypted1); StringBuffer originalString = new StringBuffer(new String(original)); return originalString; } catch (Exception e) { System.out.println(e.toString()); return null; } } catch (Exception ex) { System.out.println(ex.toString()); return null; } } //獲取認證簽名(身份認證需要) public static String getSign(String currentTime) throws Exception { String sign = ""; Map<String, Object> map = new HashMap<String, Object>(); map.put("ak", AK); map.put("sk", SK); map.put("ts", currentTime); //獲取 參數字典排序后字符串 String decrypt = getOrderMap(map); try { //指定sha1算法 MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(decrypt.getBytes()); //獲取字節數組 byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字節數組轉換為十六進制數 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } sign = hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return sign; } //獲取參數的字典排序 private static String getOrderMap(Map<String, Object> maps) { List<String> paramNames = new ArrayList<String>(); for (Map.Entry<String, Object> entry : maps.entrySet()) { paramNames.add(entry.getValue().toString()); } Collections.sort(paramNames); StringBuilder paramStr = new StringBuilder(); for (String paramName : paramNames) { paramStr.append(paramName); } return paramStr.toString(); } // public static void main(String[] args) { // // String mw = "123qwe!@#"; // StringBuffer stringBuffer = new StringBuffer(); // // try { // String en = encrypt(mw); // StringBuffer append = stringBuffer.append(en); // System.out.println("加密" + append.toString());//w8RzmA/N1zPTRBKCYjoJgQ== // StringBuffer decrypt = decrypt(append.toString()); // System.out.println("解密" + decrypt);//123qwe!@# // } catch (Exception e) { // e.printStackTrace(); // } // // } }
注意事項
需要注意的是, 在獲取解密后的內容后是由StringBuffer接收的, 解密內容使用完畢需要將StringBuffer清空, 不得不說也太安全了...
StringBuffer清空方式有三種, 可參考如下方式:
// 清空sb sb.setLength(0);//或sb.delete(0,sb.length());或sb = new StringBuffer();
感謝