java、c#、vue基于hutool的aes指定秘钥加密(前后端aes加解密)

private-logs / 2023-07-04 / 原文

 

后端java代码
//加密 data 对称AES Key
byte[] key = getBytes("._^BV67nW6ck8fwg", 16);//秘钥长度最好是16位
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
String jsondata = aes.encryptHex("中国test");
System.out.println(jsondata);
//解密,加密模式ecb,填充pkcs7,数据库128位,迁移量无,输出hex16进制,字符集utf-8
String decryptStr = aes.decryptStr(jsondata, CharsetUtil.CHARSET_UTF_8);
System.out.println(decryptStr);

 

后端c#代码

加密

/// <summary>
        ///AES 算法加密(ECB模式) 将明文加密,加密后进行Hex编码,返回密文
        /// </summary>
        /// <param name="str">明文</param>
        /// <param name="key">密钥</param>
        /// <returns>加密后Hex编码的密文</returns>
        public static string AesEncryptor_Hex(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);

            System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
            {
                Key = StrToHexByte(key),
                Mode = System.Security.Cryptography.CipherMode.ECB,
                Padding = System.Security.Cryptography.PaddingMode.PKCS7
            };

            System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return ToHexString(resultArray);
        }

解密

/// <summary>
        ///AES 算法加密(ECB模式) 将明文加密,加密后进行Hex编码,返回密文
        /// </summary>
        /// <param name="str">明文</param>
        /// <param name="key">密钥</param>
        /// <returns>加密后Hex编码的密文</returns>
        public static string AesEncryptor_Hex(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str);

            System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
            {
                Key = StrToHexByte(key),
                Mode = System.Security.Cryptography.CipherMode.ECB,
                Padding = System.Security.Cryptography.PaddingMode.PKCS7
            };

            System.Security.Cryptography.ICryptoTransform cTransform = rm.CreateEncryptor();
            Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return ToHexString(resultArray);
        }

hex编码和解密

/// <summary>
        /// byte数组Hex编码
        /// </summary>
        /// <param name="bytes">需要进行编码的byte[]</param>
        /// <returns></returns>
        public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "
        {
            string hexString = string.Empty;
            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    strB.Append(bytes[i].ToString("X2"));
                }
                hexString = strB.ToString();
            }
            return hexString;
        }
        /// <summary> 
        /// 字符串进行Hex解码(Hex.decodeHex())
        /// </summary> 
        /// <param name="hexString">需要进行解码的字符串</param> 
        /// <returns></returns> 
        public static byte[] StrToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

 

 

 

 前端vue代码

utils文件夹下新建encryp.js

import CryptoJS from 'crypto-js'
// 加密
export default {
  encrypt(word, keyStr, iv) {
    let keys = CryptoJS.enc.Utf8.parse(keyStr); 
    let ivs = CryptoJS.enc.Utf8.parse(iv); 
    let srcs = CryptoJS.enc.Utf8.parse(word);
    let encrypted = CryptoJS.AES.encrypt(srcs, keys, {
      iv: ivs,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    console.log("base64:" + encrypted);
    var encryptedStr = encrypted.ciphertext.toString();
    console.log("16进制:" + encryptedStr);
    return encrypted.ciphertext.toString().toUpperCase();  //16进制
  },
  // }
  // 解密
  decrypt(word, keyStr, iv) {
    // ********************解密16进制***********************
    let key = CryptoJS.enc.Utf8.parse(keyStr);
    let ivs = CryptoJS.enc.Utf8.parse(iv);
    let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
    let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    let decrypt = CryptoJS.AES.decrypt(srcs, key, {
      iv: ivs,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    console.log(decryptedStr)
    return decryptedStr.toString();
  }

}

使用

import Crypto from "@/utils/encryp.js"; //很多页面要使用时也可以再main.js中定义:import Crypto from "@/utils/encryp.js";Vue.prototype.$crypto = Crypto; 页面中调用: var t = $crypto.encrypt('中国test',"._^BV67nW6ck8fwg","");



var t = Crypto.encrypt('中国test',"._^BV67nW6ck8fwg",""); 
console.log(t);

 

 

 js的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="width:500px; height:20px;"/>
        <button type="button" onclick="encryptText()">加密</button>
    <input id="encrypted" type="text" style="width:500px; height:20px;" />
    <br>
    <br>
    <br>
    <input id="todecrypt" type="text" style="width:500px; height:20px;"/>
        <button type="button" onclick="decryptText()">解密</button>
    <input id="decrypted" type="text" style="width:500px; height:20px;" />
</body>
</html>
复制代码

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