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

18 篇文章 0 订阅

国密SM加密

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

后端封装SM2:

原文:SM2国密算法加解密_皮皮的小猪仔的技术博客_51CTO博客

1.1 导入POM依赖

<!-- hutool -->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.5</version>
</dependency>
<!-- 加解密依赖包 -->
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15to18</artifactId>
  <version>1.71</version>
</dependency>

1.2 生成公钥、私钥密钥对

/**
 * 生成公钥、私钥,这个保存好,尤其是私钥,切记不可泄漏
 */
public static void generateCommonKey() {
  SM2 sm2 = SmUtil.sm2();
  // 私钥:这个保存好,切记不要泄漏,真的泄露了就重新生成一下
  byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
  // 公钥:这个是前后端加密用的,不压缩选择带04的,不带04到时候前端会报错
  byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
  Console.log("公钥:\n{}", HexUtil.encodeHexStr(publicKey));
  Console.log("私钥:\n{}", HexUtil.encodeHexStr(privateKey));
}

1.3 加解密

/**
 * sm2明文加密
 * PRIVATE_KEY:生成的私钥
 * PUBLIC_KEY:生成的公钥
 * @param data 加密前的明文
 * @return 加密后的密文
 */
public static String encryptData(String data) {
  SM2 sm2 = SmUtil.sm2(ECKeyUtil.toSm2PrivateParams(PRIVATE_KEY), ECKeyUtil.toSm2PublicParams(PUBLIC_KEY));
  String encryptBcd = sm2.encryptBcd(data, KeyType.PublicKey);
  // 这里的处理前端也可以处理,这个就看怎么约定了,其实都无伤大雅
  if (StrUtil.isNotBlank(encryptBcd)) {
    // 生成的加密密文会带04,因为前端sm-crypto默认的是1-C1C3C2模式,这里需去除04才能正常解密
    if (encryptBcd.startsWith("04")) {
      encryptBcd = encryptBcd.substring(2);
    }
    // 前端解密时只能解纯小写形式的16进制数据,这里需要将所有大写字母转化为小写
    encryptBcd = encryptBcd.toLowerCase();
  }
  return encryptBcd;
}

/**
 * sm2密文解密
 * PRIVATE_KEY:生成的私钥
 * PUBLIC_KEY:生成的公钥
 * @param encryptData 加密密文
 * @return 解密后的明文字符串
 */
public static String decryptData(String encryptData) throws Exception {
  if (StrUtil.isBlank(encryptData)) {
    throw new RuntimeException("解密串为空,解密失败");
  }
  SM2 sm2 = SmUtil.sm2(ECKeyUtil.toSm2PrivateParams(PRIVATE_KEY), ECKeyUtil.toSm2PublicParams(PUBLIC_KEY));
  // BC库解密时密文开头必须带04,如果没带04则需补齐
  if (!encryptData.startsWith("04")) {
    encryptData = "04".concat(encryptData);
  }
  byte[] decryptFromBcd = sm2.decryptFromBcd(encryptData, KeyType.PrivateKey);
  if (decryptFromBcd != null && decryptFromBcd.length > 0) {
    return StrUtil.utf8Str(decryptFromBcd);
  } else {
    throw new Exception("密文解密失败");
  }
}

前端封装SM2

原文:前端使用国密sm2和sm4进行加解密_js sm4_二七二十七的博客-CSDN博客

SM2加密依赖

