前端md5,aes,sm2加密的使用

在数据请求和接收时,因为要兼顾系统安全测试,要对接口部分数据或者整个请求体进行加密解密,这时候根据不同的安全要求需要前端使用不同的方法进行实现。

加密算法常用的有三种,分别为散列算法,对称算法,非对称算法。也对应着前端常使用的三种方法md5,aes和sm2。

  • 散列算法是不可逆的,安全姓极高但灵活性不够。常用于对身份信息的验证,例如登录。
  • 对称算法前后端使用同一个密钥,加密速度快,但安全性低于非对称算法。可使用于对安全性要求不高但有需要进行一定的加密的系统。
  • 非对称算法有私钥和公钥的区分,安全性高,但加密和解密的速度较慢。用于对安全性要求严格的系统。
  • 但为了方便以下案例都以登录为例。

1.md5

1.1安装

npm install js-md5 

1.2引用

import md5 from 'js-md5'

1.3使用

axios.post('xxx/login', {
     username: this.username,
     password: md5(this.password)
})

2.aes

2.1安装

npm install crypto-js

2.2引用

import CryptoJS from 'crypto-js'

2.3封装

export default {
    // 加密
    encrypt(word) {
          let stringkey = "5C3TyE5kSHeE2e5a";
          var key = CryptoJS.enc.Utf8.parse(stringkey);
          var srcs = CryptoJS.enc.Utf8.parse(word);
          var resultByte = CryptoJS.AES.encrypt(srcs, key, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7,
          });
          return resultByte.toString();
        },
    // 解密
    decrypt(word) {
        let stringkey = "5C3TyE5kSHeE2e5a";
        var key = CryptoJS.enc.Utf8.parse(stringkeys);
        var resultByte = CryptoJS.AES.decrypt(word, key, {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7,
        });
        return CryptoJS.enc.Utf8.stringify(resultByte).toString();
      },
}

2.4使用

import AES from '@/utils/common/crypto.js'
let json = {
    username: this.username,
    password: this.password,
};
let param = AES.encrypt(JSON.stringify(json));
axios.post('xxx/login', { requestData: param })

3.sm2

3.1安装

npm install --save sm-crypto

3.2引用

const sm2 = require('sm-crypto').sm2 // 获取sm2对象

3.3封装

//为0时在加密的串前加上04,后端才能解密成功,同样后端加密后也会返回带04的加密串给前端,cipherMode为1的话必须去掉04才能解密成功
const cipherMode = 0 // 选择加密策略,1 - C1C3C2,0 - C1C2C3,默认为1
const sysPublicKey = '04A1AEEB6A3A2DD87A9439AAC2E90CF5EC41CE85C6BA98349BE52344951DAE44BCE78FD2A914030F95A7A418D094B9F659BF120488B12DEAFEE58A27D9A4B38DE1' // 系统后台公钥
const uiPrivateKey = '00E51DC7364DE2AB9061677FDFA181CC3438761DEA9E67FC7A19890EC23251DF64' // 前端UI私钥
export default {
    // 加密
    doEncrypt(data){
        //加'04'
        return '04' + sm2.doEncrypt(data, sysPublicKey, cipherMode)  
    },
    // 解密
    doDecrypt(data){
        dataHex = data.substring(2).toLocaleLowerCase()
        return sm2.doDecrypt(dataHex, uiPrivateKey, cipherMode)  
    },
   // 签名(如果需要)
    doSignature(msg){
        return sm2.doSignature(msg, uiPrivateKey, { hash:true, der:true });
    }
}

3.4使用

import SM from '@/utils/common/sm2.js'

let json = {
    username: this.username,
    password: this.password,
};
let param = SM.doEncrypt(JSON.stringify(json));
//请求头加入接口签名(如果需要)
let timestamp = new Date().getTime().toString();
let sign = SM.doSignature(timestamp);
axios.post('xxx/login', { requestData: param },{headers:{'timestamp':timestamp,'sign':sign}})

当然以上都为简单使用,针对灵活性高,数据格式复杂例如formdata,file等格式等的请求体进行加密和解密还要在此基础上增加封装,这里贴出一个案例供大家思考。

