国密SM2 后端Hutool+前端sm-crypto

这篇具有很好参考价值的文章主要介绍了国密SM2 后端Hutool+前端sm-crypto。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在网上找了很多文章,都只是单独说了用后端加解密及前端加解密,很少把两个结合起来一起说的文章,本文分享两者结合起来的用法和踩坑。

准备工作

前端项目引入第三方包

npm install --save sm-crypto

后端项目引入工具类

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

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15to18</artifactId>
  <version>1.69</version>
</dependency>

生成密钥

使用工具类生成两套公私钥: 服务端公私钥、客户端公私钥
前端拿服务端公钥+客户端私钥
后端拿客户端公钥+服务端私钥

本文仅做演示,如何安全存储密钥请自行研究。

	import cn.hutool.core.util.HexUtil;
	import cn.hutool.crypto.BCUtil;
	import cn.hutool.crypto.SmUtil;
	import cn.hutool.crypto.asymmetric.SM2;
	import org.bouncycastle.crypto.engines.SM2Engine;
	import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
				
	//创建sm2 对象
	SM2 sm = SmUtil.sm2();
		        
	// sm2的加解密时有两种方式即 C1C2C3、 C1C3C2,
	sm.setMode(SM2Engine.Mode.C1C3C2);
		        
	// 生成私钥
	String privateKey = HexUtil.encodeHexStr(sm.getPrivateKey().getEncoded());
	log.info("私钥: {}", privateKey);
		        
	// 生成公钥
	String publicKey = HexUtil.encodeHexStr(sm.getPublicKey().getEncoded());
	log.info("公钥: {}", publicKey);
	
	 // 生成私钥 D,以D值做为js端的解密私钥
     String privateKeyD = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm.getPrivateKey()));
     log.info("私钥D: {}", privateKeyD);
     	
	// 生成公钥 Q,以Q值做为js端的加密公钥
	String publicKeyQ = HexUtil.encodeHexStr(((BCECPublicKey) sm.getPublicKey()).getQ().getEncoded(false));
	log.info("公钥Q: {}", publicKeyQ);
	私 钥: 308193020100301306072a8648ce3d020106082a811ccf5501822d047930770201010420b1933b8a0c16c1bcf64dcbcc2cb822c27452dfb8a19b6167e5ee9bec963b8171a00a06082a811ccf5501822da14403420004d6fd83141fe38cee09f8f4e20a72d3ba056dcfeeda4238dc671a1f11e811293c10b8537ea0adb4b9ad1fa37d147b65c451fe4ab51054d71c810cc0e84cd8232d
	公 钥: 3059301306072a8648ce3d020106082a811ccf5501822d03420004d6fd83141fe38cee09f8f4e20a72d3ba056dcfeeda4238dc671a1f11e811293c10b8537ea0adb4b9ad1fa37d147b65c451fe4ab51054d71c810cc0e84cd8232d
	私钥D: 00b1933b8a0c16c1bcf64dcbcc2cb822c27452dfb8a19b6167e5ee9bec963b8171
	公钥Q: 04d6fd83141fe38cee09f8f4e20a72d3ba056dcfeeda4238dc671a1f11e811293c10b8537ea0adb4b9ad1fa37d147b65c451fe4ab51054d71c810cc0e84cd8232d

上面密钥仅供参考

加密及解密

1.前端加密+后端解密

在需要加解密的js文件中引入sm2方法

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

// 1 - C1C3C2,0 - C1C2C3,默认为1
const cipherMode = 1 

//服务端公钥 Q
const publicKeyQ ="服务端公钥 Q";

//要加密的报文
const body={"age":10,"name":"张三"}

 // 加密
let encryStr=sm2.doEncrypt(JSON.stringify(body), publicKeyQ, cipherMode);
 // 加密结果
encryStr: aaaba1cea1af9a9c621d75bacc7434e1eea713861885a28ab8b3a5ebc911bf971c76af94acff2ab0647b8e157e9ccb6f78e85d5173120fbb11f9be610c0194c3c7d97b069478c4f07d06982b4c691d530bb817f490f531b271ee8d52bb9babbe8305ff92782f4fe263a6ea63d010c4bb682241aff20b5c11442a

注意:通过前端加密的密文没有04前缀,所以如果我们想要在后端解密需要手动加上

