Browse Source

后端加密修改为sm2和sm4

ai_300
zhouhaibin 2 months ago
parent
commit
a73cce8cc1
  1. 10
      ruoyi-admin/src/main/resources/application.yml
  2. 6
      ruoyi-common/ruoyi-common-encrypt/pom.xml
  3. 14
      ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java
  4. 10
      ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java
  5. 92
      ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java
  6. 69
      ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/SM4Util.java
  7. 3
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ModelPrompts.java

10
ruoyi-admin/src/main/resources/application.yml

@ -160,7 +160,7 @@ mybatis-encryptor:
# 是否开启加密
enable: false
# 默认加密算法
algorithm: BASE64
algorithm: SM4
# 编码方式 BASE64/HEX。默认BASE64
encode: BASE64
# 安全秘钥 对称算法的秘钥 如:AES,SM4
@ -177,12 +177,12 @@ api-decrypt:
headerFlag: encrypt-key
# 响应加密公钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换
# 对应前端解密私钥 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ==
# publicKey: MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE33S12uP/J5rMPVYuHqbuCA7OWElC60egKvWya55YHc+56PGz5WH+/IOeLXpQ+NZ5mAqRgA/a1f0DdhHRmz87Dw==
# publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ==
publicKey: 04f41b6910c3ad0edbd184cc0fdefc1b6cd2a8e6b3cad6ad01f412d86fdd9895079cea172828dd34376347fbb527eced9d71d0c1c68971c56e671cdb43d9920942
# 请求解密私钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换
# 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=
# privateKey: MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgLzTaqeTg5aZSOuVLi+PVy7GauNpAlXdoARCtJOxMK5agCgYIKoEcz1UBgi2hRANCAASxU+uTFpJlHdv+Bhkl5EuYJTfhRkt4FxRULyN0Lf+xYecST0F1WWPmazvX3WR6mXTCIAgt5jQG8OjxyhCkKDEx
# privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=
privateKey: 00bb2ea7a18607f85b0dc4939fcebba1cb0efd1f674f8e9a4e85e1db0d53a5988e
springdoc:
api-docs:

6
ruoyi-common/ruoyi-common-encrypt/pom.xml

@ -26,7 +26,11 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
</dependency>
<dependency>
<groupId>com.antherd</groupId>
<artifactId>sm-crypto</artifactId>
<version>0.3.2.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>

14
ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/DecryptRequestBodyWrapper.java

@ -26,16 +26,20 @@ public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {
public DecryptRequestBodyWrapper(HttpServletRequest request, String privateKey, String headerFlag) throws IOException {
super(request);
// 获取 AES 密码 采用 RSA 加密
// 获取 sm4 密码 采用 RSA 加密
String headerRsa = request.getHeader(headerFlag);
String decryptAes = EncryptUtils.decryptByRsa(headerRsa, privateKey);
// 解密 AES 密码
// String decryptAes = EncryptUtils.decryptByRsa(headerRsa, privateKey);
String decryptAes = EncryptUtils.decryptBySm2(headerRsa, privateKey);
// 解密 sm4 密码
String aesPassword = EncryptUtils.decryptByBase64(decryptAes);
request.setCharacterEncoding(Constants.UTF8);
byte[] readBytes = IoUtil.readBytes(request.getInputStream(), false);
String requestBody = new String(readBytes, StandardCharsets.UTF_8);
// 解密 body 采用 AES 加密
String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword);
// 解密 body 采用 sm4 加密
// String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword);
String decryptBody = EncryptUtils.decryptBySm4(requestBody, aesPassword);
body = decryptBody.getBytes(StandardCharsets.UTF_8);
}

10
ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/filter/EncryptResponseBodyWrapper.java

