Java实现SM2前后端加解密

Sm2加解密原理,非对称加密,公钥加密,私钥解密。公私钥对成对生成,加密端解密端各自保存。用公钥加密必须要用对应的私钥才能解密,保证安全性。

这里我们实现的功能是前端加密,后端解密,这样前端暴露了公钥,后端持有配对的私钥,保证安全性。

1.jsp引入sm2

<script type="text/javascript" src="${pageContext.request.contextPath}/jslib/jquery-easyui-1.5.2/jquery.easyui.min.js" charset="utf-8"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/jslib/sm2/crypto-js.js" charset="utf-8"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/jslib/sm2/sm2.js" charset="utf-8"></script>

2.js加密

改写sm2.js,输入公钥

function sm2EncryptPwd(data) {var publicKey = '04XXXXXXXXXXXXXXXXXXXXXXXXXXXCB42F6044B1BA8640B42AE038252F3490F02029E37B91D6E0796DE0B3D67166CDD971E556EF1D6B54ED350031817DED6B0C40';return sm2Encrypt(data, publicKey, 1);}

公钥用后端的生成公私钥对方法生成,请勿使用文章提到的公私钥对。

例如login.js使用了加密,即

login.js,调用加密函数

var encryptedPwd = sm2EncryptPwd(pwd);

3.后端Java解密

引用依赖库 bcprov-jdk15on-1.68.jar

<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.68</version></dependency>

login.java

私钥附上对应的值

pwd = new String(SM2Utils.decrypt(pwd, sm2PrivKey));

Sm2Utils.java