把密文传给后端进行解密

	import cn.hutool.core.util.StrUtil;
	
	//服务端私钥
  	String privateKey = "服务端私钥";
  	
  	//后端解密时,公钥可以不填
    String publicKey = "";
    
    //手动加上前缀04
	String encryStr = "04" + "aaaba1cea1af9a9c621d75bacc7434e1eea713861885a28ab8b3a5ebc911bf971c76af94acff2ab0647b8e157e9ccb6f78e85d5173120fbb11f9be610c0194c3c7d97b069478c4f07d06982b4c691d530bb817f490f531b271ee8d52bb9babbe8305ff92782f4fe263a6ea63d010c4bb682241aff20b5c11442a";
	SM2 sm2 = SmUtil.sm2(HexUtil.decodeHex(privateKey), null);
	log.info("密文: {}", encryStr);
	byte[] decrypt = sm2.decrypt(encryStr, KeyType.PrivateKey);
	log.info("解密结果: {}", StrUtil.utf8Str(decrypt));
密文: 04aaaba1cea1af9a9c621d75bacc7434e1eea713861885a28ab8b3a5ebc911bf971c76af94acff2ab0647b8e157e9ccb6f78e85d5173120fbb11f9be610c0194c3c7d97b069478c4f07d06982b4c691d530bb817f490f531b271ee8d52bb9babbe8305ff92782f4fe263a6ea63d010c4bb682241aff20b5c11442a
解密结果: {"age":10,"name":"张三"}

2.后端加密+前端解密

	//后端加密时,可以不填私钥。 客户端公钥
	SM2 sm2 = SmUtil.sm2(null, HexUtil.decodeHex(publicKey));
	String str = "Hello World";
	byte[] encrypt = sm2.encrypt(str, KeyType.PublicKey);
	String encryStr = HexUtil.encodeHexStr(encrypt);
	log.info("密文: {}", encryStr);
	密文: 046415900ab4af09490d257cdd5aee2d0710b1e222d4386124d6e70f4e39468d2e68d7eb9830db46804b472747e42819bdd56312982da1f765a963cd4c7c51795bd8c3faa220547033740dcb2f91b17039a05c9c6081bbf9c756b90f9a09cfa8cb39e0853766394661b265c60b

注意:后端密文前缀存在04,前端在解密时会在首部自动补充 04,所以我们需截取后再传入。

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

  // 1 - C1C3C2,0 - C1C2C3,默认为1
  const cipherMode = 1 
  
	//客户端私钥 D
  let privateKeyD="客户端私钥 D"
  
  //去掉04前缀后的密文
  let encryStr ="6415900ab4af09490d257cdd5aee2d0710b1e222d4386124d6e70f4e39468d2e68d7eb9830db46804b472747e42819bdd56312982da1f765a963cd4c7c51795bd8c3faa220547033740dcb2f91b17039a05c9c6081bbf9c756b90f9a09cfa8cb39e0853766394661b265c60b"

  const str = sm2.doDecrypt(encryStr , privateKeyD, cipherMode);
  console.log("解密报文:",str);
  
解密报文: Hello World

签名及验签

1.后端加签+前端验签

  // 服务端私钥 ,签名时可以不填公钥
  SM2 sm2 = SmUtil.sm2(HexUtil.decodeHex(privateKey),null);
  
  //要签名的明文数据
  String str = "Hello World";

  //把明文字符串转为十六进制字符串
  String sign = sm2.signHex(HexUtil.encodeHexStr(str));
  log.info("签名:{}", sign);
签名:304502207b8a07c36a97c34278bf4352af13f4a1022f79816820c52a1a23d7499e24a609022100dcf53edf3f2d7f648fea027cacce90f6d101923b1215b2cb9aa6811064ed6cdd

前端接受密文和签名文章来源地址https://www.toymoban.com/news/detail-856681.html

/**
 * msg  明文数据即解密后数据
 * sigValueHex 后端传过来的签名(不需要进行任何处理)
 * publicKeyQ 服务端公钥 Q
 * 最后的json对象必传,否则验签失败
 */
sm2.doVerifySignature(msg, sigValueHex, publicKeyQ ,{der: true,hash: true,}) // 验签结果

const sm2 = require('sm-crypto').sm2
let signResult = sm2.doVerifySignature(
      "Hello World", "304502207b8a07c36a97c34278bf4352af13f4a1022f79816820c52a1a23d7499e24a609022100dcf53edf3f2d7f648fea027cacce90f6d101923b1215b2cb9aa6811064ed6cdd",
      publicKeyQ,
      { hash: true, der: true }
    );
console.log("验签结果:", signResult);
验签结果: true

2.前端加签+后端验签

/**
 * msg  明文数据
 * privateKeyD 客户端私钥 D
 * 最后的json对象必传,否则验签失败
 */
sm2.doSignature(msg, privateKeyD,{der: true,hash: true,}) // 签名

