同理先在类中定义一个初始向量,需要与 iOS 端的统一。
private static final String IV_STRING = "16-Bytes--String";
另 Java 不需手动设置密钥大小,系统会自动根据传入的 Key 进行判断。
先引入必要的包:
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
加密方法
public static String encryptAES(String content, String key)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, UnsupportedEncodingException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
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);
// 同样对加密后数据进行 base64 编码
Base64.Encoder encoder = Base64.getEncoder();
return encoder.encodeToString(encryptedBytes);
}
解密方法
public static String decryptAES(String content, String key)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
// base64 解码
Base64.Decoder decoder = Base64.getDecoder();
byte[] encryptedBytes = decoder.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");
}
注意以上实现的是 AES-128,因此方法传入的 key 需为长度为 16 的字符串。
关于Java使用大于128 bits的key
到 Oracle 官网下载对应 Java 版本的 JCE ,解压后放到 JAVA_HOME/jre/lib/security/
,然后修改 iOS 端的 kKeySize 和两端对应的 key 即可。
【代码下载】
AESCipher-Java
AES4ObjC-Java-JavaScript/Java/src/