AES對稱加密工具Java實現,與iOS加密互通
阿新 • • 發佈:2019-01-07
使用者登陸的驗證資訊需要與前端互傳,採用一種簡單的加密手段。在開發過程中很快實現了與安卓的加密互通,但與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