package com.sgsg.basic.encrypt.util;import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;/*** SM2工具类* @author van*/public class SM2Utils {/*** 生成 SM2 公私钥对** @return* @throws NoSuchAlgorithmException* @throws InvalidAlgorithmParameterException*/public static KeyPair geneSM2KeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");// 获取一个椭圆曲线类型的密钥对生成器final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());// 产生随机数SecureRandom secureRandom = new SecureRandom();// 使用SM2参数初始化生成器kpg.initialize(sm2Spec, secureRandom);// 获取密钥对KeyPair keyPair = kpg.generateKeyPair();return keyPair;}/*** 生产hex秘钥对*/public static void geneSM2HexKeyPair(){try {KeyPair keyPair = geneSM2KeyPair();PrivateKey privateKey = keyPair.getPrivate();PublicKey publicKey = keyPair.getPublic();System.out.println("========  EC X Y keyPair    ========");System.out.println(privateKey);System.out.println(publicKey);System.out.println("========  hex keyPair       ========");System.out.println("hex priKey: " + getPriKeyHexString(privateKey));System.out.println("hex pubKey: " + getPubKeyHexString(publicKey));System.out.println("========  base64 keyPair    ========");System.out.println("base64 priKey: " + new String(Base64.getEncoder().encode(privateKey.getEncoded())));System.out.println("base64 pubKey: " + new String(Base64.getEncoder().encode(publicKey.getEncoded())));System.out.println("========  generate finished ========");} catch (Exception e) {e.printStackTrace();}}/*** 获取私钥(16进制字符串,头部不带00长度共64)** @param privateKey 私钥PrivateKey型* @return*/public static String getPriKeyHexString(PrivateKey privateKey) {// OK
//	        BCECPrivateKey s=(BCECPrivateKey)privateKey;
//	        String priKeyHexString = Hex.toHexString(s.getD().toByteArray());
//	        if(null!= priKeyHexString && priKeyHexString.length()==66 && "00".equals(priKeyHexString.substring(0,2))){
//	            return priKeyHexString.substring(2);
//	        }// OKBCECPrivateKey key = (BCECPrivateKey) privateKey;BigInteger intPrivateKey = key.getD();String priKeyHexString = intPrivateKey.toString(16);return priKeyHexString;}/*** 获取私钥 base64字符串** @param privateKey 私钥PrivateKey型* @return*/public static String getPriKeyBase64String(PrivateKey privateKey) {return new String(Base64.getEncoder().encode(privateKey.getEncoded()));}/*** 获取公钥(16进制字符串,头部带04长度共130)** @param publicKey 公钥PublicKey型* @return*/public static String getPubKeyHexString(PublicKey publicKey) {BCECPublicKey key = (BCECPublicKey) publicKey;return Hex.toHexString(key.getQ().getEncoded(false));}/*** 获取公钥 base64字符串** @param publicKey 公钥PublicKey型* @return*/public static String getPubKeyBase64String(PublicKey publicKey) {return new String(Base64.getEncoder().encode(publicKey.getEncoded()));}/*** SM2加密算法** @param publicKey 公钥* @param data      明文数据* @return*/public static String encrypt(String data, PublicKey publicKey) {return encrypt(data.getBytes(StandardCharsets.UTF_8), publicKey);}/*** @param data* @param publicKey* @return* @author * @version 1.0* 2023年4月12日下午4:41:24*/public static String encrypt(byte[] data, PublicKey publicKey) {BCECPublicKey key = (BCECPublicKey) publicKey;return encrypt(data, Hex.toHexString(key.getQ().getEncoded(false)));}/*** @param data* @param pubKeyHexString* @return* @author * @version 1.0* 2023年4月12日下午4:46:37*/public static String encrypt(String data, String pubKeyHexString) {return encrypt(data.getBytes(StandardCharsets.UTF_8), pubKeyHexString);}/*** SM2加密算法** @param pubKeyHexString 公钥(16进制字符串)* @param data            明文数据* @return hex字符串*/public static String encrypt(byte[] data, String pubKeyHexString) {// 获取一条SM2曲线参数X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");// 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数NECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());//提取公钥点ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(pubKeyHexString));// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);// 设置sm2为加密模式sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));byte[] arrayOfBytes = null;try {arrayOfBytes = sm2Engine.processBlock(data, 0, data.length);} catch (Exception e) {System.out.println("SM2加密时出现异常:" + e.getMessage());}return Hex.toHexString(arrayOfBytes);}/*** SM2解密算法* @param cipherData    hex格式密文* @param privateKey    密钥PrivateKey型* @return              明文*/public static String decrypt(String cipherData, PrivateKey privateKey) {return decrypt(Hex.decode(cipherData), privateKey);}/*** @param cipherData* @param privateKey* @return* @author * @version 1.0* 2023年4月12日下午4:46:50*/public static String decrypt(byte[] cipherData, PrivateKey privateKey) {BCECPrivateKey key = (BCECPrivateKey) privateKey;return decrypt(cipherData, Hex.toHexString(key.getD().toByteArray()));}/*** @param cipherData* @param priKeyHexString* @return* @author * @version 1.0* 2023年4月12日下午4:46:53*/public static String decrypt(String cipherData, String priKeyHexString) {// 使用BC库加解密时密文以04开头,传入的密文前面没有04则补上if (!cipherData.startsWith("04")) {cipherData = "04" + cipherData;}return decrypt(Hex.decode(cipherData), priKeyHexString);}/*** SM2解密算法** @param cipherData      密文数据* @param priKeyHexString 私钥(16进制字符串)* @return*/public static String decrypt(byte[] cipherData, String priKeyHexString) {//获取一条SM2曲线参数X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());BigInteger privateKeyD = new BigInteger(priKeyHexString, 16);ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters);SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);// 设置sm2为解密模式sm2Engine.init(false, privateKeyParameters);String result = "";try {byte[] arrayOfBytes = sm2Engine.processBlock(cipherData, 0, cipherData.length);return new String(arrayOfBytes);} catch (Exception e) {System.out.println("SM2解密时出现异常:" + e.getMessage());}return result;}/*** @param data* @param priKeyHexString hex私钥,长度64* @return hex格式签名值* @throws Exception*/public static String sign(String data, String priKeyHexString) throws Exception {return sign(data.getBytes(StandardCharsets.UTF_8), priKeyHexString);}/*** 签名* @param data              原始数据,字节数组* @param priKeyHexString   hex私钥,64长度* @return                  Hex字符串* @throws Exception*/public static String sign(byte[] data, String priKeyHexString) throws Exception {String signValue = null;SM2Signer signer = new SM2Signer();X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());CipherParameters param = new ParametersWithRandom(new ECPrivateKeyParameters(new BigInteger(priKeyHexString, 16), domainParameters));signer.init(true, param);signer.update(data, 0, data.length);signValue = Hex.toHexString(signer.generateSignature());return signValue;}/*** 验签* @param data                  数据* @param signValue             签名值(hex型)* @param pKHexString    hex130长度公钥* @return */public static boolean verify(String data, String signValue, String publicKeyHexString) throws Exception {return verify(data.getBytes(StandardCharsets.UTF_8), Hex.decode(signValue), publicKeyHexString);}/*** 验签* @param data                  原始数据字节数组* @param sign                  字节数组()* @param pKHexString    hex130长度公钥* @return                      true or false* @throws Exception*/public static boolean verify(byte[] data, byte[] sign, String pKHexString) throws Exception {SM2Signer signer = new SM2Signer();X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());if (pKHexString.length() == 128) {pKHexString = "04" + pKHexString;}ECPoint ecPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(pKHexString));CipherParameters param = new ECPublicKeyParameters(ecPoint, domainParameters);signer.init(false, param);signer.update(data, 0, data.length);return signer.verifySignature(sign);}/*** 私钥生成公钥* @param priKeyHexString 私钥Hex格式,必须64位* @return 公钥Hex格式,04开头,130位* @throws Exception 例如:*/public static String getPubKeyByPriKey(String priKeyHexString) throws Exception {if (priKeyHexString == null || priKeyHexString.length() != 64) {System.err.println("priKey 必须是Hex 64位格式,例如:11d0a44d47449d48d614f753ded6b06af76033b9c3a2af2b8b2239374ccbce3a");return "";}String pubKeyHexString = null;X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数BigInteger privateKeyD = new BigInteger(priKeyHexString, 16);ECParameterSpec ecParameterSpec = new ECParameterSpec(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(privateKeyD, ecParameterSpec);PrivateKey privateKey = null;privateKey = KeyFactory.getInstance("EC", new BouncyCastleProvider()).generatePrivate(ecPrivateKeySpec);// 临时解决办法String pointString = privateKey.toString();
//	        System.out.println(pointString);String pointString_X = pointString.substring(pointString.indexOf("X: ") + "X: ".length(), pointString.indexOf("Y: ")).trim();String pointString_Y = pointString.substring(pointString.indexOf("Y: ") + "Y: ".length()).trim();
//	        System.out.println(pointString_X);
//	        System.out.println(pointString_Y);pubKeyHexString = "04" + pointString_X + pointString_Y;return pubKeyHexString;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/57898.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四川玖璨电子商务有限公司:抖店运营攻略

抖店运营&#xff0c;是指在抖音平台上进行电商销售的一种新型商业模式。随着抖音平台越来越受到年轻人的喜爱和关注&#xff0c;抖店运营正变得越来越重要。那么&#xff0c;抖店运营应该如何做呢&#xff1f;我们来谈谈抖店运营的一些攻略。 第一&#xff0c;选对产品。选择…

什么是住宅ip,静态和动态怎么选?

上文我们介绍了数据中心代理&#xff0c;这次我们来介绍下住宅代理ip&#xff0c;住宅代理ip分类两种类型&#xff1a;静态住宅代理和动态住宅代理&#xff0c;他们有什么区别又能用在什么场景呢&#xff1f;我们先从他们是如何运作开始。 一、什么是住宅代理ip isp住宅代理i…

如何通过原型修改第三方类库,来实现自己的功能而不破坏类库?手写一下

使用原型链对第三方库进行扩展或修改是JavaScript中的常见做法。这种做法的优点是可以在不修改原始库源码的情军况下增加或修改功能。但也需要小心&#xff0c;因为过度的修改可能会导致与原始库的不兼容&#xff0c;或者出现不可预料的副作用。 下面给出一个简单的例子说明如…

【java】【springboot】【idea】springboot项目pom.xml 灰色下划线

解决方案&#xff1a; 这里我们找到了原因&#xff0c;就是因为选择了Ignored Files导致pom.xml文件被设置在maven忽略文件清单中&#xff0c;所以我们将打勾的选项取消&#xff0c;点击Apply,然后点击OK

DatabaseMetaData.getIndexInfo获取索引权限不足

报错&#xff1a; - [com.unicom.dts.api.jdbc.AbsJdbcUtil : getTableIndexs : 783] - java.sql.SQLSyntaxErrorException: ORA-01031: 权限不足 原因&#xff1a; 缺少analyze权限 解决办法&#xff1a; 赋权限sql&#xff1a;grant analyze any to oracle_whcs; getIndex…

Spark 启动时,报JAVA_HOME is not set

文章目录 1、报错内容2、解决方式3、再次启动Spark集群 1、报错内容 Spark启动时报错&#xff1a; hadoop104: JAVA_HOME is not set2、解决方式 解决方式&#xff1a; 打开启动配置文件 cd /opt/module/spark-standalone/sbin/ vim spark-config.sh配置Java的环境变量 …

clickhouse一次异常排查记录

clickhouse中报错 关闭了自启动&#xff0c;删了status&#xff0c;重启了clickhouse还是报错 1&#xff0c;排查定时执行的脚本日志&#xff08;每小时第5分钟执行&#xff09; INSERT INTO quality0529.previously_reported_urls (url) SELECT url FROM quality0529.hourly_…

javacv基础02-调用本机摄像头并预览摄像头图像画面视频

引入架包&#xff1a; <dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.5.5-1</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId…

说说如何借助webpack来优化前端性能?

文章目录 如何优化&#xff1f;简单介绍一下1.JS代码压缩2、CSS代码压缩3、Html文件代码压缩4、文件大小压缩5、图片压缩6、内联chunk 总结 如何优化&#xff1f; 通过webpack优化前端的手段有&#xff1a; JS代码压缩CSS代码压缩Html文件代码压缩文件大小压缩图片压缩 简单…

null和undefined区别

1.undefined&#xff0c;表示无值。 比如下面场景&#xff1a; a. 变量被声明了&#xff0c;但是没有被赋值&#xff1b; b. 调用函数的时候&#xff0c;应该给函数传参却没有给函数传这个参数打印出来就是 undefined&#xff1b; c. 访问一个对象中没有的属性&#xff1b;…

Ribbon:listOfServers ,${variableName:defaultValue}

解释&#xff1a; 配置了address的地址,请求会走address&#xff0c;也就是http://127.0.0.1:8081&#xff0c;通常用户与别的后端服务进行联调设置为其本地服务的ip。 如果address的地址被注释掉&#xff0c;如下面所示&#xff0c;类似这样的占位符${variableName:defaultVa…

【Terraform学习】使用 Terraform 创建应用程序负载均衡器(Terraform-AWS最佳实战学习)

使用 Terraform 创建应用程序负载均衡器 实验步骤 前提条件 安装 Terraform&#xff1a; 地址 下载仓库代码模版 本实验代码位于 task_elb 文件夹中。 变量文件 variables.tf 在上面的代码中&#xff0c;您将声明&#xff0c;aws_access_key&#xff0c;aws_secret_key…

【设计模式】Java设计模式详细讲解

一、概述 Java设计模式是Java程序设计中一种重要的最佳实践&#xff0c;它提供了一种框架和结构&#xff0c;可以帮助开发者更好地理解和设计复杂的系统。设计模式不仅仅是一种语法规则&#xff0c;更是一种思想和方法论&#xff0c;它能够帮助开发者更好地分析、设计和实现软…

算法通关村第6关【白银】| 树的层次遍历问题

一、基本层次遍历问题 1.二叉树的层次遍历 思路&#xff1a;使用队列可以很好的保存遍历状态&#xff0c;出队将结点左右子结点入队&#xff0c;用size记录下一层的元素个数&#xff0c;这样就能区分出层了 class Solution {public List<List<Integer>> levelOr…

【数据结构】树与二叉树

文章目录 &#x1f340;树型结构&#x1f431;‍&#x1f464;什么是树型结构&#x1f431;‍&#x1f453;树型结构的概念&#x1f431;‍&#x1f3cd;树的表示形式&#x1f431;‍&#x1f409;树的应用 &#x1f333;二叉树&#x1f431;‍&#x1f464;二叉树的概念&#…

LLM-chatgpt训练过程

流程简介 主要包含模型预训练和指令微调两个阶段 模型预训练&#xff1a;搜集海量的文本数据&#xff0c;无监督的训练自回归decoder&#xff1b; O T P ( O t < T ) O_TP(O_{t<T}) OT​P(Ot<T​)&#xff0c;损失函数CE loss指令微调&#xff1a;在输入文本中加入…

java解析json

1. 解析根节点为“{}”的json {"id": 1525490,"name": "有缘网" }代码&#xff1a; String jsonString "{\"id\":1525490\",\"name\":\"有缘网\"}";JSONObject jsonObject JSONObject.…

Android获取手机已安装应用列表JAVA实现

最终效果: 设计 实现java代码: //获取包列表private List<String> getPkgList() {List<String> packages new ArrayList<String>();try {//使用命令行方式获取包列表Process p Runtime.getRuntime().exec("pm list packages");//取得命令行输出…

图数据库Neo4j学习五渲染图数据库neo4jd3

文章目录 1.现成的工具2.Neo4j JavaScript Driver3.neovis4.neo4jd34.1neo4jd3和neovis对比4.2获取neo4jd34.3neo4jd3的数据结构4.4Spring data neo4.4.1 定义返回数据格式4.4.1.1NeoResults4.4.1.2GraphVO4.4.1.3NodeVO4.4.1.4ShipVO 4.4.2 SDN查询解析4.4.2.1 Repo查询语句4.…

Java小记-矩阵转置

对于给定的一个二维矩阵&#xff0c;请转置后进行输出。 输入描述 对于一个n*m的矩阵&#xff0c;输入有n行&#xff0c;每行是m个以空格分隔的数字。 输出描述 n*m矩阵的转置矩阵。输出m行&#xff0c;每行是n个空格分隔的数据。 import java.io.*; import java.util.*;pub…