java/vue使用国密sm2、sm3、sm4进行数据加密

简介(必看)

国密sm2、sm4都是可以加解密的,sm3是单向加密,是无法解密的

sm2加密和解密是不同的秘钥,需要提前生成一对公钥和私钥,公钥用来加密,私钥用来解密

sm4的加解密用的是一样的秘钥

国密sm2

sm2加解密方式:需要提前生成好一对公钥和私钥,然后加密的时候,用公钥进行加密,解密的时候,用私钥进行解密

java端

添加依赖

<!--SM2加密-->
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15to18</artifactId>
	<version>1.72</version>
</dependency>
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15on</artifactId>
	<version>1.70</version>
</dependency>
<!--hutool-->
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.8.22</version>
</dependency>

生成公钥和私钥

SM2 sm2 = SmUtil.sm2();
String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));

加解密工具类

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;

/**
 * 加解密工具类
 *
 * @author 猴哥
 */
public class Sm2Util {
	/**
	 * 加密
	 *
	 * @param publicKey 公钥
	 * @param data 明文
	 * @return 密文
	 */
	public static String encrypt(String publicKey, String data) {
		return SmUtil.sm2(null, publicKey)
				.encryptHex(data.getBytes(), KeyType.PublicKey)
				// 加密后,密文前面会有04,需要去掉
				.substring(2);
	}

	/**
	 * 解密
	 *
	 * @param privateKey 私钥
	 * @param data 密文
	 * @return 明文
	 */
	public static String decrypt(String privateKey, String data) {
		// 前端加密是没有04的,所以解析的时候要加04
		data = "04" + data;
		return SmUtil.sm2(privateKey, null)
				.decryptStr(data, KeyType.PrivateKey);
	}
}

vue端

添加依赖

npm install sm-crypto --save

生成公钥和私钥

const sm2 = require('sm-crypto').sm2

let keypair = sm2.generateKeyPairHex();
// 公钥
let publicKey = keypair.publicKey.toUpperCase();
// 私钥
let privateKey = keypair.privateKey.toUpperCase();

公钥加密

const sm2 = require('sm-crypto').sm2;
sm2.doEncrypt(data, publicKey);

私钥解密

const sm2 = require('sm-crypto').sm2;
sm2.doDecrypt(data, privateKey);

工具类封装

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.engines.SM2Engine;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 猴哥
 */
public class Sm2Util {
	/**
	 * 生成秘钥对
	 *
	 * @return 公钥和私钥
	 */
	public static Map<String, String> generator() {
		SM2 sm2 = SmUtil.sm2();
		String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false)).toUpperCase();
		String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey())).toUpperCase();
		return new HashMap<String, String>(2) {{
			put("publicKey", publicKey);
			put("privateKey", privateKey);
		}};
	}

	/**
	 * 加密
	 *
	 * @param publicKey 公钥
	 * @param data 明文
	 * @return 密文
	 */
	public static String encrypt(String publicKey, String data) {
		return SmUtil.sm2(null, publicKey)
				// 不写默认就是C1C3C2
				.setMode(SM2Engine.Mode.C1C3C2)
				.encryptHex(data.getBytes(), KeyType.PublicKey)
				// 加密后,密文前面会有04,需要去掉
				.substring(2);
	}

	/**
	 * 解密
	 *
	 * @param privateKey 私钥
	 * @param data 密文
	 * @return 明文
	 */
	public static String decrypt(String privateKey, String data) {
		// 确定前端不会加04,所以后端直接加(上面处理方式可能造成报错(Invalid point coordinates):原因前端加密后密文自带04开头)
		data = "04" + data;
		return SmUtil.sm2(privateKey, null)
				// 不写默认就是C1C3C2
				.setMode(SM2Engine.Mode.C1C3C2)
				.decryptStr(data, KeyType.PrivateKey);
	}
}

国密sm3

添加依赖

<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.8.22</version>
</dependency>

工具类

import cn.hutool.crypto.SmUtil;
import java.util.Base64;

/**
 * Sm3加密工具类
 *
 * @author 猴哥
 */
public class Sm3Util {
	/**
	 * 加密
	 *
	 * @param key 秘钥
	 * @param data 明文
	 * @return 密文
	 */
	public static String encrypt(String key, String data) {
		byte[] bytes = SmUtil.hmacSm3(Base64.getDecoder().decode(key))
				.digest(data);
		return Base64.getEncoder().encodeToString(bytes);
	}
}

国密sm4

添加依赖

<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.8.27</version>
</dependency>
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15on</artifactId>
	<version>1.70</version>
</dependency>

加解密工具类

import cn.hutool.crypto.symmetric.SymmetricCrypto;

/**
 * 国密sm4工具类
 *
 * @author 猴哥
 */
public class Sm4Util {
	/**
	 * 加密
	 *
	 * @param key 秘钥
	 * @param data 明文
	 * @return 密文
	 */
	public static String encrypt(String key, String data) {
		SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", key.getBytes());
		return sm4.encryptHex(data).toUpperCase();
	}

	/**
	 * 解密
	 *
	 * @param key 秘钥
	 * @param data 密文
	 * @return 明文
	 */
	public static String decrypt(String key, String data) {
		SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", key.getBytes());
		return sm4.decryptStr(data);
	}
}

注意:加解密的key的长度要是16个字符,否则会失败

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值