168 lines
6.0 KiB
Java
168 lines
6.0 KiB
Java
package com.xwad.os.utils;
|
||
|
||
import android.util.Base64;
|
||
import android.util.Log;
|
||
|
||
import java.nio.charset.StandardCharsets;
|
||
import java.security.GeneralSecurityException;
|
||
import java.security.spec.AlgorithmParameterSpec;
|
||
|
||
import javax.crypto.Cipher;
|
||
import javax.crypto.spec.IvParameterSpec;
|
||
import javax.crypto.spec.SecretKeySpec;
|
||
|
||
/**
|
||
* Android 对称加密解密工具类
|
||
* 支持 AES/DES/TripleDES + ECB/CBC/CFB/OFB/CTR + PKCS5Padding 等
|
||
*/
|
||
public class CryptoUtils {
|
||
/**
|
||
* 简化解密方法:仅需传入待解密字符串
|
||
*
|
||
* @param data 待解密的字符串
|
||
* @return 解密后的原文
|
||
* @throws Exception 解密异常
|
||
*/
|
||
public static String decrypt(String data) {
|
||
String KEY = JgyUtils.getAesKey();
|
||
String IV = JgyUtils.getAesIv();
|
||
|
||
try {
|
||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||
|
||
// 解码密钥
|
||
byte[] keyBytes = KEY.getBytes(StandardCharsets.UTF_8);
|
||
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
|
||
|
||
// 初始化Cipher
|
||
// 解码偏移量IV
|
||
byte[] ivBytes = IV.getBytes(StandardCharsets.UTF_8);
|
||
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
|
||
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
|
||
|
||
// 解码待解密数据
|
||
byte[] dataBytes = Base64.decode(data, Base64.DEFAULT);
|
||
|
||
// 执行解密并返回字符串
|
||
byte[] decryptBytes = cipher.doFinal(dataBytes);
|
||
return new String(decryptBytes, StandardCharsets.UTF_8);
|
||
} catch (GeneralSecurityException e) {
|
||
e.printStackTrace();
|
||
Log.e("CryptoUtils", "decrypt: " + e.getMessage());
|
||
}
|
||
return "";
|
||
}
|
||
|
||
/**
|
||
* 对称解密核心方法
|
||
*
|
||
* @param data 待解密的字符串
|
||
* @param type 加密类型:AES / DES / TRIPLEDES
|
||
* @param mode 模式:ECB / CBC / CFB / OFB / CTR
|
||
* @param pad 填充方式:PKCS5Padding / ISO10126Padding / NoPadding
|
||
* @param key 密钥字符串
|
||
* @param keyType 密钥编码:Utf8 / Base64 / Hex
|
||
* @param iv 偏移量(ECB模式无需)
|
||
* @param ivType 偏移量编码:Utf8 / Base64 / Hex
|
||
* @param isBase64 待解密数据编码:true=Base64 false=Hex
|
||
* @return 解密后的原始字符串
|
||
* @throws Exception 解密异常(密钥长度/算法不支持/数据错误等)
|
||
*/
|
||
public static String decrypt(
|
||
String data,
|
||
String type,
|
||
String mode,
|
||
String pad,
|
||
String key,
|
||
String keyType,
|
||
String iv,
|
||
String ivType,
|
||
boolean isBase64
|
||
) throws Exception {
|
||
// 1. 拼接算法全称
|
||
String algorithm = type + "/" + mode + "/" + pad;
|
||
Cipher cipher = Cipher.getInstance(algorithm);
|
||
|
||
// 2. 解码密钥(修复:== 改为 equals() 字符串值比较)
|
||
byte[] keyBytes;
|
||
if ("Hex".equals(keyType)) {
|
||
keyBytes = hex2Bytes(key);
|
||
} else if ("Base64".equals(keyType)) {
|
||
keyBytes = Base64.decode(key, Base64.DEFAULT);
|
||
} else {
|
||
// 强制指定UTF-8,避免乱码
|
||
keyBytes = key.getBytes(StandardCharsets.UTF_8);
|
||
}
|
||
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, type);
|
||
|
||
// 3. 初始化Cipher(ECB无IV,其他模式需要IV)
|
||
if ("ECB".equals(mode)) {
|
||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||
} else {
|
||
// 解码偏移量IV
|
||
byte[] ivBytes;
|
||
if ("Hex".equals(ivType)) {
|
||
ivBytes = hex2Bytes(iv);
|
||
} else if ("Base64".equals(ivType)) {
|
||
ivBytes = Base64.decode(iv, Base64.DEFAULT);
|
||
} else {
|
||
ivBytes = iv.getBytes(StandardCharsets.UTF_8);
|
||
}
|
||
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes);
|
||
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
|
||
}
|
||
|
||
// 4. 解码待解密数据
|
||
byte[] dataBytes;
|
||
if (isBase64) {
|
||
dataBytes = Base64.decode(data, Base64.DEFAULT);
|
||
} else {
|
||
dataBytes = hex2Bytes(data);
|
||
}
|
||
|
||
// 5. 执行解密 + 转字符串
|
||
byte[] decryptBytes = cipher.doFinal(dataBytes);
|
||
return new String(decryptBytes, StandardCharsets.UTF_8);
|
||
}
|
||
|
||
/**
|
||
* 全Android版本兼容的 Hex字符串 → 字节数组 解码
|
||
* 替代Apache Commons-Codec的Hex.decodeHex
|
||
*/
|
||
private static byte[] hex2Bytes(String hexStr) {
|
||
if (hexStr == null || hexStr.length() == 0) return new byte[0];
|
||
byte[] bytes = new byte[hexStr.length() / 2];
|
||
for (int i = 0; i < bytes.length; i++) {
|
||
int high = Character.digit(hexStr.charAt(2 * i), 16);
|
||
int low = Character.digit(hexStr.charAt(2 * i + 1), 16);
|
||
bytes[i] = (byte) (high << 4 | low);
|
||
}
|
||
return bytes;
|
||
}
|
||
|
||
// ------------------- 你的业务调用示例(直接复制到Android Activity/ViewModel中使用) -------------------
|
||
public static void testDecrypt() {
|
||
// 你的原始配置参数(完全不变)
|
||
String data = "88072p8780";
|
||
String type = "AES";
|
||
String mode = "CBC";
|
||
String pad = "PKCS5Padding";
|
||
String key = "fRW5b5FI4uG32HISvVZ40QFSkyvXYwP8";
|
||
String keyType = "Utf8";
|
||
String iv = "7COBgH2wUtJnPPSX";
|
||
String ivType = "Utf8";
|
||
boolean isBase64 = true;
|
||
|
||
try {
|
||
// 执行解密
|
||
String result = decrypt(data, type, mode, pad, key, keyType, iv, ivType, isBase64);
|
||
// 输出结果(Android中用Log.d,不要用System.out)
|
||
Log.d("Crypto", "解密结果:" + result);
|
||
} catch (Exception e) {
|
||
// 异常捕获(密钥错误/算法不支持/数据被篡改等)
|
||
e.printStackTrace();
|
||
Log.e("Crypto", "解密失败:" + e.getMessage());
|
||
}
|
||
}
|
||
|
||
} |