加解密机制(国密2/3/4,AES,RSA,MD5)

一、依赖

国密2国密3国密4
安装依赖1.gm-crypto 优选
2.sm-crypto
1.gm-crypto 优选
2.sm-crypto
1.gm-crypto 优选
2.sm-crypto
3.gm-crypt
支持解密
加密模式1 - C1C3C2、0 - C1C2C3-cbc(优选)、ecb
所需key公钥(加密)、私钥(解密)-key、iv(cbc模式)
依赖安装指令API
gm-cryptonpm install gm-crypto
或 yarn add gm-crypto
https://gitcode.net/mirrors/byte-fe/gm-crypto?utm_source=csdn_github_accelerator
sm-cryptonpm install --save sm-crypto
ts若不能正常运行需执行:
npm i --save-dev @types/sm-crypto
https://www.npmjs.com/package/sm-crypto
gm-cryptnpm install gm-crypthttps://www.npmjs.com/package/gm-crypt

二、国密4/3/2加解密

1、国密4

(1)gm-crypto

/**
 * 加密解密方法
 */
import { SM4 } from 'gm-crypto'

export class EncryptionUtil {
   key: string // 密钥

   constructor({ keys = '' } = {}) {
     // 任意32位十六进制字符串 || 示例密钥
     this.key = keys || '0123456789abcdeffedcba9876543210'
   }

   // 国密4加密(明文,密钥)
   smEncrypt(text: any, k: string) {
     const k1 = k || this.key // key值与后端一致
     // CBC(cipher block chaining)模式,cbc比ecb模式多加一个iv的参数同key
     const sm4Encrypt = SM4.encrypt(text, k1, {
       iv: k1,
       mode: SM4.constants.CBC,
       inputEncoding: 'utf8',
       outputEncoding: 'hex'
     })
     // ECB(electronic codebook)模式
     // const sm4Encrypt = SM4.encrypt(text, k1, {
     //   inputEncoding: 'utf8',
     //   outputEncoding: 'hex'
     // })
     return sm4Encrypt
   }

   // 国密4解密(密文,密钥)
   smDecrypt(text: any, k: string) {
     const k1 = k || this.key // key值与后端一致
     // CBC
     const sm4Decrypt = SM4.decrypt(text, k1, {
       iv: k,
       mode: SM4.constants.CBC,
       inputEncoding: 'base64',
       outputEncoding: 'utf8'
     })
     // ECB
     // const sm4Decrypt = SM4.decrypt(text, k1, {
     //   inputEncoding: 'base64',
     //   outputEncoding: 'utf8'
     // })
     return sm4Decrypt
   }
}
// 明文示例: SM4 国标对称加密
// ECB示例密文: A9TLmWvl16D5xheKUxlINfhkGRQjPrHDukbYnKI82QI=
// CBC示例密文: 62f78c8c19c7f9fee800ca4f3c31cb261a4e68634fd76280faf292f1dd739665

(2)sm-crypto(加密可行,解密不适配后端)

/**
 * 加密解密方法
 */
const sm4 = require('sm-crypto').sm4

export class EncryptionUtil {
   key: string

   constructor({ keys = '' } = {}) {
     // 可以为16进制串或字节数组,要求为128比特 || 示例密钥
     this.key = keys || '3961794a786e7a78512a4544712a396b'
   }

   // 国密4加密
   smEncrypt(text: any, k: string) {
     // cbc模式
     const sm4Encrypt = sm4.encrypt(text, k || this.key, {
       mode: 'cbc',
       iv: k || this.key
     })
     // ecb模式
     //  const sm4Encrypt = sm4.encrypt(text, k || this.key)
     // 示例明文:SM4 加密,sm-crypto依赖
     // 示例密文:9bf9fbb5132b4843e54659dc5dd659559c338a85f7e7ca7e0041fcb02d666b79
     return sm4Encrypt
   }

   // 国密4解密 (此依赖国密4解密输出为UTF8,而后端都是base64,故不能解密)
   smDecrypt(text: any, k: string) {
     // cbc模式
     const sm4Decrypt = sm4.decrypt(text, k || this.key, {
       mode: 'cbc',
       iv: k || this.key
     })
     // ecb模式
     //  const sm4Decrypt = sm4.decrypt(text, k || this.key)
     return sm4Decrypt
   }
}

