程序员的资源宝库

网站首页 > gitee 正文

加密-国密-非对称-SM2

sanyeah 2024-04-12 17:41:21 gitee 3 ℃ 0 评论

国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统、密钥管理系统、应用系统进升级改造,使用支持国密SM2算法的证书。

我国现阶段使用的国密SM2算法是在椭圆曲线密码理论基础进行改进而来,其加密强度比RSA算法(2048位)更高。

前段vue + 后端springboot;

  思路: 后端使用hutools工具生成公私钥(公130,私64);并且可以进行加解密。

    前段使用的公钥加密,生成密文后,但是在后端解密的时候,解不出来。原因需要在密文前面加04

1.前段加密:

后端会生成密钥对(公钥(publicKey),私钥(privateKey))
vue使用sm2加密

1.安装下载依赖:npm install --save sm-crypto
下载报错的话可以用淘宝镜像下载:npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver
2.sm2在vue中使用: 

const sm2 = require('sm-crypto').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1

let encryptData = sm2.doEncrypt('需要加密的字符', publicKey, cipherMode) // 加密结果
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果
//给后端(java)传值时需要在加密的密文前面加04 (`04${encryptData}`),这样后端才能解密正确不报错;

 1.1 vue 引入js 

  vue 中 

<script>
import { sm2Encrypt, sm2Decrypt } from '@/utils/sm2Encrypt'

sm2Encrypt.js

const publicKey = '130'

const privateKey = '64'

const sm2 = require('sm-crypto').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1


// 加密
export function sm2Encrypt(txt) {
  let encryptData = sm2.doEncrypt(txt, publicKey, cipherMode) // 加密结果
  return encryptData

}

// 解密
export function sm2Decrypt(txt) {
  let decryptData = sm2.doDecrypt(txt, privateKey, cipherMode) // 解密结果
  return decryptData;

}
View Code

 

 

 

 

 

2.后端解密

2.1pom中引入依赖

 <!-- hutool工具类 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.4</version>
        </dependency>

        <!-- 第三方加密功能依赖sm2 -->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15to18</artifactId>
            <version>1.69</version>
        </dependency>
     <!--
    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.56</version>
    </dependency>
-->

 

相关代码:

 

package com.sinosoft;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.nio.charset.Charset;
//import org.junit.runner.RunWith;


/**
 * TODO
 *
 * @author zhaoJs
 * @version 1.0
 * @date 2022/9/2 15:07
 */
@SpringBootTest (classes = Sm2Test.class)
@RunWith(SpringRunner.class)
@Slf4j
public class Sm2Test {
    String privateKey = "00ac90ec091563b319bdf2e449df659940f24e14beaf09935a92b260fa68c6c8ac";
    String publicKey = "0462a7f3ed9cc136465353dffcf0e253723e3b0c1525cf47860901c0c4ba57c8d984bfc6cb0d1d9764498b41e58fd0040a9920d904ad442495e154d2fe68fd2720";
    String content = "测试";

    //公私钥生成
    @Test
    public void createSM2Key(){

        SM2 sm2 = SmUtil.sm2();
        // sm2的加解密时有两种方式即 C1C2C3、 C1C3C2,
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        // 生成私钥
        String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        // 生成公钥
        String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
        
        log.info("privateKey:" + privateKey);
        log.info("publicKey:" + publicKey);

    }
    //公钥加密
    @Test
    public void encrypt(){
        SM2 sm2 = SmUtil.sm2(null, publicKey);         
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        // 返回值的字符串,需要注意此处加密后密文为16进制,否则前端解密前需要先转换格式
        String encryptStr = sm2.encryptHex(new String(content), Charset.forName("utf-8"), KeyType.PublicKey);
        log.info("encryptStr:" + encryptStr);
    }
    //私钥解密
    @Test
    public void decrypt(){
     // 如果是前段vue传来的 密文,需要在密文前加04 String encryptStr
= "04f0d63500e8f56243462b17c9489c7ea7bbbb10271f45066cc150e2da934fca72abe396b05639fac1192630c27bd7d3ff553c0f43260e8cdb84c5c6594701f75ce96a49ba0d16368acdc3ef16c211bc638cc47caf05214e8e302c8ddb3798534044d1d6204277"; // 解密 SM2 sm2 = SmUtil.sm2(privateKey, publicKey); sm2.setMode(SM2Engine.Mode.C1C3C2); //String newBody1 = StrUtil.utf8Str(sm2.decryptFromBcd(d, KeyType.PrivateKey)); String decryptStr = sm2.decryptStr(encryptStr, KeyType.PrivateKey, Charset.forName("utf-8")); log.info("decryptStr:" + decryptStr); } }

 使用的原生的sm2加密参考

 加密是为了防止信息被泄露,而签名是为了防止信息被篡改。

参考:

SM2 java+hutool方法示例(重点参考)

一文告诉你,国密SM2算法有多优秀

国密SM2的前端加密,后端解密(Java版本)及SM3 摘要加密

国密SM2前端VUE,后端Hutool工具的搭配

前端Vue使用SM2加密、解密方法

vue/java使用国密SM2加密

 

使用hutool工具类国密算法SM2实现

基于hutool实现非对称加密(RSA和国密SM2)的加解密和加签验签

RSA加密、解密、签名、验签的原理及方法

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表