@ -6,6 +6,7 @@ import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.dromara.common.encrypt.utils.SM4Util;
import java.io.*;
import java.nio.charset.StandardCharsets;
@ -69,11 +70,14 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {
*/
public String getEncryptContent(HttpServletResponse servletResponse, String publicKey, String headerFlag) throws IOException {
// 生成秘钥
String aesPassword = RandomUtil.randomString(32);
// String aesPassword = RandomUtil.randomString(16);
String aesPassword = SM4Util.generateKey();
// 秘钥使用 Base64 编码
String encryptAes = EncryptUtils.encryptByBase64(aesPassword);
// Rsa 公钥加密 Base64 编码
String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);
// String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey);
String encryptPassword = EncryptUtils.encryptBySm2Hex(encryptAes, publicKey);
// 设置响应头
servletResponse.addHeader("Access-Control-Expose-Headers", headerFlag);
@ -85,7 +89,7 @@ public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper {
// 获取原始内容
String originalBody = this.getContent();
// 对内容进行加密
return EncryptUtils.encryptByAes(originalBody, aesPassword);
return EncryptUtils.encryptBySm4(originalBody, aesPassword);
}
@Override

92
ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/EncryptUtils.java

@ -2,13 +2,19 @@ package org.dromara.common.encrypt.utils;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.SM2;
import com.antherd.smcrypto.sm4.Sm4;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import javax.script.ScriptException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@ -112,7 +118,7 @@ public class EncryptUtils {
* @param password 秘钥字符串
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptBySm4(String data, String password) {
public static String encryptBySm4Bak(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
@ -150,7 +156,7 @@ public class EncryptUtils {
* @param password 秘钥字符串
* @return 解密后字符串
*/
public static String decryptBySm4(String data, String password) {
public static String decryptBySm4Bak(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
@ -161,7 +167,47 @@ public class EncryptUtils {
}
return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).decryptStr(data, StandardCharsets.UTF_8);
}
public static String decryptBySm4(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
// sm4算法的秘钥要求是16位长度
int sm4PasswordLength = 32;
if (sm4PasswordLength != password.length()) {
throw new IllegalArgumentException("SM4秘钥长度要求为16位");
}
String decrypt = "";
try {
String replace = data.replace("\"", "");
decrypt=SM4Util.decrypt(replace, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
return decrypt;
}
/** sm4加密
*
* @param data 待加密数据
* @param password 秘钥字符串
* @return 加密后字符串, 采用Base64编码
*/
public static String encryptBySm4(String data, String password) {
if (StrUtil.isBlank(password)) {
throw new IllegalArgumentException("SM4需要传入秘钥信息");
}
// sm4算法的秘钥要求是16位长度
int sm4PasswordLength = 32;
if (sm4PasswordLength != password.length()) {
throw new IllegalArgumentException("SM4秘钥长度要求为16位");
}
String encrypt = null;
try {
encrypt = SM4Util.encrypt(data, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
return encrypt;
}
/**
* 产生sm2加解密需要的公钥和私钥
*
@ -169,12 +215,32 @@ public class EncryptUtils {
*/
public static Map<String, String> generateSm2Key() {
Map<String, String> keyMap = new HashMap<>(2);
SM2 sm2 = SmUtil.sm2();
keyMap.put(PRIVATE_KEY, sm2.getPrivateKeyBase64());
keyMap.put(PUBLIC_KEY, sm2.getPublicKeyBase64());
// SM2 sm2 = SmUtil.sm2();
// keyMap.put(PRIVATE_KEY, sm2.getPrivateKeyBase64());
// keyMap.put(PUBLIC_KEY, sm2.getPublicKeyBase64());
//创建sm2 对象
SM2 sm = SmUtil.sm2();
// sm2的加解密时有两种方式即 C1C2C3、 C1C3C2,
sm.setMode(SM2Engine.Mode.C1C3C2);
// 生成私钥
String privateKey = HexUtil.encodeHexStr(sm.getPrivateKey().getEncoded());
keyMap.put("私钥: {}", privateKey);
// 生成公钥
String publicKey = HexUtil.encodeHexStr(sm.getPublicKey().getEncoded());
keyMap.put("公钥: {}", publicKey);
// 生成私钥 D,以D值做为js端的解密私钥
String privateKeyD = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm.getPrivateKey()));
keyMap.put("私钥D: {}", privateKeyD);
// 生成公钥 Q,以Q值做为js端的加密公钥
String publicKeyQ = HexUtil.encodeHexStr(((BCECPublicKey) sm.getPublicKey()).getQ().getEncoded(false));
keyMap.put("公钥Q: {}", publicKeyQ);
return keyMap;
}
/**
* sm2公钥加密
*
@ -186,7 +252,7 @@ public class EncryptUtils {
if (StrUtil.isBlank(publicKey)) {
throw new IllegalArgumentException("SM2需要传入公钥进行加密");
}
SM2 sm2 = SmUtil.sm2(null, publicKey);
SM2 sm2 = SmUtil.sm2(null, HexUtil.decodeHex(publicKey));
return sm2.encryptBase64(data, StandardCharsets.UTF_8, KeyType.PublicKey);
}
@ -202,7 +268,10 @@ public class EncryptUtils {
throw new IllegalArgumentException("SM2需要传入公钥进行加密");
}
SM2 sm2 = SmUtil.sm2(null, publicKey);
return sm2.encryptHex(data, StandardCharsets.UTF_8, KeyType.PublicKey);
// return sm2.encryptHex(data, StandardCharsets.UTF_8, KeyType.PublicKey);
byte[] encrypt = sm2.encrypt(data, KeyType.PublicKey);
String encryStr = HexUtil.encodeHexStr(encrypt);
return encryStr;
}
/**
@ -216,8 +285,8 @@ public class EncryptUtils {
if (StrUtil.isBlank(privateKey)) {
throw new IllegalArgumentException("SM2需要传入私钥进行解密");
}
SM2 sm2 = SmUtil.sm2(privateKey, null);
return sm2.decryptStr(data, KeyType.PrivateKey, StandardCharsets.UTF_8);
SM2 sm2 = SmUtil.sm2(HexUtil.decodeHex(privateKey), null);
return sm2.decryptStr("04"+data, KeyType.PrivateKey, StandardCharsets.UTF_8);
}
/**
@ -309,3 +378,4 @@ public class EncryptUtils {
}
}

69
ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/utils/SM4Util.java

@ -0,0 +1,69 @@
package org.dromara.common.encrypt.utils;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
public class SM4Util {
private static final int BLOCK_SIZE = 16; // 块大小
// 随机生成 SM4 密钥
public static String generateKey() {
byte[] key = new byte[BLOCK_SIZE];
new SecureRandom().nextBytes(key);
return Hex.toHexString(key);
}
// 加密
public static String encrypt(String plainText, String hexKey) throws Exception {
byte[] input = plainText.getBytes(StandardCharsets.UTF_8);
byte[] keyBytes = Hex.decode(hexKey);
// 计算填充长度
int paddingLength = BLOCK_SIZE - (input.length % BLOCK_SIZE);
byte[] paddedInput = new byte[input.length + paddingLength];
// 复制原始数据
System.arraycopy(input, 0, paddedInput, 0, input.length);
// PKCS7填充
for (int i = input.length; i < paddedInput.length; i++) {
paddedInput[i] = (byte) paddingLength;
}
SM4Engine sm4 = new SM4Engine();
sm4.init(true, new KeyParameter(keyBytes));
byte[] encrypted = new byte[paddedInput.length];
for (int i = 0; i < paddedInput.length; i += BLOCK_SIZE) {
sm4.processBlock(paddedInput, i, encrypted, i);
}
// SM4Engine sm4 = new SM4Engine();
// sm4.init(true, new KeyParameter(keyBytes)); // 加密模式
//
// byte[] encrypted = new byte[input.length];
// for (int i = 0; i < input.length; i += BLOCK_SIZE) {
// sm4.processBlock(input, i, encrypted, i);
// }
return Hex.toHexString(encrypted);
}
// 解密
public static String decrypt(String cipherText, String hexKey) throws Exception {
byte[] keyBytes = Hex.decode(hexKey);
byte[] encrypted = Hex.decode(cipherText);
SM4Engine sm4 = new SM4Engine();
sm4.init(false, new KeyParameter(keyBytes)); // 解密模式
byte[] decrypted = new byte[encrypted.length];
for (int i = 0; i < encrypted.length; i += BLOCK_SIZE) {
sm4.processBlock(encrypted, i, decrypted, i);
}
return new String(decrypted, StandardCharsets.UTF_8).trim();
}
}

3
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ModelPrompts.java

@ -1,5 +1,7 @@
package org.dromara.productManagement.domain;
import org.dromara.common.encrypt.annotation.EncryptField;
import org.dromara.common.encrypt.enumd.AlgorithmType;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@ -35,6 +37,7 @@ public class ModelPrompts extends TenantEntity {
/**
* 模型任务名称
*/
@EncryptField(algorithm = AlgorithmType.SM4, password = "c7746c89a780c27eda14a2f9b3097c8f")
private String taskName;
/**

Loading…
Cancel
Save