(3)gm-crypt(只支持国密4加密,秘钥为16位字符串)

/**
 * 加密解密方法
 */
import { sm4 } from 'gm-crypt'

export class EncryptionUtil {
  key: string

  constructor({ keys = '' } = {}) {
    // 密钥16位
    this.key = keys || 'jhmyApp202072ymt'
  }

  // 国密4加密
  smEncrypt(text: any, k: string) {
    // k:例 2023Z07@14a15!00  16个字符
    // eslint-disable-next-line new-cap
    // cbc模式
    const sm4Instance = new sm4({
      key: k || this.key, // key值与后端一致
      mode: 'cbc',
      iv: k || this.key,
      cipherType: 'base64'
    })
    // ecb模式
    // const sm4Instance = new sm4({
    //   key: k || this.key, // key值与后端一致
    //   mode: 'ecb', // 加密的方式有两种,ecb和cbc两种,这里使用的是ecb,cbc模式还要加一个iv的参数,ecb不用
    //   cipherType: 'base64' // 密码数据的类型;可以是“base64”或“text”,代表TextEncoder和Base64.js
    // })
    return sm4Instance.encrypt(text)
    // 密文cbc:J2IMKFP9NZfbiH5ofW8ZIIbS6OSVFbmwt+pyw3jeX3Zh+JICZlarkplAQ//WaunH
    // 密文ecb:djN+QRtD9T27fJ1K1gcryFg/DwZUkJmrgWdEDBg0xqc=
  }

  // 国密4解密
  smDecrypt(text: any, k: string) {
    // cbc模式
    // eslint-disable-next-line new-cap
    const sm4Instance = new sm4({
      key: k || this.key, // key值与后端一致
      mode: 'cbc',
      iv: k || this.key,
      cipherType: 'base64'
    })
    // ecb模式
    // const sm4Instance = new sm4({
    //   key: k || this.key, // key值与后端一致
    //   mode: 'ecb', // 加密的方式有两种,ecb和cbc两种,这里使用的是ecb,cbc模式还要加一个iv的参数,ecb不用
    //   cipherType: 'base64'
    // })
    return sm4Instance.decrypt(text)
    // 明文cbc:中国国密4-cbc 加解密算法
    // 明文ecb:中国国密加解密算法
  }
}

备注:(3)gm-crypt的国密4加密,需要修改文件 node_modules\gm-crypt\src\crypt.js 如下
改1:return unescape(encodeURIComponent(str)).split(‘’).map(function(val) {return val.charCodeAt();});
改2:return decodeURIComponent(escape(String.fromCharCode.apply(null, strBuffer)));

在这里插入图片描述

2、国密3(仅支持加密,不能解密)

(1)gm-crypto

import { SM3 } from 'gm-crypto'

export class EncryptionUtil {
  // 国密3加密
  smEncrypt() {
    // eslint-disable-next-line new-cap
    const sm3Encrypt = SM3.digest('国密3加密,不可解密', 'utf8', 'hex')
    return sm3Encrypt
  }
}

(2)sm-crypto(后端仅适配杂凑加密,hmac加密后台不支持)

export class EncryptionUtil {
  // 国密3加密
  smEncrypt() {
    const sm3Encrypt0 = sm3('abc') // 杂凑加密,示例密文:66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0
    return sm3Encrypt
  }
}

3、国密2

(1)gm-crypto

import { SM2 } from 'gm-crypto'

export class EncryptionUtil {
   // 前端密钥
   keyClass: any = {
     publicKey: '', // 公钥加密
     privateKey: '' // 私钥解密
   };
   constructor(/* 亦可后端传参密钥 */) {
     // 前端随机生成密钥
     this.keyClass = SM2.generateKeyPair()
   }

