• JavaScript实现AES算法加密和解密


    JavaScript的加密和解密用的是google的CryptoJS库。本文以AES/ECB/NoPadding为例展示AES加密和解密的方法。

    需要下载CryptoJS库,下载地址如下:
    https://github.com/sytelus/CryptoJS

    需要引入库文件:
    <script src="./CryptoJS-master/rollups/aes.js"></script>
    <script src="./CryptoJS-master/components/mode-ecb.js"></script>
    <script src="./CryptoJS-master/components/pad-nopadding.js"></script>

    加密方法:

    function encrypt(str) {
        var decArray = hexStrToDecArray(str);
        var wordArray = int8parse(decArray);
        var encrypted = CryptoJS.AES.encrypt(wordArray, aesKeyBytes(), {
            mode: CryptoJS.mode.ECB, 
            padding: CryptoJS.pad.NoPadding
        });
        return wordArrayToHexStr(encrypted.ciphertext.words);
    }

    这个方法传入的是十六进制字符串,格式为"AA BB CC DD EE FF";
    hexStrToDecArray()方法用来将十六进制字符串转换成十进制数字的数组;
    int8parse()方法用来将十进制数字转换成CryptoJS所需要的wordArray数组;
    最后,encrypt()方法加密得到的是一个wordArray数组,wordArrayToHexStr()再将其解析成十六进制字符串。

    解密方法:

    function decrypt(str) {
        var decArray = hexStrToDecArray(str);
        var wordArray = int8parse(decArray);
        var base64Str = CryptoJS.enc.Base64.stringify(wordArray);
        var decrypted = CryptoJS.AES.decrypt(base64Str, aesKeyBytes(), {
            mode: CryptoJS.mode.ECB, 
            padding: CryptoJS.pad.NoPadding
        });
        return wordArrayToHexStr(decrypted.words);
    }

    解密方法同加密方法类似,但是CryptoJS.AES.decrypt()方法需要传入Base64格式的加密字符串,因此这里需要先使用CryptoJS.enc.Base64.stringify()方法做一次转换。

    以下是完整的Demo代码:

    <!DOCTYPE html>
    <html>
    <head>
    <script src="./CryptoJS-master/rollups/aes.js"></script>
    <script src="./CryptoJS-master/components/mode-ecb.js"></script>
    <script src="./CryptoJS-master/components/pad-nopadding.js"></script>
    <script>
    function encryptText() {
        var plain = document.getElementById("plain").value;
        console.log("plain: " + plain);
        var encrypted = encrypt(plain);
        console.log("encrypted: " + encrypted);
        document.getElementById("encrypted").value = encrypted;
    }
    
    function decryptText() {
        var encrypted = document.getElementById("todecrypt").value;
        console.log("encrypted: " + encrypted);
        var decrypted = decrypt(encrypted);
        console.log("decrypted: " + decrypted);
        document.getElementById("decrypted").value = decrypted;
    }
    
    // 加解密用到的密钥
    function aesKeyBytes() {
        var key_Int = new Int8Array([65, 144, 48, 53, 18, 52, 86, 120, 131, 116, 124, 139, 237, 203, 169, 135]);
        var keyBytes = int8parse(key_Int);
        return keyBytes;
    }
    
    // 十六进制字符串数组,个数如果不足16整数倍则补0
    function hexTo16Hex(str) {
        var diff = 16 - (str.length + 1) / 3 % 16;
        for(var i = 0; i < diff; i++) {
            str = str + " 00";
        }
        return str;
    }
    
    // AES加密
    function encrypt(str) {
        var decArray = hexStrToDecArray(str);
        var wordArray = int8parse(decArray);
        var encrypted = CryptoJS.AES.encrypt(wordArray, aesKeyBytes(), {
            mode: CryptoJS.mode.ECB, 
            padding: CryptoJS.pad.NoPadding
        });
        return wordArrayToHexStr(encrypted.ciphertext.words);
    }
    
    // AES解密
    function decrypt(str) {
        var decArray = hexStrToDecArray(str);
        var wordArray = int8parse(decArray);
        var base64Str = CryptoJS.enc.Base64.stringify(wordArray);
        var decrypted = CryptoJS.AES.decrypt(base64Str, aesKeyBytes(), {
            mode: CryptoJS.mode.ECB, 
            padding: CryptoJS.pad.NoPadding
        });
        return wordArrayToHexStr(decrypted.words);
    }
    
    // 构建WordArray对象
    function int8parse(u8arr) {
      var len = u8arr.length;
      var words = [];
      for (var i = 0; i < len; i++) {
          words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
      }
      return CryptoJS.lib.WordArray.create(words, len);
    }
    
    // 十六进制字符串(空格分割)转成十进制数字的数组
    function hexStrToDecArray(str) {
        var strArray = str.split(" ");
        var decArray = [];
        for(var i = 0; i < strArray.length; i++) {
            decArray.push(parseInt(strArray[i], 16));
        }
        return arrayTo16Array(decArray);
    }
    
    // 十进制数组转成十六进制字符串
    function decArrayToHexStr(array) {
        var hexStr = "";
        for(var i = 0; i < array.length; i++) {
            var str = array[i].toString(16).toUpperCase();
            if (str.length < 2) {
                str = "0" + str;
            }
            hexStr = hexStr + str + " ";
        }
        return hexStr.substr(0, hexStr.length - 1);
    }
    
    // word类型的十进制数组转成十六进制字符串
    function wordArrayToHexStr(array) {
        var hexStr = "";
        for(var i = 0; i < array.length; i++) {
            var num = array[i];
            if (num < 0) {
                num = array[i] + 0x100000000;
            }
            var str = num.toString(16).toUpperCase();
            var fullStr = str;
            if (str.length < 8) {
                for(var j = 0; j < 8 - str.length; j++) {
                    fullStr = "0" + fullStr;
                }
            }
            hexStr = hexStr + fullStr;
        }
        var ret = "";
        for(var i = 0; i < hexStr.length; i += 2) {
            ret = ret + hexStr.substr(i, 2) + " "
        }
        return ret.substr(0, ret.length - 1);
    }
    
    // 数组元素个数必须是16的整数倍,不足的在后面补0
    function arrayTo16Array(array) {
        var len = array.length;
        var distLen = parseInt((array.length - 1) / 16) * 16 + 16;
        for(var i = array.length; i < distLen; i++) {
            array[i] = 0;
        }
        return array;
    }
    </script>
    </head>
    <body>
        <h1>加解密测试</h1>
        AES128,ECB模式,PaddingModeZeros,不足部分补0
        <br>
        <input id="plain" type="text" style="500px; height:20px;"/>
            <button type="button" onclick="encryptText()">加密</button>
        <input id="encrypted" type="text" style="500px; height:20px;" />
        <br>
        <br>
        <br>
        <input id="todecrypt" type="text" style="500px; height:20px;"/>
            <button type="button" onclick="decryptText()">解密</button>
        <input id="decrypted" type="text" style="500px; height:20px;" />
    </body>
    </html>

    在浏览器中打开之后效果如下:

    输入要加密或解密的字符串,点击加密/解密按钮即可。

  • 相关阅读:
    洛谷 1842 [USACO05NOV]奶牛玩杂技【贪心】
    洛谷 1757 通天之分组背包【分组背包】
    洛谷 1330 封锁阳光大学
    洛谷 1019 单词接龙
    【模板】CDQ分治
    BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】
    BZOJ 2457 [BeiJing2011]双端队列
    洛谷 2015 二叉苹果树
    牛客网 牛可乐发红包脱单ACM赛 C题 区区区间间间
    牛客网 牛可乐发红包脱单ACM赛 B题 小a的旅行计划
  • 原文地址:https://www.cnblogs.com/lasdaybg/p/9971285.html
Copyright © 2020-2023  润新知