• vue项目中使用crypto-js加密


    https://blog.csdn.net/ddx2019/article/details/102964182

    https://www.cnblogs.com/chaoyuehedy/p/9947381.html

    以上两种方法我用得时候报错:Uncaught Error: Malformed UTF-8 data     at Object.stringify (crypto-js.js:478)     at WordArray.init.toString (crypto-js.js:215)  ,没找到解决方法,就自己进行了封装。。

    以下是自己得封装方法。

    1. 安装:

    npm install crypto-js 或者yarn add crypto-js

    2. 引入crypto-js,并封装加密解密的方法

    secureUtil.js

    /**
     * Created by lijingwei on 2018/1/12.
     */
    import CryptoJS from 'crypto-js'
    
    // SecureUtil = function () {
    
    var CONTRAST = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var DICTIONARIES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()";
    var IV_TEXT = "0102030405060708";
    
    /**
     * 字符串转byte[]
     */
    export function stringToByte(str) {
        var bytes = new Array();
        var len, c;
        len = str.length;
        for (var i = 0; i < len; i++) {
            c = str.charCodeAt(i);
            if (c >= 0x010000 && c <= 0x10FFFF) {
                bytes.push(((c >> 18) & 0x07) | 0xF0);
                bytes.push(((c >> 12) & 0x3F) | 0x80);
                bytes.push(((c >> 6) & 0x3F) | 0x80);
                bytes.push((c & 0x3F) | 0x80);
            } else if (c >= 0x000800 && c <= 0x00FFFF) {
                bytes.push(((c >> 12) & 0x0F) | 0xE0);
                bytes.push(((c >> 6) & 0x3F) | 0x80);
                bytes.push((c & 0x3F) | 0x80);
            } else if (c >= 0x000080 && c <= 0x0007FF) {
                bytes.push(((c >> 6) & 0x1F) | 0xC0);
                bytes.push((c & 0x3F) | 0x80);
            } else {
                bytes.push(c & 0xFF);
            }
        }
        return bytes;
    }
    
    /**
     * byte[]转字符串
     */
    function byteToString(arr) {
        if (typeof arr === 'string') {
            return arr;
        }
        var str = '',
            _arr = arr;
        for (var i = 0; i < _arr.length; i++) {
            var one = _arr[i].toString(2),
                v = one.match(/^1+?(?=0)/);
            if (v && one.length == 8) {
                var bytesLength = v[0].length;
                var store = _arr[i].toString(2).slice(7 - bytesLength);
                for (var st = 1; st < bytesLength; st++) {
                    store += _arr[st + i].toString(2).slice(2);
                }
                str += String.fromCharCode(parseInt(store, 2));
                i += bytesLength - 1;
            } else {
                str += String.fromCharCode(_arr[i]);
            }
        }
        return str;
    }
    
    /**
     * 十六进制字符串转字节数组
     */
    function Str2Bytes(str) {
        var pos = 0;
        var len = str.length;
        if (len % 2 != 0) {
            return null;
        }
        len /= 2;
        var hexA = new Array();
        for (var i = 0; i < len; i++) {
            var s = str.substr(pos, 2);
            var v = parseInt(s, 16);
            hexA.push(v);
            pos += 2;
        }
        return hexA;
    }
    
    /**
     * 字节数组转十六进制字符串
     */
    function Bytes2Str(arr) {
        var str = "";
        for (var i = 0; i < arr.length; i++) {
            var tmp = arr[i].toString(16);
            if (tmp.length == 1) {
                tmp = "0" + tmp;
            }
            str += tmp;
        }
        return str;
    }
    
    /**
     * 字符串插入指定位置字符
     */
    function insertChar(str, char, pos) {
        var oldstrArray = [str.substring(0, pos), str.substring(pos, str.length)];
    //        console.log("拆分后字符串 = %s", oldstrArray.toString());
        var newstr = oldstrArray[0] + char + oldstrArray[1];
    //        console.log("组合后字符串 = %s", newstr);
        return newstr;
    }
    
    /**
     * 加密
     */
    export function encryption(content) {
        content = content.replace(/,/g, "FENGEFU");
    //        console.log("密前文本 = %s", content);
        // 根据DICTIONARIES生成16为动态密钥
        var maxPos = DICTIONARIES.length; // 密钥字典最大长度
        var LEN = 16; // 密钥长度
        var password = ''; // 动态密钥
        var array = new Array(maxPos)
            .fill(0)
            .map((v, i)=>i + 1)
            .sort(()=>0.5 - Math.random())
            .filter((v, i)=>i < LEN); // 生成16个不同随机数,作为字典抽取角标
        for (var i = 0; i < array.length; i++) {
            password += DICTIONARIES.charAt(array[i] - 1);
        }
        // console.log("原始动态密钥 = %s", password);
        // AES加密内容
        var key = CryptoJS.enc.Utf8.parse(password);
        var iv = CryptoJS.enc.Utf8.parse(IV_TEXT)
        var encryptResult = CryptoJS.AES.encrypt(content, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        // 转BASE64,增加加密强度
        var encryptedStr = encryptResult.ciphertext.toString();
        // // encryptedStr = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(encryptedStr));
        // encryptedStr = Bytes2Str(stringToByte(encryptedStr));
        // console.log(encryptedStr);
        // console.log("原始加密后密文 = %s", encryptedStr);
        // 密钥干扰
        var currentTimeMillis = (new Date()).valueOf().toString(); // 获得当前时间戳
        var currentTimeMillisLength = currentTimeMillis.length;
        if (currentTimeMillisLength < 13) { // 解决特殊机型获取当前时间毫秒位数异常
            var missingCount = 13 - currentTimeMillisLength;
            for (var i = 0; i < missingCount; i++) {
                currentTimeMillis = currentTimeMillis + i;
            }
        } else if (currentTimeMillis.length > 13) {
            currentTimeMillis = currentTimeMillis.substring(0, 13);
        }
    //        console.log("当前时间戳 = %s", currentTimeMillis);
    //        console.log("当前时间戳长度 = %s", currentTimeMillis.length);
        var h = new Array(); // 实际插入角标集合
        var arrayTime = new Array(16)
            .fill(0)
            .map((v, i)=>i + 1)
            .sort(()=>0.5 - Math.random())
            .filter((v, i)=>i < currentTimeMillis.length); // 生成16个不同随机数,作为字典抽取角标
        for (var i = 0; i < arrayTime.length; i++) {
    //            console.log("取16位随机数第 %s 位", arrayTime[i] - 1);
            h[i] = arrayTime[i] - 1;
        }
    //        console.log("集合长度 = %s", h.length);
        var indexs = ""; // 插入角标字符串,每位是要插入的角标
        //随机选取要插入干扰字符
        var arrayMix = new Array(13)
            .fill(0)
            .map((v, i)=>i + 1)
            .sort(()=>0.5 - Math.random())
            .filter((v, i)=>i < h.length); // 生成13个不同随机数,作为字典抽取角标
    //        console.log("arrayMix集合长度 = %s", arrayMix.length);
        for (var i = 0; i < arrayMix.length; i++) {
            var charAt = currentTimeMillis.charAt(arrayMix[i] - 1); //取随机干扰字符
    //            console.log("干扰字符 = %s", charAt);
            password = insertChar(password, charAt, h[i]);
    //            console.log("已插入干扰字符密钥 = %s", password);
            indexs += CONTRAST.charAt(h[i]); // 将10进制角标映射为16进制标识方式
        }
        // console.log("混淆插入角标索引集合字符串 = %s", indexs);
        // console.log("混淆后的动态密钥 = %s", password);
        //将角标分成两节(0~6)(6~13)
        var qian = indexs.substring(0, 6);
        var hou = indexs.substring(6, 13);
        //将分好的两节分别拼接到角标前后
        password = qian + password + hou;
    //        console.log("最终携带混淆角标混淆后的动态密钥 = %s", password);
        var result = password + "," + encryptedStr;
        // console.log("最终加密文本 = %s", result);
        var byteResult = stringToByte(result);
    //        console.log("最终字节加密文本 = %s", byteResult);
        var hexResult = Bytes2Str(byteResult).toUpperCase();
        // console.log("最终16进制加密文本 = %s", hexResult);
        // console.log("--------------------------");
        return hexResult;
    }
    
    /**
     * 解密
     * @param content
     */
    export function decryption(content) {
        var btyeMessage = Str2Bytes(content);
    //        console.log("最终16进制转字符串加密文本Byte = %s", btyeMessage);
        var message = byteToString(btyeMessage);
        // console.log("字节转字符串加密文本 = %s", message);
        var resultArray = message.split(",");
    //        console.log("混淆密钥 = %s", resultArray[0]);
        var realMessage = resultArray[1];
        // console.log("实际密文 = %s", realMessage);
        var qian = resultArray[0].substring(0, 6);
        var hou = resultArray[0].substring(resultArray[0].length - 7, resultArray[0].length);
        var indexs16 = qian + hou;
        var password = resultArray[0].substring(6, resultArray[0].length - 7)
        // console.log("干扰字符角标 = %s", indexs16);
        // console.log("干扰后密钥 = %s", password);
        var indexArray = indexs16.split("");
    //        console.log("角标数量 = %s", indexArray);
        for (var i = indexArray.length - 1; i >= 0; i--) {
            var pos = parseInt(indexArray[i], 16); // 16进制字符转10进制字符
    //            console.log("干扰字符角标 = %s", pos);
            password = password.substring(0, pos) + password.substring(pos + 1);
    //            console.log("删除干扰字符后 = %s", password);
        }
        // console.log("实际密钥 = %s", password);
        // AES解密内容
        var key = CryptoJS.enc.Utf8.parse(password);
        var iv = CryptoJS.enc.Utf8.parse(IV_TEXT)
        // realMessage = CryptoJS.enc.Hex.parse(realMessage).toString();
        var encryptedHexStr = CryptoJS.enc.Hex.parse(realMessage);
        var encryptedBase64Str2 = CryptoJS.enc.Base64.stringify(encryptedHexStr);
        var decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str2, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8);
        decryptedStr = decryptedStr.replace(/FENGEFU/g, ",");
        // console.log("最终文本 = %s", decryptedStr);
        return decryptedStr;
    }
    // };
    
    export default {
        encryption,
        decryption
    }

    utils.js

    /**
     * 工具类
     */
    import secureUtils from './secureUtil'
    
    //加密解密
    export function demoRequest(data) {
      var encryptMessage = secureUtils.encryption(data);
      return encryptMessage;
    }
    
    export function demoResponse(data) {
      var decryptMessage = secureUtils.decryption(data);
      return decryptMessage;
    }
    export default {
      demoRequest,
      demoResponse
    }

    3. 在入口文件main.js中使用

    import Utils from './utils/utils'
    Vue.prototype.$Utils = Utils

    在组件中使用

    加密:

    this.$Utils.demoRequest(JSON.stringify(data))

    要加密得数据必须先转为字符串

    解密:

    data = JSON.parse(this.$Utils.demoResponse(res.data))

    解密完转换为JSON对象

    不积跬步无以至千里
  • 相关阅读:
    AcWing:141. 周期(KMP)
    暑假集训
    AcWing:112. 雷达设备(贪心 + 笛卡尔坐标系化区间)
    AcWing:111. 畜栏预定(贪心 + 小根堆)
    20200207总结
    Miku and Generals(二分图染色+可行性dp)
    20200205总结
    Coding Contest(最小费用最大流)
    Wannafly-Winter-Camp day5总结
    Wannafly-Winter-Camp day4总结
  • 原文地址:https://www.cnblogs.com/lyt0207/p/12807433.html
Copyright © 2020-2023  润新知