   // 国密2加密
   smEncrypt(text: any/* , k: string 后端传公钥 */) {
     // eslint-disable-next-line new-cap
     // 公钥加密
     const sm2Encrypt = SM2.encrypt(text, this.keyClass.publicKey, {
       inputEncoding: 'utf8',
       outputEncoding: 'hex',
       pc: true
     })
     // 示例公钥:"publicKey":"04a8d6bff96d3a7d1352ab69d10e35d93b7a9cc9bd69aff3d5946a0a5b1c2a454f94f06e99aa080088a27f49d7407ca930069274e21f1923f6a537ae8a9e62e85a"
     // 示例明文:SM2 椭圆曲线公钥密码算法
     // 示例密文:04bc77866178b842cb8fc0242cf359416c57b95a991d2a0cebca15fe9f2484c0c99f8b6c4f4f0856160a0f053de0acf1a205935e43c45cff35ec2b5e464f271b0ccb2fec37cdb5b6e71e7528205d6a08b1040ae6069a25b7e575053185e7b2ab00f423c7ed79fb06d1baeab4f4ad780521d93dedca96a5ebd0d70a239d7969244ced68
     return sm2Encrypt
   }

   // 国密2解密
   smDecrypt(text: any/* , k: string 后端传私钥 */) {
     // eslint-disable-next-line new-cap
     // 私钥解密
     const sm2Decrypt = SM2.decrypt(text, this.keyClass.privateKey, {
       inputEncoding: 'base64',
       outputEncoding: 'utf8',
       pc: true
     })
     // 示例私钥:71542a6cc09d9e06e9f1e1c305fc24dc51b0ee91b5b1fe0ed7b31e5d6f71d6e1
     // 示例密文:BDLfCL0Ds0ohVBjcraUxPhf/GrWCXmoRoBfrjEID7siTLu+EiTqKY3da6oRkKfICJvk0sxS/dnm4k/MEp9CAsGWUOFbOsidbp37Jn4h8PRhyVPMKSDD/e1j+ntC+BpTBlOrC0Vd02Wod61IfpDAcl0XepD5uIIsn1Enf5G/6RQlLfFnBjT4uozgoU0cSVP6LNJrv3FyKhKpd2bxM1CvSFXWPwyAP/DGGcg==
     // 示例明文: {  "zoneCode":3202000000,  "orderType":4,  "curdepartment":"3202810201"}
     return sm2Decrypt
   }
}

备注:(1)gm-crypto的国密2需修改文件 node_modules\gm-crypto\types\index.d.ts 如下

在这里插入图片描述

(2)sm-crypto

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

export class EncryptionUtil {
   // 前端密钥
   keyClass: any = {
     publicKey: '',
     privateKey: ''
   };

   constructor() {
     // 前端生成密钥
     this.keyClass = sm2.generateKeyPairHex()
     // 示例密钥
     //  this.keyClass.publicKey = '04799a2643d99ed67ef52b196c56d79feecf2b2cad229be4ff5516b3eba0bbb80443f865cb1bd58c3df56112eb67ee88d60c6a513c6a3db9d4f0f9a2f9741004f4'
     //  this.keyClass.privateKey = '47ec13b27eb05008e7afe8d86ef61addbad779192e7846291b64bfb3b321c5f1'
   }

   // 国密2加密
   smEncrypt(text: any/* , k: string */) {
     const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
     // 示例明文'hello sm2 by sm-crypto~'
     // 公钥加密
     const sm2Encrypt = sm2.doEncrypt(text, this.keyClass.publicKey, cipherMode)
     return sm2Encrypt
   }

   // 国密2解密(传给后端时,密文前+'04')
   smDecrypt(text: any/* , k: string */) {
     const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
     // 私钥解密
     const sm2Decrypt = sm2.doDecrypt('04' + text, this.keyClass.privateKey, cipherMode)
     // 示例密文
     // text = '04' + '25d4d19fcc23750a7b470824780e84dc0ae0af5e44d9aa667c0096df9be6deb6ce36ae27142523270080b9a2916bd1316740ac65c6591b4906f0c2dc68dba29a07b10e867a050cabca65c0c054d3408cbd549a684b39dd556a7904822035b8bdc7b7021366324d47f673a337e3b453a0f28bec47891f3b'
     // 示例明文 hello sm4 by sm-crypto~
     return sm2Decrypt
   }
}

三、其他

1、AES

配合后端加解密改造,AES(mode:GCM;padding:nopadding)
公众号/平台端无需安装新依赖,小程序需安装新依赖

(1)公众号js代码:

import crypto from 'crypto'

