• golang、JS AES(CBC模式)加密解密兼容


    原文地址:
    https://www.cnblogs.com/haima/p/12611372.html

    golang、JS AES(CBC模式)加密解密兼容

    golang代码

    package crypto
    
    import (
    	"bytes"
    	"crypto/aes"
    	"crypto/cipher"
    	"encoding/hex"
    	"errors"
    	"fmt"
    )
    //参考文档
    //http://www.topgoer.com/%E5%85%B6%E4%BB%96/%E5%8A%A0%E5%AF%86%E8%A7%A3%E5%AF%86/%E5%8A%A0%E5%AF%86%E8%A7%A3%E5%AF%86.html
    //高级加密标准(Adevanced Encryption Standard ,AES)
    
    //16,24,32位字符串的话,分别对应AES-128,AES-192,AES-256 加密方法
    //key不能泄露
    //var PwdKey = []byte("DIS**#KKKDJJSKDI")
    var PwdKey = "linkbook1qaz*WSX"
    
    //PKCS7 填充模式
    func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
    	padding := blockSize - len(ciphertext)%blockSize
    	//Repeat()函数的功能是把切片[]byte{byte(padding)}复制padding个,然后合并成新的字节切片返回
    	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    	return append(ciphertext, padtext...)
    }
    
    //填充的反向操作,删除填充字符串
    func PKCS7UnPadding1(origData []byte) ([]byte, error) {
    	//获取数据长度
    	length := len(origData)
    	if length == 0 {
    		return nil, errors.New("加密字符串错误!")
    	} else {
    		//获取填充字符串长度
    		unpadding := int(origData[length-1])
    		//截取切片,删除填充字节,并且返回明文
    		return origData[:(length - unpadding)], nil
    	}
    }
    
    //实现加密
    func AesEcrypt(origData []byte, key []byte) ([]byte, error) {
    	//创建加密算法实例
    	block, err := aes.NewCipher(key)
    	if err != nil {
    		return nil, err
    	}
    	//获取块的大小
    	blockSize := block.BlockSize()
    	//对数据进行填充,让数据长度满足需求
    	origData = PKCS7Padding(origData, blockSize)
    	//采用AES加密方法中CBC加密模式
    	blocMode := cipher.NewCBCEncrypter(block, key[:blockSize])
    	crypted := make([]byte, len(origData))
    	//执行加密
    	blocMode.CryptBlocks(crypted, origData)
    	return crypted, nil
    }
    
    //实现解密
    func AesDeCrypt(cypted []byte, key []byte) (string, error) {
    	//创建加密算法实例
    	block, err := aes.NewCipher(key)
    	if err != nil {
    		return "", err
    	}
    	//获取块大小
    	blockSize := block.BlockSize()
    	//创建加密客户端实例
    	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
    	origData := make([]byte, len(cypted))
    	//这个函数也可以用来解密
    	blockMode.CryptBlocks(origData, cypted)
    	//去除填充字符串
    	origData, err = PKCS7UnPadding1(origData)
    	if err != nil {
    		return "", err
    	}
    	return string(origData), err
    }
    
    //加密base64
    func EnPwdCode(pwdStr string) string {
    	pwd := []byte(pwdStr)
    	result, err := AesEcrypt(pwd, []byte(PwdKey))
    	if err != nil {
    		return ""
    	}
    	return hex.EncodeToString(result)
    }
    
    //解密
    func DePwdCode(pwd string) string {
    	temp, _ := hex.DecodeString(pwd)
    	//执行AES解密
    	res, _:=AesDeCrypt(temp, []byte(PwdKey))
    	return res
    }
    
    func main() {
    
    	//aes加密
    	destring:=`{"name":"菜鸟教程11","site":"http://www.runoob.com"}`
    	deStr := EnPwdCode(destring)
    	fmt.Println(deStr) //4f4d74c15e0ad4afb323a17927b1176ecb0c95ecbdf8e776ceb093499e3ff4c45157b007ae7dff1688ac2d2bf9fef28644922a1b3bbc6ef5881cb1ed0dff298a
    
    	//aes解密
    	decodeStr := DePwdCode("4f4d74c15e0ad4afb323a17927b1176ecb0c95ecbdf8e776ceb093499e3ff4c45157b007ae7dff1688ac2d2bf9fef28644922a1b3bbc6ef5881cb1ed0dff298a")
    	fmt.Println(decodeStr) //{"name":"菜鸟教程11","site":"http://www.runoob.com"}
    }
    

    前端javascript的代码

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Title</title>
    
    </head>
    <script src="./aes.js"></script>
    
    <body>
    
      <script>
        // var key1 = "1234567887654321";
        var key1 = "linkbook1qaz*WSX";
        // var plaintText = '"name"="lisi",age=18'; // 明文
        var str = {
          name: "菜鸟教程11",
          site: "http://www.runoob.com"
        }
        var plaintText = JSON.stringify(str)
        console.log(plaintText)
        endata = encodeAes(plaintText)
        //加密
        function encodeAes(plaintTextStr) {
          var key = CryptoJS.enc.Utf8.parse(key1);
    
          var encryptedData = CryptoJS.AES.encrypt(plaintText, key, {
            iv: key,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
          });
    
          // console.log("加密前:" + plaintText);
          // console.log("加密后:" + encryptedData);    //Pkcs7:   WoCzvm6eZiM4/bx5o/CzGw==
    
          // console.log("加密后 base64:" + encryptedData.ciphertext.toString(CryptoJS.enc.Base64));
          encryptedData = encryptedData.ciphertext.toString();
          console.log("加密后-no-hex:" + encryptedData);
          return encryptedData
        }
    
    
        // 解密
        endata1 = "46ce4f5bb33896c4c75a24a46c6f16c32991228f40831003b98acffe41fee255f892d68283b8a1b07a4dfd66622b6c50685854e918ac059d5d8e969b3b105c6b";
        decodeAes(endata1)
        function decodeAes(encryptedDataStr) {
          var key = CryptoJS.enc.Utf8.parse(key1);
          var encryptedHexStr = CryptoJS.enc.Hex.parse(encryptedDataStr);
          // console.log("解密前hex:" + encryptedHexStr);
          var encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
          // console.log("解密前:" + encryptedBase64Str);
    
          var decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, {
            iv: key,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
          });
    
          var decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8);
          console.log("解密后:" + decryptedStr);
    
        }
    
      </script>
    </body>
    
    </html>
    

    aes.js

    github下载地址:
    https://github.com/brix/crypto-js/blob/develop/src/aes.js

    (function () {
        // Shortcuts
        var C = CryptoJS;
        var C_lib = C.lib;
        var BlockCipher = C_lib.BlockCipher;
        var C_algo = C.algo;
    
        // Lookup tables
        var SBOX = [];
        var INV_SBOX = [];
        var SUB_MIX_0 = [];
        var SUB_MIX_1 = [];
        var SUB_MIX_2 = [];
        var SUB_MIX_3 = [];
        var INV_SUB_MIX_0 = [];
        var INV_SUB_MIX_1 = [];
        var INV_SUB_MIX_2 = [];
        var INV_SUB_MIX_3 = [];
    
        // Compute lookup tables
        (function () {
            // Compute double table
            var d = [];
            for (var i = 0; i < 256; i++) {
                if (i < 128) {
                    d[i] = i << 1;
                } else {
                    d[i] = (i << 1) ^ 0x11b;
                }
            }
    
            // Walk GF(2^8)
            var x = 0;
            var xi = 0;
            for (var i = 0; i < 256; i++) {
                // Compute sbox
                var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
                sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
                SBOX[x] = sx;
                INV_SBOX[sx] = x;
    
                // Compute multiplication
                var x2 = d[x];
                var x4 = d[x2];
                var x8 = d[x4];
    
                // Compute sub bytes, mix columns tables
                var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
                SUB_MIX_0[x] = (t << 24) | (t >>> 8);
                SUB_MIX_1[x] = (t << 16) | (t >>> 16);
                SUB_MIX_2[x] = (t << 8)  | (t >>> 24);
                SUB_MIX_3[x] = t;
    
                // Compute inv sub bytes, inv mix columns tables
                var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
                INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
                INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
                INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);
                INV_SUB_MIX_3[sx] = t;
    
                // Compute next counter
                if (!x) {
                    x = xi = 1;
                } else {
                    x = x2 ^ d[d[d[x8 ^ x2]]];
                    xi ^= d[d[xi]];
                }
            }
        }());
    
        // Precomputed Rcon lookup
        var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
    
        /**
         * AES block cipher algorithm.
         */
        var AES = C_algo.AES = BlockCipher.extend({
            _doReset: function () {
                var t;
                
                // Skip reset of nRounds has been set before and key did not change
                if (this._nRounds && this._keyPriorReset === this._key) {
                    return;
                }
    
                // Shortcuts
                var key = this._keyPriorReset = this._key;
                var keyWords = key.words;
                var keySize = key.sigBytes / 4;
    
                // Compute number of rounds
                var nRounds = this._nRounds = keySize + 6;
    
                // Compute number of key schedule rows
                var ksRows = (nRounds + 1) * 4;
    
                // Compute key schedule
                var keySchedule = this._keySchedule = [];
                for (var ksRow = 0; ksRow < ksRows; ksRow++) {
                    if (ksRow < keySize) {
                        keySchedule[ksRow] = keyWords[ksRow];
                    } else {
                        t = keySchedule[ksRow - 1];
    
                        if (!(ksRow % keySize)) {
                            // Rot word
                            t = (t << 8) | (t >>> 24);
    
                            // Sub word
                            t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
    
                            // Mix Rcon
                            t ^= RCON[(ksRow / keySize) | 0] << 24;
                        } else if (keySize > 6 && ksRow % keySize == 4) {
                            // Sub word
                            t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
                        }
    
                        keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
                    }
                }
    
                // Compute inv key schedule
                var invKeySchedule = this._invKeySchedule = [];
                for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
                    var ksRow = ksRows - invKsRow;
    
                    if (invKsRow % 4) {
                        var t = keySchedule[ksRow];
                    } else {
                        var t = keySchedule[ksRow - 4];
                    }
    
                    if (invKsRow < 4 || ksRow <= 4) {
                        invKeySchedule[invKsRow] = t;
                    } else {
                        invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
                                                   INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
                    }
                }
            },
    
            encryptBlock: function (M, offset) {
                this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
            },
    
            decryptBlock: function (M, offset) {
                // Swap 2nd and 4th rows
                var t = M[offset + 1];
                M[offset + 1] = M[offset + 3];
                M[offset + 3] = t;
    
                this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
    
                // Inv swap 2nd and 4th rows
                var t = M[offset + 1];
                M[offset + 1] = M[offset + 3];
                M[offset + 3] = t;
            },
    
            _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
                // Shortcut
                var nRounds = this._nRounds;
    
                // Get input, add round key
                var s0 = M[offset]     ^ keySchedule[0];
                var s1 = M[offset + 1] ^ keySchedule[1];
                var s2 = M[offset + 2] ^ keySchedule[2];
                var s3 = M[offset + 3] ^ keySchedule[3];
    
                // Key schedule row counter
                var ksRow = 4;
    
                // Rounds
                for (var round = 1; round < nRounds; round++) {
                    // Shift rows, sub bytes, mix columns, add round key
                    var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
                    var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
                    var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
                    var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
    
                    // Update state
                    s0 = t0;
                    s1 = t1;
                    s2 = t2;
                    s3 = t3;
                }
    
                // Shift rows, sub bytes, add round key
                var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
                var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
                var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
                var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
    
                // Set output
                M[offset]     = t0;
                M[offset + 1] = t1;
                M[offset + 2] = t2;
                M[offset + 3] = t3;
            },
    
            keySize: 256/32
        });
    
        /**
         * Shortcut functions to the cipher's object interface.
         *
         * @example
         *
         *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
         *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);
         */
        C.AES = BlockCipher._createHelper(AES);
    }());
    
  • 相关阅读:
    夏令营讲课内容整理 Day 6 Part 3.
    夏令营讲课内容整理 Day 6 Part 2.
    计算几何:模板
    字符串:SAM
    字符串:回文自动机
    字符串:马拉车
    数学&模拟:随机化-矩阵随机化
    模拟:随机增量法
    模拟:爬山算法与模拟退火算法
    模拟:压位高精度
  • 原文地址:https://www.cnblogs.com/haima/p/12611372.html
Copyright © 2020-2023  润新知