aes js 加盐值 解密_AES 加解密 前后台 Java JS

本文介绍了AES对称加密方式的基本原理,并提供了Java后端与JavaScript前端实现AES加盐值加密解密的代码示例,包括加密、解密、密钥与向量的处理。同时提到了在实践中遇到的JDK不支持256位AES加密以及初始化向量长度限制的问题。
摘要由CSDN通过智能技术生成

简介

AES是一种对称加密方式,对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。

对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。

加密标准

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

AES

密钥长度(32位比特字)

分组长度(32位比特字)

加密轮数

AES-128

4

4

10

AES-192

6

4

12

AES-256

8

4

14

Java后端实现(128位)

导入依赖:

commons-codec

commons-codec

1.10

实现工具类:

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class AesUtil {

//加密时调用方法,三个参数分别是:明文,密钥,向量,注意向量的长度只能是16byte,而且加密解密时必须使用一致的向量。

public static byte[] AES_CBC_Encrypt(byte[] content, byte[] keyBytes,

byte[] iv) {

try {

SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

// PKCS7Padding是缺几个字节就补几个字节的0,而PKCS5Padding是缺几个字节就补充几个字节的几,好比缺6个字节,就补充6个字节的6

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));

byte[] result = cipher.doFinal(content);

return result;

} catch (Exception e) {

System.out.println("exception:" + e.toString());

}

return null;

}

//解密方法,三个参数:密文,密钥,向量

public static byte[] AES_CBC_Decrypt(byte[] content, byte[] keyBytes,

byte[] iv) {

try {

SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

byte[] result = cipher.doFinal(content);

return result;

} catch (Exception e) {

System.out.println("exception:" + e.toString());

}

return null;

}

/**

*将base64类型的字符串转成byte类型

* @param key

* @return

* @throws Exception

*/

public static byte[] decryptBASE64(String key) throws Exception {

return Base64.decodeBase64(key.getBytes());

}

/**

* 将byte类型转变为base64类型的字符串

* @param key

* @return

* @throws Exception

*/

public static String encryptBASE64(byte[] key) throws Exception {

return new String(Base64.encodeBase64(key));

}

/**

* 字符串转二进制字符串

*

* @param str

*/

public String toBinary(String str) {

char[] strChar = str.toCharArray();

String result = "";

for (int i = 0; i < strChar.length; i++) {

result += Integer.toBinaryString(strChar[i]) + "";

}

return result;

}

/**

* 字符串转16进制字符串

* @param s

* @return

*/

public static String strTo16(String s) {

String str = "";

for (int i = 0; i < s.length(); i++) {

int ch = (int) s.charAt(i);

String s4 = Integer.toHexString(ch);

str = str + s4;

}

return str;

}

public static void main(String[] args) throws Exception {

//明文

String returnMessageContent = "矛盾综合体";

// 密钥,一定是16byte长度的 前后台需要一致

String key = "SHmfaQwNX6nzb3Ee";

// 向量,一定是16byte长度的 前后台需要一致

String iv = "SHmfaQwNX6nzb3Ee";

//注意第一个参数-明文转化为byte数组的时候,一定要指定是按照utf-8的格式进行转化的,不然对中文的加密就会出现加密后无法解密的情况。

//第三个参数-向量,一定是16byte长度的

byte[] encrypted = AesUtil.AES_CBC_Encrypt(returnMessageContent.getBytes("utf-8"), key.getBytes(), iv.getBytes());

//将加密后的密文转成base64格式的字符串

String secretWord = AesUtil.encryptBASE64(encrypted);

System.out.println(secretWord);

String chat_content = secretWord;

// 解密,获得消息明文

byte[] chat_contentming = AesUtil.AES_CBC_Decrypt(AesUtil.decryptBASE64(chat_content), key.getBytes(), iv.getBytes());

//将明文byte按照utf-8的形式转化为String字符串

String messageming = new String(chat_contentming, "utf-8");

System.out.println(messageming);

}

}

运行结果

GilLsEWESwtMFdyJ6P7rpg==

矛盾综合体

前端实现(JS)

html

AES加解密

// 加密方法

function getAesString(data, key, iv) {

var key = CryptoJS.enc.Utf8.parse(key);

var iv = CryptoJS.enc.Utf8.parse(iv);

var encrypted = CryptoJS.AES.encrypt(data, key, {

iv: iv,

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

return encrypted.toString(); // 返回的是base64格式的密文

}

// 解密方法

function getDAesString(encrypted, key, iv) {

var key = CryptoJS.enc.Utf8.parse(key);

var iv = CryptoJS.enc.Utf8.parse(iv);

var decrypted = CryptoJS.AES.decrypt(encrypted, key, {

iv: iv,

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

return decrypted.toString(CryptoJS.enc.Utf8); // 返回明文

}

// 明文

var data = "矛盾综合体";

// 密钥,一定是16byte长度的 前后台需要一致

var key = 'SHmfaQwNX6nzb3Ee';

// 向量,一定是16byte长度的 前后台需要一致

var iv = 'SHmfaQwNX6nzb3Ee';

// 密文,生成的密文就是base64格式的

var encrypted = getAesString(data, key, iv);

console.log(encrypted);

//生成的decryptedStr已经被默认转为了utf-8类型的字符串

var decryptedStr = getDAesString(encrypted, key, iv);

console.log(decryptedStr);

部署运行, 打开浏览器控制台Console, 运行结果

GilLsEWESwtMFdyJ6P7rpg==

矛盾综合体

前后端密文和明文内容一致, 表明没有问题.

实践中遇到的问题

JDK自带jar包不支持256位AES加密,需要到官网上下载下面两个jar包替换下面目录中的文件【文件目录:JAVA_HOME/jre/lib/security】:local_policy 和 US_export_policy

JAVA中IV【初始化向量不可以为32位,否则异常java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值