export class EncryptionUtil {
  constructor({ key } = {}) {
    this.key = key || 'Q6PL3a64b2*%%fcb' // 后台提供的aes密钥
  }

  // 加密
  smEncrypt(text, k) {
    const key = k || this.key
    // 加密
    const cipher = crypto.createCipheriv('aes-128-gcm', key, key)
    const encrypted = cipher.update(text, 'utf8')
    cipher.final()
    const tag = cipher.getAuthTag()
    const res = Buffer.concat([encrypted, tag])
    return res.toString('base64')
    // text = 'aes加密测试' 示例明文
    // k = 'Q6PL3a64b2*%%fcb' 示例密钥
    // aes加密结果示例: 4S5Q6zDDmywND2XboytC1YWAgqk9d5InliXFmwsftg==
  }

  // 解密
  smDecrypt(text, k) {
    const key = k || this.key
    // 解密
    var bData = Buffer.from(text, 'base64')
    const tag1 = bData.slice(-16)
    const cdata = bData.slice(0, bData.length - 16)
    const decipher = crypto.createDecipheriv('aes-128-gcm', key, key)
    decipher.setAuthTag(tag1)
    var msg = decipher.update(cdata)
    const fin = decipher.final()
    const decryptedStr = new TextDecoder('utf8').decode(Buffer.concat([msg, fin]))
    return decryptedStr
    // 示例密文:text='4S5QLtACCOKrDFrwritRC9kYmxsqbOi2NSX2K2PGoV1aAq+2AQ=='
    // k = 'Q6PL3a64b2*%%fcb' 示例密钥
    // aes解密结果示例: aes java 加密测试
  }
}

(2)小程序ts代码:

安装依赖:npm install crypto
         npm install --save vue-buffer

/**
 * AES-GCM-nopadding
 */
const crypto = require('crypto')
const Buffer = require('vue-buffer')

export class EncryptionUtil {
  key: string

  constructor({ key } = {}) {
    this.key = key || 'Q6PL3a64b2*%%fcb'
  }

  // 加密(明文,密钥)
  smEncrypt(text: any, k:string) {
    k = k || this.key
    const cipher = crypto.createCipheriv('aes-128-gcm', k, k)
    const encrypted = cipher.update(text, 'utf8')
    cipher.final()
    const tag = cipher.getAuthTag()
    const res = Buffer.concat([encrypted, tag])
    const r = res.toString('base64')
    return r
  }

  // 解密(密文,密钥)
  smDecrypt(text: any, k:string) {
    k = k || this.key
    var bData = Buffer.from(text, 'base64')
    const tag1 = bData.slice(-16)
    const cdata = bData.slice(0, bData.length - 16)
    const decipher = crypto.createDecipheriv('aes-128-gcm', k, k)
    decipher.setAuthTag(tag1)
    var msg = decipher.update(cdata)
    const fin = decipher.final()
    const decrypted = new TextDecoder('utf8').decode(Buffer.concat([msg, fin]))
    return decrypted
  }
}

2、RSA

配合后端加解密改造,RSA(mode:ECB;padding:OAEPWITHSHA-256ANDMGF1PADDING)

安装依赖:npm install node-forge

/**
 * RSA-ECB-padding: OAEPWITHSHA-256ANDMGF1PADDING
 */
const forge = require('node-forge')

export class EncryptionUtil {
    publicKey: string // 公钥
    privateKey: string // 私钥