const sm2 = require('sm-crypto').sm2 // 获取sm2对象
const cipherMode = 0 // 选择加密策略,1 - C1C3C2,0 - C1C2C3,默认为1
const sysPublicKey = '04A1AEEB6A3A2DD87A9439AAC2E90CF5EC41CE85C6BA98349BE52344951DAE44BCE78FD2A914030F95A7A418D094B9F659BF120488B12DEAFEE58A27D9A4B38DE1' // 系统后台公钥
const uiPrivateKey = '00E51DC7364DE2AB9061677FDFA181CC3438761DEA9E67FC7A19890EC23251DF64' // 前端UI私钥
// 开启全局加密
const enableGlobal = false;
// 必须加密请求体的请求
const mustEncryptRequestBodyUrls = [
  // '/configuration/taskManage/save','/oauth/login'
]
// 不加密请求体的请求
const forbiddenEncryptRequestBodyUrls = []

/**
 * 是否为必须加密请求体的请求
 * @param {*} url 
 * @returns 
 */
function isMustEncryptRequestBodyUrls(url){
  return mustEncryptRequestBodyUrls.filter(element => element == url).length > 0
}

/**
 * 是否为不加密请求体的请求
 * @param {*} url 
 * @returns 
 */
 function isForbiddenEncryptRequestBodyUrls(url){
  return forbiddenEncryptRequestBodyUrls.filter(element => element == url).length > 0
}

/**
 * SM2加密string数据
 * @param {string} data 原始数据
 * @returns {string} 加密后数据
 */
function getSm2DataHexByString(data) {
  if (data && (typeof data === 'string') && data.constructor === String) {
    return '04' + sm2.doEncrypt(data, sysPublicKey, cipherMode)
  }
  return null
}

/**
 * SM2加密object数据
 * @param {Object} data 原始数据
 * @returns {string} 加密后数据
 */
 function getSm2DataHexByObject(url,data) {
  if (data) {
    if(data instanceof FormData) {
      if(url === '/configuration/cnfTaskDeliver/add') {
        return '04' + sm2.doEncrypt(JSON.stringify(data), sysPublicKey, cipherMode)
      } else {
        let formData = new FormData();
        data.forEach((value,key)=>{
          if(value instanceof File) {
            formData.append(key,value);
          } else {
            if(typeof(value) === 'string') {
              if(value!==''&&value!==null) {
                formData.append(key,'04' + sm2.doEncrypt(value, sysPublicKey, cipherMode));
              }
            } else {
              if(value!==''&&value!==null) {
                formData.append(key,'04' + sm2.doEncrypt(JSON.stringify(value), sysPublicKey, cipherMode));
              }
            }
          }
        })
        return formData;
      }
      
      /* if(validType("[object File]",data)) {
        return '04' + sm2.doEncrypt(JSON.stringify(data), sysPublicKey, cipherMode)
      } else {
        let formData = new FormData();
        data.forEach((value,key)=>{
          if(value instanceof File) {
            formData.append(key,value);
          } else {
            if(typeof(value) === 'string') {
              if(value!==''&&value!==null) {
                formData.append(key,'04' + sm2.doEncrypt(value, sysPublicKey, cipherMode));
              }
            } else {
              if(value!==''&&value!==null) {
                formData.append(key,'04' + sm2.doEncrypt(JSON.stringify(value), sysPublicKey, cipherMode));
              }
            }
          }
        })
        return formData;
      } */
    } else {
      return '04' + sm2.doEncrypt(JSON.stringify(data), sysPublicKey, cipherMode)
    }
  }
  return null
}

/**
 * SM2解密数据
 * @param {string} dataHex 原始加密数据
 * @returns {string} 解密后数据
 */
function getSm2DataByString(dataHex) {
  if (dataHex && (typeof dataHex === 'string') && dataHex.constructor === String) {
    dataHex = dataHex.substring(2).toLocaleLowerCase()
    return sm2.doDecrypt(dataHex, uiPrivateKey, cipherMode)
  }
}

/**
 * SM2签名
 * @param {string} msg 
 * @returns 
 */
function doSignature(msg){
    return sm2.doSignature(msg, uiPrivateKey, { hash:true, der:true });
}

/* 判断data是不是formData类型 */
function validType(val,formData) {
  const types = [];
  for(let key of formData.keys()) {
    types.push(Object.prototype.toString.call(formData.get(key)));
  }
  return types.every(item => item === Object.prototype.toString.call(val));
}

export default {
  enableGlobal,
  mustEncryptRequestBodyUrls,
  forbiddenEncryptRequestBodyUrls,
  isMustEncryptRequestBodyUrls,
  isForbiddenEncryptRequestBodyUrls,
  getSm2DataHexByString,
  getSm2DataHexByObject,
  getSm2DataByString,
  doSignature
}

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值