1. 程式人生 > >AES對稱加密工具Java實現,與iOS加密互通

AES對稱加密工具Java實現,與iOS加密互通

使用者登陸的驗證資訊需要與前端互傳,採用一種簡單的加密手段。在開發過程中很快實現了與安卓的加密互通,但與ios的打通踩到個大坑, 詳見程式碼中的註釋和文後的連結。

有懷疑到加密位數的問題,java如果要使用256位的金鑰要修改基礎jar包,最終沒有采用。

(Java本身限制金鑰的長度最多128位,而AES256需要的金鑰長度是256位,因此需要到Java官網上下載一個Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。在Java SE的下載頁面下面的Additional Resources那裡會有下載連結。下載後開啟壓縮包,裡面有兩個jar檔案。把這兩個jar檔案解壓到JRE目錄下的lib/security資料夾,覆蓋原來的檔案。這樣Java就不再限制金鑰的長度了。)

package cipher;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;


public class AESCodeUtil {
	
	/**
	 * 金鑰,必須16位
	 */
	private static final String IV_STRING = "1234567890abcdef";
	private static Base64 base64 = new Base64();
	
	private static String encryptAES(String content, String key) 
            throws Exception {

	    byte[] byteContent = content.getBytes("UTF-8");
	
	    // 注意,為了能與 iOS 統一
	    // 這裡的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
	    byte[] enCodeFormat = key.getBytes();
	    SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
	
	    byte[] initParam = IV_STRING.getBytes();
	    IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
	
	    // 指定加密的演算法、工作模式和填充方式
	    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
	
	    byte[] encryptedBytes = cipher.doFinal(byteContent);
	
	    return new String(base64.encode(encryptedBytes));
	}
	
	private static String decryptAES(String content, String key) 
            throws Exception {

		byte[] encryptedBytes = base64.decode(content);
	
	    byte[] enCodeFormat = key.getBytes();
	    SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
	
	    byte[] initParam = IV_STRING.getBytes();
	    IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
	
	    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	    cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
	
	    byte[] result = cipher.doFinal(encryptedBytes);
	
	    return new String(result, "UTF-8");
	}
	
	/**
	 * 用於加密
	 * @param content
	 * @return
	 */
	public static String base64convert(String content){
		String str1 = content.replaceAll("/", "_");
		return str1.replaceAll("\\+", "-");
	}
	
	/**
	 * 用於解密
	 * @param content
	 * @return
	 */
	public static String base64convert2(String content){
		String str1 = content.replaceAll("-", "\\+");
		return str1.replaceAll("_", "/");
	}
	
	private static String encode(String content, String key){
		try {
			return base64convert(encryptAES(content,key));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private static String decode(String content, String key){
		try {
			return decryptAES(base64convert2(content), key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static String decode(String code){
		return decode(code,IV_STRING);
	}
	
	public static String encode(String code){
		return encode(code,IV_STRING);
	}
	
	public static void main(String[] args) {
		String content = "code_12345678901234567890";
		String coded = encode(content);
		System.out.println("密文:" + coded);
		String origin = decode(coded);
		System.out.println("原文:" + origin);
	}
	
}

另附兩個別人踩坑的經歷

http://dditblog.com/itshare_603.html

http://www.cnblogs.com/mantgh/p/4244891.html