添加统一门户的身份证/手机号解密

This commit is contained in:
chenshaohua
2026-05-19 11:31:23 +08:00
parent 76e92fd8db
commit 3bfd80bee9

View File

@@ -0,0 +1,134 @@
package com.ruoyi.common.utils.encrypt;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
public class EncryptUtil {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
public static void main(String[] args) {
String appId = "cloud-9793ee8a8c3d47b8871007ffc4128502";
String appSecret = "Yi+NACK70UPg8rFvsnnfBUq1wcLD4nm6ilC4II/4C4k=";
String generatedIv = generateAppIV(appId);
String generatedKey = generateAppKey(appId, appSecret);
String data = "n+Rq0Y+quYHa9uL+EpWbuw==";
String str = decrypt(data, generatedIv, generatedKey);
System.err.println(str);
}
private static String generateAppIV(String appId) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashBytes = md.digest(appId.getBytes("UTF-8"));
// 直接使用字节数组转换确保精确的16字节
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++) {
String hex = Integer.toHexString(0xff & hashBytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString().substring(0, 16); // 确保正好16个字符
} catch (Exception e) {
throw new RuntimeException("IV生成失败", e);
}
}
private static String generateAppKey(String appId, String appSecret) {
try {
String combinedKey = appId + appSecret;
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = md.digest(combinedKey.getBytes("UTF-8"));
// 取前16字节作为AES密钥
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++) {
sb.append(Integer.toHexString((hashBytes[i] & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().substring(0, 16); // AES-128需要16字符密钥
} catch (Exception e) {
throw new RuntimeException("密钥生成失败", e);
}
}
public static String decrypt(String content, String iv, String key) {if(StringUtils.isEmpty(content)) {return "";}
iv = getIv( iv);
try {
byte[] decoded = Base64.decodeBase64(content);
byte[] decrypted = AES_CBC_Decrypt(decoded, iv, AES_normalizeKey(key));
String result = new String(decrypted, StandardCharsets.UTF_8);
// 清理可能的填充字符
result = result.trim();
if (result.endsWith("\0")) {
result = result.replaceAll("\\\\0+$", "");
}
// 处理JSON格式
String cleanResult = result.replaceAll("\"", "");
if (cleanResult.startsWith("{") && cleanResult.endsWith("}")) {
JSON parse = JSONUtil.parse(cleanResult);
return String.valueOf(parse);
} else {
return result;
}
} catch (Exception e) {
return "";
}
}
private static String getIv(String iv) {
return generateIV(iv);
}
private static String generateIV(String iv) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hashBytes = md.digest(iv.getBytes("UTF-8"));
// 直接使用字节数组转换确保精确的16字节
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 16; i++) {
String hex = Integer.toHexString(0xff & hashBytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString().substring(0, 16); // 确保正好16个字符
} catch (Exception e) {
throw new RuntimeException("IV生成失败", e);
}
}
/**
* AES CBC 解密
*/
private static byte[] AES_CBC_Decrypt(byte[] content, String iv, String key) throws Exception {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
return cipher.doFinal(content);
}
/**
* 规范化密钥长度为16位AES-128
*/
private static String AES_normalizeKey(String key) {
return key;
}
}