package com.nova.sankuai.domain.api.doudouqian; import com.alibaba.fastjson.JSONObject; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import java.security.Key; import java.security.KeyFactory; import java.security.MessageDigest; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.*; /** *

* 用于加密解密的各种工具集 *

* * @author Tiangle * @since 2022/4/26 **/ public class DdqSignUtil { /** * @param bizDataJson 业务数据 * @param channelCode 机构申请得到的渠道号 * @param publicKey 公钥 * @param md5Key MD5秘钥 * @return * @throws Exception */ public static String buildRequest(String bizDataJson, String channelCode, String publicKey, String md5Key) throws Exception { // aesKey String aesKey = DdqSignUtil.getRandom(16, true); // timeStamp String timestamp = System.currentTimeMillis() / 1000 + ""; // biz_data String bizEncryptData = DdqSignUtil.encrypt(bizDataJson, aesKey); // secretKey String secretKey = DdqSignUtil.encryptByPublicKey(aesKey, publicKey); Map sortMap = new HashMap<>(); sortMap.put("channel_code", channelCode); sortMap.put("timestamp", timestamp); sortMap.put("biz_data", bizEncryptData); sortMap.put("secret_key", secretKey); String sign = DdqSignUtil.createSign(sortMap, md5Key); // 构建请求参数 JSONObject params = new JSONObject(); params.put("sign", sign); params.put("secret_key", secretKey); params.put("biz_data", bizEncryptData); params.put("channel_code", channelCode); params.put("timestamp", timestamp); return params.toString(); } /** * 生成指定位数的随机字符串 * * @param length 长度 * @param useAlphabet 是否使用字母 * @return String */ public static String getRandom(int length, boolean useAlphabet) { StringBuffer buffer = new StringBuffer(); String s = "0123456789" + (useAlphabet ? "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" : ""); for (int i = 0; i < length; i++) { buffer.append(s.charAt(new Random().nextInt(s.length()))); } return buffer.toString(); } /** * AES 加密 * * @param content 待加密内容 * @param key 秘钥 * @return String 密文 * @throws Exception EX */ public static String encrypt(String content, String key) throws Exception { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES")); byte[] bytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); return Base64.encodeBase64String(bytes); } /** * AES 解密 * * @param encryptBytes 密文 * @param key 秘钥 * @return String 明文 * @throws Exception EX */ public static String decrypt(String encryptBytes, String key) throws Exception { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES")); byte[] decryptBytes = cipher.doFinal(Base64.decodeBase64(encryptBytes)); return new String(decryptBytes); } /** * 用公钥加密 * * @param value 要加密数据 * @param key 密钥 * @return byte[] * @throws Exception RSA异常 */ public static String encryptByPublicKey(String value, String key) throws Exception { byte[] data = getBytes(value); // 对公钥解密 byte[] keyBytes = Base64.decodeBase64(key); // 取公钥 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); // 对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return Base64.encodeBase64String(doFinalBySegment(cipher, data, true)); } /** * 获取字符串的字节数组 * * @param content 字符串 * @return byte[] */ public static byte[] getBytes(String content) { return content.getBytes(StandardCharsets.UTF_8); } private static byte[] doFinalBySegment(Cipher cipher, byte[] source, boolean isEncode) throws Exception { ByteArrayOutputStream out = null; try { int blockSize = isEncode ? 117 : 128; if (source.length <= blockSize) { return cipher.doFinal(source); } out = new ByteArrayOutputStream(); int offsetIndex = 0, offset = 0, sourceLength = source.length; while (sourceLength - offset > 0) { int size = Math.min(sourceLength - offset, blockSize); byte[] buffer = cipher.doFinal(source, offset, size); out.write(buffer, 0, buffer.length); offsetIndex++; offset = offsetIndex * blockSize; } return out.toByteArray(); } finally { IOUtils.closeQuietly(out); } } /** * MD5 Encrypt * * @param info 待加密字符串 * @return String * @throws Exception 加密异常 */ public static String md5Encrypt(String info) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(info.getBytes(StandardCharsets.UTF_8)); byte[] result = md5.digest(); StringBuffer buffer = new StringBuffer(); for (byte b : result) { String str = Integer.toHexString(b & 0xFF); if (str.length() == 1) { buffer.append("0"); } buffer.append(str); } return buffer.toString().toUpperCase(); } /** * 创建签名字符串 * * @param sortMap 用于创建签名的参数集合 * @param md5Key MD5加密秘钥 * @return * @throws Exception */ public static String createSign(Map sortMap, String md5Key) throws Exception { // 按ASCII码升序组成签名参数字符串 SortedMap sortedMap = new TreeMap(sortMap); Set set = sortedMap.keySet(); StringBuffer tempSign = new StringBuffer(); for (String o : set) { tempSign.append(o).append("=").append(sortedMap.get(o)); tempSign.append("&"); } tempSign.deleteCharAt(tempSign.length() - 1); // 获取加密签名字符串 String sign = md5Encrypt(tempSign + md5Key); return sign; } /** * 用私钥解密 * * @param value 密文 * @param key 密钥 * @return String * @throws Exception RSA异常 */ public static String decryptByPrivateKey(String value, String key) throws Exception { byte[] data = Base64.decodeBase64(value); // 对私钥解密 byte[] keyBytes = Base64.decodeBase64(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); // 对数据解密 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return getString(doFinalBySegment(cipher, data, false)); } /** * 转换字节数组为字符串 * * @param content 字节数组 * @return String */ public static String getString(byte[] content) { return new String(content, StandardCharsets.UTF_8); } /** * 查询参数 * * @param paramMap * @param name * @return String */ public static String getValue(Map paramMap, String name) { if (paramMap == null || paramMap.isEmpty() || StringUtils.isBlank(name) || !paramMap.containsKey(name)) { return null; } Object obj = paramMap.get(name); if (obj == null) { return null; } String value = obj.toString(); return value.trim(); } }