sm/4.js

import { SM4 } from "../../utils/sm4"
/**
 * sm4
 * @category sm
 * @alias sm4
 * @param {string|Uint8Array} originalData - 待加密的数据
 * @param {string|Uint8Array} key 加密密钥
 * @param {Object} [options] 加密选项
 * @param {('ecb'|'cbc')} [options.mode='ecb'] 加密模式
 * @param {('pkcs7'|'none')} [options.padding='pkcs7'] 填充方式
 * @param {('hex'|'array')} [options.output='hex'] 输出格式
 * @param {string|Uint8Array} [options.iv] 初始向量
 * @returns {string|Uint8Array} 加密后的数据
 * @example
 * 加密
 * import {sm4} from "jxk"
 * const msg = '我是原始数据' // 可以为 utf8 串或字节数组
 * const key = '5e0a3ab263b283e3db6001018776c4f0' // 可以为 16 进制串或字节数组,要求为 128 比特  *
 * let encryptData = sm4.encrypt(msg, key) // 加密,默认输出 16 进制字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 充)
 * let encryptData = sm4.encrypt(msg, key, {padding: 'none'}) // 加密,不使用 padding
 * let encryptData = sm4.encrypt(msg, key, {padding: 'none', output: 'array'}) // 加密,不使用 padding,输出为字节数组
 * let encryptData = sm4.encrypt(msg, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 加密,cbc 模式
 * @example
 * 解密
  import {sm4} from "jxk"
  const encryptData =  'aaff18e2a966d10017469a492b800169d68e6f979da91cdeed454bb769665892' // 可以为 16 进制串或字节数组
  const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
  let decryptData = sm4.decrypt(encryptData, key) // 解密,默认输出 utf8 字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
  let decryptData = sm4.decrypt(encryptData, key, {padding: 'none'}) // 解密,不使用 padding
  let decryptData = sm4.decrypt(encryptData, key, {padding: 'none', output: 'array'}) // 解密,不使用 padding,输出为字节数组
  let decryptData = sm4.decrypt(encryptData, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 解密,cbc 模式
 * @author xkloveme <xkloveme@gmail.com>
 * @Date: 2024-08-10 21:53:59
 */
export default {
  /**
   * 加密数据
   * @param {string|Uint8Array} originalData - 待加密的数据
   * @param {string|Uint8Array} key - 加密密钥
   * @param {Object} [options] - 加密选项
   * @param {('ecb'|'cbc')} [options.mode='ecb'] - 加密模式
   * @param {('pkcs7'|'none')} [options.padding='pkcs7'] - 填充方式
   * @param {('hex'|'array')} [options.output='hex'] - 输出格式
   * @param {string|Uint8Array} [options.iv] - 初始向量
   * @returns {string|Uint8Array} - 加密后的数据
   */
  encrypt: (originalData, key, options = {}) => {
    if (originalData === '' || originalData === null || originalData === undefined) {
      return originalData;
    }
    try {
      const encrypted = SM4(originalData + '', key, 1, options);
      if (options.output === 'array') {
        return encrypted;
      } else {
        return encrypted.toString('hex');
      }
    } catch (error) {
      console.error('🐛: ~ encrypt ~ error:', originalData, error);
      return originalData;
    }
  },

  /**
   * 解密数据
   * @param {string|Uint8Array} encryptedData - 待解密的数据
   * @param {string|Uint8Array} key - 解密密钥
   * @param {Object} [options] - 解密选项
   * @param {('ecb'|'cbc')} [options.mode='ecb'] - 解密模式
   * @param {('pkcs7'|'none')} [options.padding='pkcs7'] - 填充方式
   * @param {('utf8'|'array')} [options.output='utf8'] - 输出格式
   * @param {string|Uint8Array} [options.iv] - 初始向量
   * @returns {string|Uint8Array} - 解密后的数据
   */
  decrypt: (encryptedData, key, options = {}) => {
    if (encryptedData === '' || encryptedData === null || encryptedData === undefined) {
      return encryptedData;
    }

    try {
      const decrypted = SM4(encryptedData, key, 0, options);
      if (decrypted === '') {
        throw new Error('Decryption failed')
      }
      if (options.output === 'array') {
        return decrypted;
      } else {
        const decryptedStr = decrypted.toString('utf8');
        try {
          // 尝试解析为 JSON 对象
          if(decryptedStr.includes('}') || decryptedStr.includes(']')){
            return JSON.parse(decryptedStr);
          }else{
            return decryptedStr;
          }
        } catch (parseError) {
          // 如果解析失败,返回原始字符串
          return decryptedStr;
        }
      }
    } catch (error) {
      console.error('🐛: ~ decrypt ~ error:', encryptedData, error);
      return encryptedData;
    }
  }
}