npm install --save sm-crypto
或
npm install --save sm-crypto --legacy-peer-deps   
  1. 将sm2的加密解密方法进行封装,文件命名为sm2.ts
    // 引入
    const sm2 = require('sm-crypto').sm2
    const cipherMode = 0 // 1 - C1C3C2,0 - C1C2C3,默认为1
    
    // 后端会生成密钥对
    // publicKey:公钥 后端提供
    // privateKey:私钥 后端提供
    const publicKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    const privateKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    
    // 加密
    // value:需要加密的内容
    export function encrypt (value) {
    	// 给后端传值时需要在加密的密文前面加04 ,这样后端才能解密正确不报错
    	return '04' + sm2.doEncrypt(value, publicKey, cipherMode)
    }
    
    // 解密
    // value:需要解密的密文
    export function decrypt (value) {
    	// 后端传输过来的密文开头的两个字符通常也为04,因此解密时需要删除
    	return sm2.doDecrypt(value.slice(2, value.length), privateKey, cipherMode)
    }
    
    使用
    	// 引入sm2.js,注意文件路径不要出错
    	import { encrypt, decrypt } from './sm2'
    
    	// data:需要加密的数据
    	// encryptData:加密后的密文
    	// 若有需要则将js对象转换为字符串后进行加密:JSON.stringify(data)
    	const encryptData = encrypt(JSON.stringify(data))
    
    	// data:需要解密的密文
    	// decryptData:解密后的数据
    	// 若解密结果为json字符串,则可以通过JSON.parse()方法将解密结果转化为json对象
    	const decryptData = decrypt(data)
    

    SM4

    前端封装
  2. 将sm4的加密解密方法进行封装,文件命名为sm4.js

    const SM4 = require("gm-crypt").sm4;
    
    const pwdKey = "xxxx"; //密钥 前后端一致,后端提供
    let sm4Config = {
          key: pwdKey,
          mode: "ecb",  // 加密的方式有两种,ecb和cbc两种,看后端如何定义的,cbc需要iv参数,ecb不用
          iv: '1234567891011121', // 初始向量,cbc模式的第二个参数,也需要跟后端配置的一致
          cipherType: "base64"
        };
    
    const sm4Util = new SM4(sm4Config); // new一个sm4函数,将上面的sm4Config作为参数传递进去。
        
    /* 
     * 加密工具函数
     * @param {String} text 待加密文本
     */
    export function encrypt(text) {
      return sm4Util.encrypt(text, pwdKey);
    }
    
    /*
     * 解密工具函数
     * @param {String} text 待解密密文
     */
     export function decrypt(text) {
      return sm4Util.decrypt(text, pwdKey);
    }
    
    使用
    	// 引入asm4.js,注意文件路径不要出错
    	import { encrypt,decrypt } from "./sm4"
    
    	// data:需要加密的数据
    	// encryptData:加密后的密文
    	// 若有需要则将js对象转换为字符串后进行加密:JSON.stringify(data)
    	const encryptData = encrypt(JSON.stringify(data))
    
    	// data:需要解密的密文
    	// decryptData:解密后的数据
    	// 若解密结果为json字符串,则可以通过JSON.parse()方法将解密结果转化为json对象
    	const decryptData = decrypt(data)
    

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用C语言实现国密SM2算法的加解密代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sm3.h" #include "sm2.h" int main() { // 初始化SM2上下文 sm2_context ctx; sm2_init(&ctx); // 设置SM2公钥 unsigned char pub_key[64] = { 0x04, 0xA9, 0xF1, 0x9F, 0xC4, 0x5A, 0x2E, 0x4F, 0x5E, 0x4A, 0x12, 0x2F, 0x3D, 0x50, 0x32, 0x22, 0x62, 0x80, 0x20, 0x25, 0x61, 0x0B, 0x09, 0x06, 0x4A, 0x2F, 0x9A, 0x0D, 0x14, 0x70, 0x2C, 0x7D, 0x34, 0x7B, 0x33, 0x5B, 0x4F, 0x8E, 0x97, 0x63, 0x0E, 0x0C, 0xD7, 0x0D, 0x5B, 0x61, 0xA7, 0x32, 0x60, 0x2C, 0x17, 0x69, 0x2F, 0x00, 0x3E, 0x0F, 0x9C, 0x57, 0x0B, 0x8E, 0xF8, 0x1C, 0x00, 0x05 }; sm2_set_public_key(&ctx, pub_key); // 设置SM2私钥 unsigned char pri_key[32] = { 0x71, 0x1E, 0x5E, 0x6A, 0x39, 0x5D, 0x3D, 0x7D, 0x4F, 0x5C, 0x29, 0xC2, 0x76, 0x17, 0x38, 0x3A, 0x9B, 0xB5, 0x60, 0x4E, 0x81, 0x77, 0x1F, 0x15, 0x9D, 0x1C, 0x91, 0x21, 0x92, 0x4C, 0x63, 0x4F }; sm2_set_private_key(&ctx, pri_key); // 待加密的明文 unsigned char plain_text[32] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35 }; // 加密密文和密钥 unsigned char cipher_text[256] = {0}; unsigned char secret_key[32] = {0}; // 进行加密 sm2_encrypt(&ctx, plain_text, 32, cipher_text, secret_key); printf("cipher text:\n"); for(int i = 0; i < 128; i++) { printf("%02x", cipher_text[i]); } printf("\n"); printf("secret key:\n"); for(int i = 0; i < 32; i++) { printf("%02x", secret_key[i]); } printf("\n"); // 解密明文 unsigned char plain_text2[32] = {0}; sm2_decrypt(&ctx, cipher_text, 128, secret_key, plain_text2); printf("plain text:\n"); for(int i = 0; i < 32; i++) { printf("%02x", plain_text2[i]); } printf("\n"); return 0; } ``` 需要使用到两个库文件 `sm3.h` 和 `sm2.h`,这里不做展示。运行代码即可进行 SM2加解密操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值