    constructor() {
      // 示例公钥、私钥
      this.publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFJw1dxTTWtuztr6eXLPPvIo2zWVPioJ4x3NKw0RD0YhxYe2r5XjKAIVqwxDKwpQv6+GImbI41rjUEmgkGQhtp+zgAJj2ANrFXKdAbgXnUHYhpT/h4UoemF8uTEVmA826Zex//xkjeMdXsLb9aYAqutseQaMra51T+sbjLElUV2wIDAQAB'
      this.privateKey = 'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMUnDV3FNNa27O2vp5cs8+8ijbNZU+KgnjHc0rDREPRiHFh7avleMoAhWrDEMrClC/r4YiZsjjWuNQSaCQZCG2n7OAAmPYA2sVcp0BuBedQdiGlP+HhSh6YXy5MRWYDzbpl7H//GSN4x1ewtv1pgCq62x5BoytrnVP6xuMsSVRXbAgMBAAECfxuphVQD9nHAEpjFgl0pfsQAI9vLbBQuQC06c2oPQNYpqkBQK0hcMtcuh3CMjH6O5LKP1N1mHSEeiyuVtPgCoOprfV8G+JNRMYfaNYErtN/WCj2SfIZ9FiPckaOFwaBqUISk5p3qqZu3mSkjfMCjJPUb1hm15IIEYg1Tl5CoEIkCQQD0cn/Ml1lJ/VGXSHW/ME+noTU2a2G5iOLd2koqMipOXKF0m6bJY1sA+uu+j/UpsecIrCDIJJRfk07fgtAg87V1AkEAznhY3eL7qkZEu8nqkZi9iqpyQW0ZepWFLF6vt3INP/2itrCbvh7iNxV2Oef/+OeWcc8m/87oZGhPgVpOXkUkDwJAFFuczRslsoXIT8MXG08Ysys31UpoHx2JV1SgrJb08wW/5Ig6AbemkpRTIdG3ZzuLtCsxp7l0KemIvhCU6MmjKQJBAKfz7943KR8e4ASeQKjFRdIJyr18ARDdliI8t9WS+kJGkVjpGxexybSjSbPbDDcuNAxKRWArsJEU5S/FBSDcP3MCQQDPPcnjEWCSmI6lKmaCUfYblCEzySEeyr2V4eXzJEGK4GbZQ6ESd7MhITsgDwaZbt/Eb8ai+QMqXTmK4qnLOcIl'
    }

    // 加密(明文,公钥)
    smEncrypt(text: any, k:string) {
      // text = 'ceshi测试' 示例明文
      k = this.publicKey // 示例公钥
      const publicKeyAll = '-----BEGIN PUBLIC KEY-----\n' + k + '\n-----END PUBLIC KEY-----'
      const pKey = forge.pki.publicKeyFromPem(publicKeyAll)
      const buffer = forge.util.createBuffer(text, 'utf8')
      const bytes = buffer.getBytes()
      // 使用公钥加密
      const encrypted = forge.util.encode64(pKey.encrypt(bytes, 'RSA-OAEP', {
        md: forge.md.sha256.create(),
        mgf1: {
          md: forge.md.sha256.create()
        }
      }))
      return encrypted
      // 示例密文:FGFTjGb7D9uWIP0R5hCbTVeqqJJIt4FUlrVvtVg7QIYcL3gABS5dqw4KHeq8rJU2mtTq2t965kuk7OUWLPjUxvQ300nhhtbUsH/gI7XrCZuYv8xOylgVq0L1Wk5kSXxLqf27jvPShcS1KkGOfk9eO9Grgoq1+dD8Hi0XIh6DXts=
    }

    // 解密(密文,私钥)
    smDecrypt(text: any, k:string) {
      // text = 'jNxkgLRjsp9Nh8L4kJwRDUcoNGQxdYC0LPX0Ml7aVVE/rMH/kEDWgMXDtVDuqnxqRQbxH1v6BQuQWNlV9y/KCKo+ont5lopWS9xyiKdNmJdZvAOJogVy34E9QFJLBxHvpBFodRhcyyNgWfzxtnHFbfyF8cRLYPgkeSacVP5hfzc=' 示例密文
      k = this.privateKey // 示例私钥
      const priveKeyAll = '-----BEGIN PRIVATE KEY-----\n' + k + '\n-----END PRIVATE KEY-----'
      const privateKey = forge.pki.privateKeyFromPem(priveKeyAll)
      const b = forge.util.decode64(text, 'base64')
      // 使用私钥解密
      const decrypted = forge.util.decodeUtf8(privateKey.decrypt(b, 'RSA-OAEP', {
        md: forge.md.sha256.create(),
        mgf1: {
          md: forge.md.sha256.create()
        }
      }))
      return decrypted
    }
}

3、MD5(不可解密)

安装依赖:npm install crypto-js
const CryptoJS = require('crypto-js')

export class EncryptionUtil {
  // 加密
  smEncrypt(text: any) {
    text = 'MD5加密'
    const encrypted = CryptoJS.MD5(text).toString()
    console.log(encrypted)
    return encrypted
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值