一、后端(SpringBoot)
1.后端导入国密支持
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
2.国密工具类(sm1算法不公开,这里不涉及、sm2是非对称加密、sm3是信息摘要,类似MD5加密、sm4是对称加密)
package com.doctortech.tmc.support.util;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.Security;
public class SMUtil {
private static final Logger logger = LoggerFactory.getLogger(NotificationUtil.class);
public static final String SM4_KEY = "1234567887654321";
private static final String ALGORITHM_NAME = "SM4";
private static final String ALGORITHM_ECB_PKCS5PADDING = "SM4/ECB/PKCS5Padding";
public static final String SM2_PRIVATE_KEY = "sm2私钥";
public static final String SM2_PUBLIC_KEY = "sm2公钥";
public static final SM2Engine.Mode SM2ENGINE_MODE = SM2Engine.Mode.C1C3C2;
private static final String SM2BC_STR = "04";
private static SM2 sm2 = new SM2();
private static final int DEFAULT_KEY_SIZE = 128;
private static final String DEFAULT_ENCODING="utf-8";
static {
if(null == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)){
Security.addProvider(new BouncyCastleProvider());
}
}
public static String sm3(String content){
String res = "";
try{
byte[] srcData = content.getBytes(DEFAULT_ENCODING);
byte[] resultHash = hash(srcData);
res = ByteUtils.toHexString(resultHash);
}catch (Exception e){
e.printStackTrace();
}
return res;
}
private static byte[] hash(byte[] srcData){
SM3Digest digest = new SM3Digest();
digest.update(srcData,0,srcData.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash,0);
return hash;
}
private static byte[] generateKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
kg.init(DEFAULT_KEY_SIZE, new SecureRandom());
return kg.generateKey().getEncoded();
}
public static String sm4Encrypt(String content,String key){
String res = "";
try{
byte[] resByte = encryptEcbPkcs5Padding(content.getBytes(DEFAULT_ENCODING),key.getBytes(DEFAULT_ENCODING));
res = Hex.toHexString(resByte);
}catch (Exception e){
e.printStackTrace();
}
return res;
}
public static String sm4Encrypt(String content){
String res = "";
try{
byte[] resByte = encryptEcbPkcs5Padding(content.getBytes(DEFAULT_ENCODING),SM4_KEY.getBytes(DEFAULT_ENCODING));
res = Hex.toHexString(resByte);
}catch (Exception e){
e.printStackTrace();
}
return res;
}
public static String sm4Decrypt(String data,String key){
String res = "";
try{
byte[] resByte = decryptEcbPkcs5Padding(Hex.decode(data),key.getBytes(DEFAULT_ENCODING));
res = new String(resByte, DEFAULT_ENCODING);
}catch (Exception e){
e.printStackTrace();
}
return res;
}
public static String sm4Decrypt(String data){
String res = "";
try{
byte[] resByte = decryptEcbPkcs5Padding(Hex.decode(data),SM4_KEY.getBytes(DEFAULT_ENCODING));
res = new String(resByte, DEFAULT_ENCODING);
}catch (Exception e){
e.printStackTrace();
}
return res;
}
private static byte[] encryptEcbPkcs5Padding(byte[] data, byte[] key) throws Exception {
return sm4work(data, key, ALGORITHM_ECB_PKCS5PADDING, null, Cipher.ENCRYPT_MODE);
}
private static byte[] decryptEcbPkcs5Padding(byte[] data, byte[] key) throws Exception {
return sm4work(data, key, ALGORITHM_ECB_PKCS5PADDING, null, Cipher.DECRYPT_MODE);
}
private static byte[] sm4work(byte[] input, byte[] key, String sm4mode, byte[] iv, int mode)
throws Exception {
IvParameterSpec ivParameterSpec = null;
if (null != iv) {
ivParameterSpec = new IvParameterSpec(iv);
}
SecretKeySpec sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
Cipher cipher = Cipher.getInstance(sm4mode, BouncyCastleProvider.PROVIDER_NAME);
if (null == ivParameterSpec) {
cipher.init(mode, sm4Key);
} else {
cipher.init(mode, sm4Key, ivParameterSpec);
}
return cipher.doFinal(input);
}
public static String sm2Decrypt(String data) {
String decryptData = "";
try {
long start = System.currentTimeMillis();
logger.info("初始化sm2实例");
initSm2Instance();
if (!data.startsWith(SM2BC_STR)) {
data = new StringBuffer(SM2BC_STR).append(data).toString();
}
decryptData = sm2.decryptStr(data, KeyType.PrivateKey);
long end = System.currentTimeMillis();
logger.info("sm2解密一次所花时间:{}ms",(end - start));
} catch (Exception e) {
e.printStackTrace();
}
return decryptData;
}
public static String sm2Encrypt(String data) {
String encryptData = "";
try {
long start = System.currentTimeMillis();
logger.info("初始化sm2实例");
initSm2Instance();
encryptData = sm2.encryptBcd(data, KeyType.PublicKey);
long end = System.currentTimeMillis();
logger.info("sm2加密一次所花时间:{}ms",(end - start));
} catch (Exception e) {
e.printStackTrace();
}
return encryptData;
}
private static void initSm2Instance() {
logger.info("初始化sm2实例");
ECPrivateKeyParameters privateKeyParameters = BCUtil.toSm2Params(SM2_PRIVATE_KEY);
String xhex = SM2_PUBLIC_KEY.substring(2, 66);
String yhex = SM2_PUBLIC_KEY.substring(66, 130);
ECPublicKeyParameters publicKeyParameters = BCUtil.toSm2Params(xhex, yhex);
sm2.setPrivateKeyParams(privateKeyParameters);
sm2.setPublicKeyParams(publicKeyParameters);
sm2.setMode(SM2ENGINE_MODE);
}
public static void createSm2Key() {
SM2 createSm2Key = SmUtil.sm2();
byte[] privateKey = BCUtil.encodeECPrivateKey(createSm2Key.getPrivateKey());
byte[] publicKey = ((BCECPublicKey) createSm2Key.getPublicKey()).getQ().getEncoded(false);
byte[] publicKeyEc = BCUtil.encodeECPublicKey(createSm2Key.getPublicKey());
System.out.println("私钥: " + HexUtil.encodeHexStr(privateKey));
System.out.println("公钥: " + HexUtil.encodeHexStr(publicKey));
System.out.println("压缩后的公钥: " + HexUtil.encodeHexStr(publicKeyEc));
}
}
3.国密测试
package com.doctortech.tmc;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;
import com.doctortech.tmc.entity.User;
import com.doctortech.tmc.mapper.UserMapper;
import com.doctortech.tmc.service.ServiceConst;
import com.doctortech.tmc.support.util.SMUtil;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.charset.StandardCharsets;
import java.util.List;
@SpringBootTest
public class SMTest {
@Test
public void createSm2KeyTest() {
SMUtil.createSm2Key();
}
@Test
public void sm2EncryptAndDecryptTest() {
long start = System.currentTimeMillis();
String text = "我是一段测试aaaa";
String sm2Encrypt = SMUtil.sm2Encrypt(text);
System.out.println("加密结果:" + sm2Encrypt);
String sm2Decrypt = SMUtil.sm2Decrypt(sm2Encrypt);
System.out.println("解密结果:" + sm2Decrypt);
System.out.println(text.equals(sm2Decrypt));
long end = System.currentTimeMillis();
System.out.println("加密解密一次所花时间:" + (end - start) + "ms");
}
@Test
public void sm3EncryptAndDecryptTest() {
String encryptPassword = SMUtil.sm3(ServiceConst.RESET_PASSWORD);
System.out.println(encryptPassword);
List<User> userList = userMapper.selectList(null);
for (User user : userList) {
user.setPassword(encryptPassword);
userMapper.updateById(user);
}
}
@Test
public void sm2EncryptAndDecryptTest() {
long start = System.currentTimeMillis();
String text = "我是一段测试aaaa";
String sm2Encrypt = SMUtil.sm2Encrypt(text);
System.out.println("加密结果:" + sm2Encrypt);
String sm2Decrypt = SMUtil.sm2Decrypt(sm2Encrypt);
System.out.println("解密结果:" + sm2Decrypt);
System.out.println(text.equals(sm2Decrypt));
long end = System.currentTimeMillis();
System.out.println("加密解密一次所花时间:" + (end - start) + "ms");
}
@Test
public void sm3EncryptAndDecryptTest() {
String encryptPassword = SMUtil.sm3("123456");
System.out.println(encryptPassword);
}
@Test
public void createSm4KeyTest() throws Exception {
byte[] bytes = SMUtil.generateKey();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
}
@Test
public void sm4KeyToByteTest() {
System.out.println(HexUtil.encodeHexStr(SMUtil.SM4_KEY));
}
@Test
public void sm4EncryptAndDecryptTest() {
String content = "123456789你好";
String encryptContent = SMUtil.sm4Encrypt(content);
String decryptContent = SMUtil.sm4Decrypt(encryptContent);
System.out.println("加密后内容:" + encryptContent);
System.out.println("解密后内容:" + decryptContent);
System.out.println(content.equals(decryptContent));
}
}
二、前端(Vue)
1.安装依赖
npm install --save sm-crypto
2.sm2非对称加密(对登录、注册、修改密码进行加密)
const sm2 = require('sm-crypto').sm2
const cipherMode = 1
const publicKey = '公钥'
let encryptPwd = sm2.doEncrypt('password', publicKey, cipherMode)
console.log("encryptPwd:" + encryptPwd)
3.sm4对称加解密(对身份证、邮箱等敏感信息进行加密和解密)
const sm4 = require('sm-crypto').sm4
const sm4Key = 'sm4密钥,要求16进制'
let sm4Encrypt = sm4.encrypt("1245877961584你好", sm4Key)
console.log(sm4Encrypt)
let sm4Decrypt = sm4.decrypt(sm4Encrypt, sm4Key)
console.log(sm4Decrypt)