|
|
@@ -0,0 +1,294 @@
|
|
|
+package com.fs.until;
|
|
|
+
|
|
|
+import cn.hutool.http.HttpException;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fs.common.core.domain.AjaxResult;
|
|
|
+import com.fs.common.utils.ParseUtils;
|
|
|
+import com.fs.common.utils.StringUtils;
|
|
|
+import com.fs.system.domain.SysConfig;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import javax.crypto.Cipher;
|
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
|
+import java.util.Base64;
|
|
|
+
|
|
|
+import static com.fs.common.core.domain.AjaxResult.CODE_TAG;
|
|
|
+import static com.fs.common.core.domain.AjaxResult.DATA_TAG;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class PhoneUtil {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 2025-9-3 需求替换新 key
|
|
|
+ */
|
|
|
+ private static String OLD_KEY = "2c8d1a7f4e9b3c6ae6d5c4b3a291f8c9";
|
|
|
+
|
|
|
+ private static String USE_KEY = "AESAabCdeREssREA";
|
|
|
+
|
|
|
+
|
|
|
+ //外部刷新方法
|
|
|
+ public static void refreshKeyExternal(SysConfig config) {
|
|
|
+ String configValue = config.getConfigValue();
|
|
|
+ if (null != configValue) {
|
|
|
+ JSONObject jsonObject = JSON.parseObject(configValue);
|
|
|
+ if (jsonObject.containsKey("useKey") && jsonObject.containsKey("oldKey")) {
|
|
|
+ USE_KEY = jsonObject.getString("useKey");
|
|
|
+ OLD_KEY = jsonObject.getString("oldKey");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加密
|
|
|
+ */
|
|
|
+ public static String encryptPhone(String text) {
|
|
|
+
|
|
|
+ try {
|
|
|
+ String encryptedText = null;
|
|
|
+ String url = "http://42.194.147.226:8000/app/common/genEncryption";
|
|
|
+ // 构建请求体 JSON
|
|
|
+ JSONObject jsonBody = new JSONObject();
|
|
|
+ jsonBody.put("content", text);
|
|
|
+
|
|
|
+ String result = HttpRequest.post(url).body(jsonBody.toString()).execute().body();
|
|
|
+ //解析返回
|
|
|
+ AjaxResult ajaxResult = JSONUtil.toBean(result, AjaxResult.class);
|
|
|
+
|
|
|
+ //取值返回参数
|
|
|
+ Object codeValue = ajaxResult.get(CODE_TAG);
|
|
|
+ Object dataValue = ajaxResult.get(DATA_TAG);
|
|
|
+
|
|
|
+ //判断是否成功
|
|
|
+ if ("200".equals(String.valueOf(codeValue))) {
|
|
|
+ encryptedText = String.valueOf(dataValue);
|
|
|
+ } else {
|
|
|
+ log.error("请求失败,状态码: " + codeValue);
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return encryptedText;
|
|
|
+ } catch (HttpException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解密
|
|
|
+ */
|
|
|
+ public static String decryptPhone(String encryptedText) {
|
|
|
+
|
|
|
+ try {
|
|
|
+ String text = null;
|
|
|
+ String url = "http://42.194.147.226:8000/app/common/genDecryption";
|
|
|
+ // 构建请求体 JSON
|
|
|
+ JSONObject jsonBody = new JSONObject();
|
|
|
+ jsonBody.put("content", encryptedText);
|
|
|
+
|
|
|
+ String result = HttpRequest.post(url).body(jsonBody.toString()).execute().body();
|
|
|
+ //解析返回
|
|
|
+ AjaxResult ajaxResult = JSONUtil.toBean(result, AjaxResult.class);
|
|
|
+
|
|
|
+ //取值返回参数
|
|
|
+ Object codeValue = ajaxResult.get(CODE_TAG);
|
|
|
+ Object dataValue = ajaxResult.get(DATA_TAG);
|
|
|
+
|
|
|
+ //判断是否成功
|
|
|
+ if ("200".equals(String.valueOf(codeValue))) {
|
|
|
+ text = String.valueOf(dataValue);
|
|
|
+ } else {
|
|
|
+ log.error("请求失败,状态码: " + codeValue);
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ } catch (HttpException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用于查询 使用老的数据加密
|
|
|
+ *
|
|
|
+ * @param text
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String encryptPhoneOldKey(String text) {
|
|
|
+ String encryptedText = null;
|
|
|
+ try {
|
|
|
+ SecretKeySpec secretKey = new SecretKeySpec(OLD_KEY.getBytes(), "AES");
|
|
|
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
|
|
+ // Encryption
|
|
|
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
|
|
+ byte[] encryptedBytes = cipher.doFinal(text.getBytes());
|
|
|
+ encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return encryptedText;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ public static void main(String[] args) {
|
|
|
+
|
|
|
+ String text = null;
|
|
|
+ String url = "http://172.16.0.114:8000/app/common/genEncryption";
|
|
|
+ // 构建请求体 JSON
|
|
|
+ JSONObject jsonBody = new JSONObject();
|
|
|
+ jsonBody.put("content", "17749925835");
|
|
|
+
|
|
|
+ String result = HttpRequest.post(url)
|
|
|
+ .body(jsonBody.toString())
|
|
|
+ .execute()
|
|
|
+ .body();
|
|
|
+ AjaxResult ajaxResult = JSONUtil.toBean(result, AjaxResult.class);
|
|
|
+ System.out.println("完整响应: " + ajaxResult);
|
|
|
+
|
|
|
+ Object codeValue = ajaxResult.get(CODE_TAG);
|
|
|
+ Object dataValue = ajaxResult.get(DATA_TAG);
|
|
|
+
|
|
|
+ System.out.println("code原始值: '" + codeValue + "'");
|
|
|
+ System.out.println("data原始值: '" + dataValue + "'");
|
|
|
+
|
|
|
+ // 使用 String.valueOf 确保类型安全
|
|
|
+ if ("200".equals(String.valueOf(codeValue))) {
|
|
|
+ text = String.valueOf(dataValue);
|
|
|
+ System.out.println("加密结果: " + text);
|
|
|
+ } else {
|
|
|
+ System.out.println("请求失败,状态码: " + codeValue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解密加*
|
|
|
+ */
|
|
|
+ public static String decryptPhoneMk(String encryptedText) {
|
|
|
+ String text = null;
|
|
|
+ try {
|
|
|
+ text = decryptPhone(encryptedText);
|
|
|
+ text = text.replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("decryptPhoneMk 解密失败 text: {}, msg: {}", encryptedText, e.getMessage(), e);
|
|
|
+ text = encryptedText;
|
|
|
+ }
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String decryptAutoPhoneMk(String encryptedText) {
|
|
|
+ String text = null;
|
|
|
+ if (encryptedText != null && encryptedText != "") {
|
|
|
+ if (encryptedText.length() > 11) {
|
|
|
+ try {
|
|
|
+ text = decryptPhone(encryptedText);
|
|
|
+ text = text.replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("decryptAutoPhoneMk 解密失败 text: {}, msg: {}", encryptedText, e.getMessage(), e);
|
|
|
+ text = encryptedText;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ text = ParseUtils.parsePhone(encryptedText);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 手机号加密 *
|
|
|
+ *
|
|
|
+ * @param text 手机号
|
|
|
+ * @return 加密后手机号
|
|
|
+ */
|
|
|
+ public static String hiddenPhone(String text) {
|
|
|
+ if (StringUtils.isBlank(text)) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ return "***********";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 显示前3位
|
|
|
+ *
|
|
|
+ * @param text 手机号
|
|
|
+ * @return 加密后手机号
|
|
|
+ */
|
|
|
+ public static String displayPre3Phone(String text) {
|
|
|
+ if (StringUtils.isBlank(text)) {
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ text = text.trim();
|
|
|
+ if (text.length() > 11) {
|
|
|
+ text = decryptPhone(text);
|
|
|
+ }
|
|
|
+
|
|
|
+ return text.replaceAll("(\\d{3})\\d*", "$1********");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断文本中是否存在手机号
|
|
|
+ *
|
|
|
+ * @param text 原始文本
|
|
|
+ * @return 是否存在手机号
|
|
|
+ */
|
|
|
+ private static boolean containsPhoneNumber(String text) {
|
|
|
+ if (text == null || text.trim().isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 手机号正则
|
|
|
+ String phoneRegex = "1[3-9]\\d{9}";
|
|
|
+ java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(phoneRegex);
|
|
|
+ java.util.regex.Matcher matcher = pattern.matcher(text);
|
|
|
+
|
|
|
+ return matcher.find();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final String PUBLIC_KEY_STR = "ylrz112233";
|
|
|
+
|
|
|
+ /**
|
|
|
+ * XOR 加密(返回 Base64)(对于解析后的电话明文加密,适用于前端解密)
|
|
|
+ *
|
|
|
+ * @param data 明文电话
|
|
|
+ * @return String 密文
|
|
|
+ */
|
|
|
+ public static String xorEncrypt(String data) {
|
|
|
+ byte[] dataBytes = data.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
|
|
+ byte[] keyBytes = PUBLIC_KEY_STR.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
|
|
+ byte[] result = new byte[dataBytes.length];
|
|
|
+ for (int i = 0; i < dataBytes.length; i++) {
|
|
|
+ result[i] = (byte) (dataBytes[i] ^ keyBytes[i % keyBytes.length]);
|
|
|
+ }
|
|
|
+ return Base64.getEncoder().encodeToString(result);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * XOR 解密
|
|
|
+ *
|
|
|
+ * @param base64Str Base64 编码的密文
|
|
|
+ * @param privateKey 私钥字符串(如 "ylrz987654321")
|
|
|
+ * @return 解密后的明文字符串
|
|
|
+ */
|
|
|
+ public static String xorDecrypt(String base64Str, String privateKey) {
|
|
|
+ // 1. Base64 解码为字节数组
|
|
|
+ byte[] encryptedBytes = Base64.getDecoder().decode(base64Str);
|
|
|
+ // 2. 私钥字符串转字节数组(UTF-8 编码)
|
|
|
+ byte[] keyBytes = privateKey.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
|
|
+ // 3. 逐字节异或
|
|
|
+ byte[] resultBytes = new byte[encryptedBytes.length];
|
|
|
+ for (int i = 0; i < encryptedBytes.length; i++) {
|
|
|
+ resultBytes[i] = (byte) (encryptedBytes[i] ^ keyBytes[i % keyBytes.length]);
|
|
|
+ }
|
|
|
+ // 4. 将字节数组按 UTF-8 解码为字符串
|
|
|
+ return new String(resultBytes, java.nio.charset.StandardCharsets.UTF_8);
|
|
|
+ }
|
|
|
+}
|