赞
踩
公司要新增一个dmz网关,网关中已经有源码部分,可以点击查看。此处为整理方便直接查看。具体需求为外部进入数据需要加密解密,使用AES与RSA进行加密解密,具体过程如下
AES工具类
package cn.git.dmz.util; import cn.git.common.exception.ServiceException; import cn.git.dmz.constants.DmzConstants; import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; /** * @description: AES加解密工具类 * @program: bank-credit-sy * @author: lixuchun * @create: 2024-01-05 08:52:41 */ @Component @Slf4j public class AESUtil { @Autowired private LogUtil logUtil; /** * 获取随机AES密钥 * @return 返回加密秘钥 */ public SecretKey getRandomKey() { // 使用种子生成种子随机秘钥,如果想每一次都生成不同秘钥,则去掉种子即可 SecureRandom secureRandom = new SecureRandom(DmzConstants.DMZ_LOCK_KEY.getBytes(StandardCharsets.UTF_8)); // 实例 KeyGenerator kg = null; try { kg = KeyGenerator.getInstance(DmzConstants.AES_TYPE); // AES kg.init(DmzConstants.KEY_SIZE, secureRandom); // 生成密钥 SecretKey secretKey = kg.generateKey(); return secretKey; } catch (NoSuchAlgorithmException e) { String errorMsg = logUtil.getStackTraceInfo(e, DmzConstants.NUM_2000); log.error(errorMsg); throw new ServiceException("获取随机AES密钥失败"); } } /** * 加密 * * @param content 内容 * @param randomPassKey 秘钥 * @return 加密后的数据 */ public String aesEncrypt(String content, String randomPassKey) { try { // 新建Cipher 类 Cipher cipher = Cipher.getInstance(DmzConstants.AES_MODE); // 初始化秘钥 SecretKeySpec sks = new SecretKeySpec(Base64.getDecoder().decode(randomPassKey), DmzConstants.AES_TYPE); // 初始化加密类 cipher.init(Cipher.ENCRYPT_MODE, sks); // 进行加密 byte[] encrypt = cipher.doFinal(content.getBytes()); // 进行base64编码 encrypt = Base64.getEncoder().encode(encrypt); // 转成字符串返回 return new String(encrypt, StandardCharsets.UTF_8); } catch (Exception e) { String errorMsg = logUtil.getStackTraceInfo(e, DmzConstants.NUM_2000); log.error(errorMsg); throw new ServiceException("AES加密失败"); } } /** * AES进行解密数据 * * @param content 解密内容 * @param randomPassKey aes随机秘钥 * @return 解密后数据 */ public String aesDecrypt(String content, String randomPassKey) { try { // base64里会携带换行符导致解码失败,替换base64里的换行 content = content.replaceAll("[\\n\\r]", StrUtil.EMPTY); // base64 解码,跟上面的编码对称 byte[] data = Base64.getDecoder().decode(content.getBytes(StandardCharsets.UTF_8)); // 新建Cipher 类 Cipher cipher = Cipher.getInstance(DmzConstants.AES_MODE); // 初始化秘钥 SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(randomPassKey), DmzConstants.AES_TYPE); // 初始化类 cipher.init(Cipher.DECRYPT_MODE, keySpec); // 进行AES byte[] result = cipher.doFinal(data); // 返回解密后内容信息 return new String(result); } catch (Exception e) { String errorMsg = logUtil.getStackTraceInfo(e, DmzConstants.NUM_2000); log.error(errorMsg); throw new ServiceException("AES解密失败"); } } /** * 将byte数组转换成16进制String * @param bytes 转换的byte数组 * @return 16进制字符串 */ public String parseBytesToHexStr(byte[] bytes) { StringBuilder stringBuilder = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(b & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } stringBuilder.append(hex.toUpperCase()); } return stringBuilder.toString(); } /** * 将16进制String转换为byte数组 * @param hexStr 16进制字符串 * @return 2进制byte数组 */ public byte[] parseHexStrToBytes(String hexStr) { // 空值判断 if (hexStr.length() < 1) { return null; } byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / DmzConstants.NUM_2; i++) { int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); result[i] = (byte) (high * 16 + low); } return result; } }
RSA工具类
package cn.git.dmz.util; import cn.git.common.exception.ServiceException; import cn.git.dmz.constants.DmzConstants; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; /** * @description: RSA加解密工具类 * @program: bank-credit-sy * @author: lixuchun * @create: 2024-01-05 08:58:58 */ @Component @Slf4j public class RSAUtil { @Autowired private LogUtil logUtil; /** * RSA初始化key pair,初始化公钥私钥方法 * @return KeyPair */ public KeyPair getRSAKeyPair() { try { // 生成RSA密钥对 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(DmzConstants.RSA_TYPE); // 根据种子生成秘钥对 SecureRandom secureRandom = new SecureRandom(DmzConstants.DMZ_LOCK_KEY.getBytes(StandardCharsets.UTF_8)); keyGen.initialize(DmzConstants.NUM_1024, secureRandom); return keyGen.generateKeyPair(); } catch (Exception e) { String errorMsg = logUtil.getStackTraceInfo(e, DmzConstants.NUM_2000); log.error(errorMsg); throw new ServiceException("RSA初始化keyPairs失败"); } } /** * RSA加密 * @param data 待加密数据 * @param publicKeyStr 公钥 * @return 加密后的数据 */ public String encryptRSA(String data, String publicKeyStr) { try { byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr); // 初始化公钥key X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(DmzConstants.RSA_TYPE); PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); // 使用公钥进行加密 Cipher encryptCipher = Cipher.getInstance(DmzConstants.RSA_MODE); encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = encryptCipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptedBytes); } catch (Exception e) { String errorMsg = logUtil.getStackTraceInfo(e, DmzConstants.NUM_2000); log.error(errorMsg); throw new ServiceException("RSA加密失败"); } } /** * 进行RSA解密 * @param content 解密文本 * @param privateKeyStr 私钥字符串 * @return */ public String decryptRSA(String content, String privateKeyStr) { try { byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr); // 初始化私钥 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(DmzConstants.RSA_TYPE); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 使用私钥进行解密 Cipher decryptCipher = Cipher.getInstance(DmzConstants.RSA_MODE); decryptCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(content)); return new String(decryptedBytes, StandardCharsets.UTF_8); } catch (Exception e) { String errorMsg = logUtil.getStackTraceInfo(e, DmzConstants.NUM_2000); log.error(errorMsg); throw new ServiceException("RSA解密失败"); } } }
测试类则是没有封装成util的方法,进行需求进行简单开发的逻辑代码,可以直接运行,注意如果要自己使用,修改自己的秘钥。
package cn.git.demo.contract; import cn.git.common.constant.CommonConstant; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import com.alibaba.fastjson.JSONObject; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * a11111密码初始化类 * 密码初始化 */ public class TestEncodePassword { /** * 外部系统请求网关加密密匙 */ public static final String DMZ_LOCK_KEY = "DMZ:XdXt:loan==,"; /** * AES * 算法名称/加密模式/数据填充方式 */ public static String MODE = "AES/ECB/PKCS5Padding"; /** * RSA * 算法名称/加密模式/数据填充方式 */ private final static String RSA_MODE = "RSA/ECB/PKCS1Padding"; /** * 加密模式 */ public static String KEY_ALGORITHM = "AES"; /** * 加密单位长度 */ private static final int KEY_SIZE = 128; /** * RSA公钥 */ private static final String RSA_PUB_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMZ/Q5CIvZjBTLD4sTwxbWYNNZWd7rImD+sAgwOAf+nH1vWN+Qk63iBGQYHzYK5EhSAFqsqX04lsTiJUH42YRJ9yIXUnvd6Osp2JYOXW8WTGgMtfDJp5WzbYzJRxQ0RmJNcfqMcHPVepgpjs2HNj59aTqNPLdiouRSRlh2E0umGwIDAQAB"; /** * RSA私钥 */ private static final String RSA_PRI_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIxn9DkIi9mMFMsPixPDFtZg01lZ3usiYP6wCDA4B/6cfW9Y35CTreIEZBgfNgrkSFIAWqypfTiWxOIlQfjZhEn3IhdSe93o6ynYlg5dbxZMaAy18MmnlbNtjMlHFDRGYk1x+oxwc9V6mCmOzYc2Pn1pOo08t2Ki5FJGWHYTS6YbAgMBAAECgYEAiQRNNXccmsDz7bGOZEumtrAor/Je8xFKnGCGrR+Q1aw7UHTnPvyO3JiyYUPcBkb+OF+2HPcNhzLCkXoQZltGlznwOwGvHl4qEheVAMwdgijuYQZpsiGQyVyr4C506ydoPjPXbWD+9GGLuakHtIlRP9FAGvwQe/5fkUYsiAJD8mkCQQDop8hxDCrsH9eBQ7PusaGjmW213zmX0O5yAntwuznX3zsQOo+AgeM00ottF4J5BXWCeyF5ZxKi6WoPjSgTw77fAkEAmn6QNwMSEbcWHbuaC3ofjcYhnOl47aQWNr+56G+Wc7vs4xs8PXdd3sVmlepOFSdJLWCxguUBO60Dg6cpnAFMRQJABZLPaHXkKVfx77TRgKxctPCeAjdgx9RHgg+xKVgy4IsGfTMJ8Qgriz5n/KsNgxywXfnZKXFgrupskgbNqPuNfQJAQlOjxnpi/4gCzrED6Xl8onk1ZRA3Ao83mjmlrsx5YyaDBN1kd18PxdwptqLo8tvy5rBkhTWb2erlX1gc3QURoQJABakHaa+GNmKyc7pasJHQ3HMR39k888TQPKEQiE461oc5//Cyqek7u91rCG0HR7O4Hk+ostH9lkxc4bG+HYgWgg=="; public static void main(String[] args) throws Exception { testAES(); } /** * AES加解密,RES加密 * 1.生成需要发送的交易请求明文报文JSON格式 * 2.生成sign签名:MD5(sysid|transtime|md5key),并将生成的sign签名放入明文报文的JSON报文中 * 3.生成AES随机密钥:Byte[] = getRandomKey(随机加密串) * 4.将随机密钥由二进制转为16进制:byteToHexString(AES随机密钥) * 5.使用AES随机密钥对报文明文进行加密:message=aesEncrypt(报文明文) * 6.使用RSA公钥对随机密钥进行加密,signature=BASE64.encode(RSAPublicEnc(16进制AES密钥)) 此时,将计算得出的message字段以及signature字段以post的方式发送至数字信贷平台。 */ private static void testAES() throws Exception { // 生成测试数据 String username = "331326"; String passowrd = "a11111"; List<String> userList = new ArrayList<>(); userList.add("赵六6.使用RSA公钥对随机密钥进行加密,signature=BASE64.encode(RSAPublicEnc(16进制AES密钥)) 此时,将计算得出的message字段以及signature字段以post的方式发送至数字信贷平台。"); userList.add("赵76.使用RSA公钥对随机密钥进行加密,signature=BASE64.encode(RSAPublicEnc(16进制AES密钥)) 此时,将计算得出的message字段以及signature字段以post的方式发送至数字信贷平台。"); userList.add("赵86.使用RSA公钥对随机密钥进行加密,signature=BASE64.encode(RSAPublicEnc(16进制AES密钥)) 此时,将计算得出的message字段以及signature字段以post的方式发送至数字信贷平台。"); // 测试数据生成需要发送的交易请求明文报文JSON格式 JSONObject jsonObject = new JSONObject(); jsonObject.put("username", username); jsonObject.put("password", passowrd); jsonObject.put("userList", userList); String jsonMessage = jsonObject.toJSONString(); // 获取随机加密私钥key Key privateRandomAESKey = getRandomKey(); // 随机加密串 String privateRandomAESKeyStr = Base64.getEncoder().encodeToString(privateRandomAESKey.getEncoded()); System.out.println("AES随机密钥 -> : " + privateRandomAESKeyStr); // 将随机密钥由二进制转为16进制:byteToHexString(AES随机密钥) String hexPassKey = parseByte2HexStr(privateRandomAESKey.getEncoded()); System.out.println("AES十六进制hexPassKey -> : " + hexPassKey); // 获取RSA公钥和私钥 KeyPair keyPair = generatorKey(); String aesPublicKey = RSA_PUB_KEY; String aesPrivateKey = RSA_PRI_KEY; if (StrUtil.isBlank(aesPublicKey)) { aesPublicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()); } if (StrUtil.isBlank(aesPrivateKey)) { aesPrivateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()); } System.out.println("RSA公钥为 -> : " + aesPublicKey); System.out.println("RSA私钥为 -> : " + aesPrivateKey); // RSA对16进制key进行加密 String signature = encryptRSA(hexPassKey, aesPublicKey); System.out.println("RSA加密signature为 -> : " + signature); // 使用随机秘钥AES加密message信息 String encodeMessage = encrypt(jsonMessage, privateRandomAESKeyStr); System.out.println("AES加密message为 -> : " + encodeMessage); // 解密signature生成16进制字符串AES秘钥 String decodeHexPassKey = decryptRSA(signature, aesPrivateKey); System.out.println("RSA解密signature为 -> : " + decodeHexPassKey); // 解密16进制字符串AES秘钥 byte[] aesRandomKeyBytes = parseHexStr2Byte(decodeHexPassKey); System.out.println("AES获取秘钥为 -> : " + Base64.getEncoder().encodeToString(aesRandomKeyBytes)); // 使用 signature 解密message数据 String decodeMessage = decrypt(encodeMessage, Base64.getEncoder().encodeToString(aesRandomKeyBytes)); System.out.println("AES解密message为 -> : " + decodeMessage); } /** * 获取密钥 * * @return * @throws Exception */ private static SecretKey getRandomKey() throws Exception { // 随机数 SecureRandom secureRandom = new SecureRandom(DMZ_LOCK_KEY.getBytes(StandardCharsets.UTF_8)); // 实例 KeyGenerator kg = KeyGenerator.getInstance("AES"); // AES kg.init(KEY_SIZE, secureRandom); // 生成密钥 SecretKey secretKey = kg.generateKey(); return secretKey; } /** * 将byte数组转换成16进制String * @param buf * @return */ public static String parseByte2HexStr(byte[] buf) { StringBuffer sb = new StringBuffer(); for (byte b : buf) { String hex = Integer.toHexString(b & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } /** * 将16进制String转换为byte数组 * @param hexStr * @return */ public static byte[] parseHexStr2Byte(String hexStr) { if (hexStr.length() < 1) return null; byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) { int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); result[i] = (byte) (high * 16 + low); } return result; } /** * 加密 * * @param content 内容 * @param randomPassKey 秘钥 * @return 加密后的数据 */ public static String encrypt(String content, String randomPassKey) throws Exception { // 新建Cipher 类 Cipher cipher = Cipher.getInstance(MODE); // 初始化秘钥 SecretKeySpec sks = new SecretKeySpec(Base64.getDecoder().decode(randomPassKey), KEY_ALGORITHM); // 初始化加密类 cipher.init(Cipher.ENCRYPT_MODE, sks); // 进行加密 byte[] encrypt = cipher.doFinal(content.getBytes()); // 这一步非必须,是因为二进制数组不方便传输,所以加密的时候才进行base64编码 encrypt = Base64.getEncoder().encode(encrypt); // 转成字符串返回 return new String(encrypt, StandardCharsets.UTF_8); } /** * 解密数据 * * @param content 内容 * @param randomPassKey 秘钥 * @return 数据 */ public static String decrypt(String content, String randomPassKey) throws Exception{ // 替换base64里的换行,这一步也非必须,只是有些情况base64里会携带换行符导致解码失败 content = content.replaceAll("[\\n\\r]", ""); // base64 解码,跟上面的编码对称 byte[] data = Base64.getDecoder().decode(content.getBytes(StandardCharsets.UTF_8)); // 新建Cipher 类 Cipher cipher = Cipher.getInstance(MODE); // 初始化秘钥 SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(randomPassKey), KEY_ALGORITHM); // 初始化类 cipher.init(Cipher.DECRYPT_MODE, keySpec); // 解密 byte[] result = cipher.doFinal(data); // 返回解密后的内容 return new String(result); } /** * RSA初始化key pair * @return KeyPair */ private static KeyPair generatorKey() throws NoSuchAlgorithmException { // 生成RSA密钥对 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(DMZ_LOCK_KEY.getBytes(StandardCharsets.UTF_8)); keyGen.initialize(1024, secureRandom); KeyPair pair = keyGen.generateKeyPair(); return pair; } /** * RSA加密 * @param data 待加密数据 * @param publicKeyStr 公钥 * @return 加密后的数据 */ private static String encryptRSA(String data, String publicKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException { byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr); // 初始化公钥key X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509KeySpec); // 使用公钥进行加密 Cipher encryptCipher = Cipher.getInstance(RSA_MODE); encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = encryptCipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptedBytes); } /** * RSA解密 * @param data * @param privateKeyStr * @return */ private static String decryptRSA(String data, String privateKeyStr) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException { byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr); // 初始化私钥 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec); // 使用私钥进行解密 Cipher decryptCipher = Cipher.getInstance(RSA_MODE); decryptCipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(data)); return new String(decryptedBytes, "UTF-8"); } }
测试结果展示如下
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。