let sign = sm2.doSignature("Hello World",privateKeyD,{der:true,hash:true,}
);
console.log("签名:", sign);
签名:30450220740a651a3f44b7647c884540b19571131da65c88e2750fd8c780d1062af16f9b022100f320694a65f1e85b0320789b9bf9b78c4cfc94f6bc6562e61072389f944ca3de
// 客户端公钥 ,验签时可以不填私钥
SM2 sm2 = SmUtil.sm2(null, HexUtil.decodeHex(publicKey));

//解密后的报文
String str = "Hello World";

String sign = "30450220740a651a3f44b7647c884540b19571131da65c88e2750fd8c780d1062af16f9b022100f320694a65f1e85b0320789b9bf9b78c4cfc94f6bc6562e61072389f944ca3de";

boolean signResult = sm2.verifyHex(HexUtil.encodeHexStr(str), sign);

log.info("验签结果:{}",signResult);

验签结果: true

到了这里,关于国密SM2 后端Hutool+前端sm-crypto的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端使用国密sm2和sm4进行加解密

    国密SM:国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。 安装SM加密依赖 SM2 封装 将sm2的加密解密

    2024年02月08日
    浏览(39)
  • 国密SM2前端加密解密示例

    目录 一、 安装sm2依赖 二、编写代码 1、data中绑定数据 2、公钥加密 3、私钥解密 4、按钮绑定一下,数据可见一下 三、完整代码 要改变的数据phone和过程数据copyphone,公钥publicKey和私钥privateKey 具体生成测试公钥私钥可参照SM2加解密 C1为65字节第1字节为压缩标识,这里固定为

    2024年02月03日
    浏览(41)
  • 前端sm2国密加密解密

    1.下载国密包 2.获取后端的公钥 注sm-crypto使用BC库加解密前端密钥与后端密钥是两队,非常规的base64密钥 前端公钥需要在前面加04占位否则无法解密 3.前端使用公钥进行加密 生成的加密串加04方便后端解密 4.前端使用私钥解密

    2024年02月11日
    浏览(37)
  • 前端国密加解密使用方法SM2、SM3、SM4

       国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。      不多废话直接上干货 项目中 可能存在

    2023年04月09日
    浏览(30)
  • react+vue 前端国密算法sm2、sm3 、sm4的js ts实现

    1. 简单介绍下SM2 和 SM3 SM2 算法:是一种公钥加密算法,它的密钥长度为 256 位,安全性较高。可用于数字签名、密钥协商等场景。 SM3 算法:是一种对称加密算法,用于消息摘要和数字签名等场景。它的密钥长度为 256 位,安全性较高。SM3 算法与 SM2 算法相互配合,提高了整体

    2024年01月19日
    浏览(32)
  • 国密SM2/SM3算法

    分类 1、SM1是一种分组加密算法 对称加密算法中的分组加密算法,其分组长度、秘钥长度都是128bit,算法安全保密强度跟 AES 相当,但是算法不公开,仅以IP核的形式存在于芯片中,需要通过加密芯片的接口进行调用。 采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙

    2024年02月05日
    浏览(49)
  • 三步实现Java的SM2前端加密后端解密

    秦医如毒,无药可解。 话不多说,先上需要用到的 js文件下载链接   和   jsp前端代码 。 第一步: 下载两个必备的js文件——  crypto-js.js 、 sm2.js   。 它们的下载链接如下↓(该网页不魔法上网的话会很卡,毕竟github,建议卡的话就多重新加载几次,我差不多试了8次才进

    2024年02月04日
    浏览(33)
  • Delphi SM2/SM4国密算法

        最近忙个医保平台的项目,涉及SM2/SM4的签名,验签,加密,解密的业务操作过程。毕竟现在用Delpih的人不是很多,懂这方面的技术的人也更少,能涉及密码算法的少之更少,网上也能搜到一些开源的代码,也由于使用的人少,未加通过业务系统来验证,所以存在不少Bu

    2024年02月11日
    浏览(38)
  • 国密算法SM2、SM3的使用

    1. SM2是非对称加密算法         它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号发布。 2.SM3是一种密码杂凑

    2024年02月06日
    浏览(35)
  • 国密算法-SM2

            国密算法是国家密码局制定标准的一系列算法,包括SM1、SM2、SM3、SM4等。其中,SM1是采用硬件实现的,不予讨论;SM2是非对称加密算法;SM3是摘要算法;SM4是对称加密算法。本篇贴出SM2 Java版本实现生成公私钥及加解密、签名验签代码,供大家一起讨论学习,所有

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包