CryptoJS中AES实现前后端通用加解密技术


Posted in Javascript onDecember 18, 2018

在项目中如果要对前后端传输的数据双向加密, 比如避免使用明文传输用户名,密码等数据。 就需要对前后端数据用同种方法进行加密,方便解密。这里介绍使用 CryptoJS 实现 AES 加解密。

首先需要下载前台使用 CryptoJS 实现 AES 加解密的,所以要先下载组件,下载 CryptoJS-v3.1.2 版本之后,文件中包含components 和 rollups 两个文件夹,components 文件夹下是单个组件,rollups 文件夹下是汇总,引用 rollups 下的 aes.js 文件即可。

已解决解密数据时出现的异常: exception:javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

 这里提供 CryptoJS-v3.1.2 的 Github链接

 先上后台Java代码: 

package com.company.pms.pmsbase.utils;
 
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
import org.apache.commons.codec.binary.Base64;
 
public class AesUtil {
 
 public static void main(String args[]) throws Exception {
 
  String content = "明文 123 abc";
 
  //加密
  String encrypted = encrypt(content, KEY, IV);
  //解密
  String decrypted = decrypt(encrypted, KEY, IV);
 
  System.out.println("加密前:" + content);
 
  System.out.println("加密后:" + encrypted);
 
  System.out.println("解密后:" + decrypted);
 }
 
 private static String KEY = "abcdef0123456789"; // 长度必须是 16
 
 private static String IV = "abcdef0123456789"; // 长度必须是 16
 
 /**
  * 加密返回的数据转换成 String 类型
  * @param content 明文
  * @param key 秘钥
  * @param iv 初始化向量是16位长度的字符串
  * @return
  * @throws Exception
  */
 public static String encrypt(String content, String key, String iv) throws Exception {
  // 将返回的加密过的 byte[] 转换成Base64编码字符串 !!!!很关键
  return base64ToString(AES_CBC_Encrypt(content.getBytes(), key.getBytes(), iv.getBytes()));
 }
 
 /**
  * 将解密返回的数据转换成 String 类型
  * @param content Base64编码的密文
  * @param key 秘钥
  * @param iv 初始化向量是16位长度的字符串
  * @return
  * @throws Exception
  */
 public static String decrypt(String content, String key, String iv) throws Exception {
  // stringToBase64() 将 Base64编码的字符串转换成 byte[] !!!与base64ToString()配套使用
  return new String(AES_CBC_Decrypt(stringToBase64(content), key.getBytes(), iv.getBytes()));
 }
 
 private static byte[] AES_CBC_Encrypt(byte[] content, byte[] keyBytes, byte[] iv){
  try {
   SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
   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;
 }
 
 private 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
  */
 
 public static byte[] stringToBase64(String key) throws Exception {
  return Base64.decodeBase64(key.getBytes());
 }
 
 /**
  * Base64装换成字符串
  */
 public static String base64ToString(byte[] key) throws Exception {
  return new Base64().encodeToString(key);
 }
 
}

再上前端代码(需引用 rollups 目录下的 aes.js ):

function encodeAesString(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 
 });
 //返回的是base64格式的密文 
 return encrypted;
}
 
// encrypted 为是base64格式的密文
function decodeAesString(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);
}
 
// 测试加、解密
function testAES(){
 var data = "明文 123 abc"; // 明文 
 var key = 'abcdef0123456789'; // 密钥 长度16
 var iv = 'abcdef0123456789'; // 密钥 长度16
 
 console.log("加密前:" + data);
 
 // 测试加密
 var encrypted = encodeAesString(data,key,iv); // 密文
 console.log("加密后: " + encrypted);
 
 var decryptedStr = decodeAesString(encrypted,key,iv);
 console.log("解密后: " + decryptedStr);
}

贴上效果图:

CryptoJS中AES实现前后端通用加解密技术

CryptoJS中AES实现前后端通用加解密技术

中间遇到的问题: 

    1.  秘钥问题, 秘钥的长度必须为16位, 否则会报错

    2. 加密得到的 byte[] 需用使用Base64转换成字符串, 不能直接转成字符串,因为加密所采用的AES, MD5, SHA-256, SHA-512 等等算法,它们是通过对byte[] 进行各种变换和运算,得到加密之后的byte[],那么这个加密之后的 byte[] 结果显然 就不会符合任何一种的编码方案,比如 UTF-8, GBK等,因为加密的过程是任意对byte[]进行运算的。所以你用任何一种编码方案来解码 加密之后的 byte[] 结果,得到的都会是乱码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
超清晰的document对象详解
Feb 27 Javascript
JavaScript中的Document文档对象
Jan 16 Javascript
jquery中常用的SET和GET$(”#msg”).html循环介绍
Oct 09 Javascript
js+html5实现可在手机上玩的拼图游戏
Jul 17 Javascript
jQuery动态星级评分效果实现方法
Aug 06 Javascript
js获取上传文件的绝对路径实现方法
Aug 02 Javascript
原生js图片轮播效果实现代码
Oct 19 Javascript
bootstrap模态框消失问题的解决方法
Dec 02 Javascript
webpack处理 css\less\sass 样式的方法
Aug 21 Javascript
微信小程序上传多图到服务器并获取返回的路径
May 05 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
Aug 19 Javascript
js实现圆形菜单选择器
Dec 03 Javascript
antd组件Upload实现自己上传的实现示例
Dec 18 #Javascript
微信小程序解除10个请求并发限制
Dec 18 #Javascript
vue项目中axios请求网络接口封装的示例代码
Dec 18 #Javascript
vue中引入第三方字体文件的方法示例
Dec 17 #Javascript
vue 表单验证按钮事件交由父组件触发的方法
Dec 17 #Javascript
Vue 报错TypeError: this.$set is not a function 的解决方法
Dec 17 #Javascript
vuex 解决报错this.$store.commit is not a function的方法
Dec 17 #Javascript
You might like
体育彩票排列三组选三算法分享
2014/03/07 PHP
简单谈谈PHP中的Reload操作
2016/12/12 PHP
TP5多入口设置实例讲解
2020/12/15 PHP
lyhucSelect基于Jquery的Select数据联动插件
2011/03/29 Javascript
javascript之querySelector和querySelectorAll使用说明
2011/10/09 Javascript
JS判断客服QQ号在线还是离线状态的方法
2015/01/13 Javascript
jquery实现漂亮的二级下拉菜单代码
2015/08/26 Javascript
JavaScript 七大技巧(一)
2015/12/13 Javascript
使用jQuery Ajax 请求webservice来实现更简练的Ajax
2016/08/04 Javascript
原生js实现中奖信息无间隙滚动效果
2017/01/18 Javascript
JS实现的Unicode编码转换操作示例
2017/04/28 Javascript
mui开发中获取单选按钮、复选框的值(实例讲解)
2017/07/24 Javascript
微信小程序实现城市列表选择
2018/06/05 Javascript
详解VUE中常用的几种import(模块、文件)引入方式
2018/07/03 Javascript
支付宝小程序tabbar底部导航
2018/11/06 Javascript
Vue.js 中 axios 跨域访问错误问题及解决方法
2018/11/21 Javascript
Vue element-ui父组件控制子组件的表单校验操作
2020/07/17 Javascript
解决Vue大括号字符换行踩的坑
2020/11/09 Javascript
vue 动态添加的路由页面刷新时失效的原因及解决方案
2021/02/26 Vue.js
[15:28]DOTA2 HEROS教学视频教你分分钟做大人-剧毒术士
2014/06/13 DOTA
[56:12]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第一场 6.3
2018/06/04 DOTA
Python中条件选择和循环语句使用方法介绍
2013/03/13 Python
介绍Python中的__future__模块
2015/04/27 Python
centos6.7安装python2.7.11的具体方法
2017/01/16 Python
pandas实现将dataframe满足某一条件的值选出
2019/06/12 Python
Kears+Opencv实现简单人脸识别
2019/08/28 Python
使用OpenCV去除面积较小的连通域
2020/07/05 Python
python实现暗通道去雾算法的示例
2020/09/27 Python
python 使用xlsxwriter循环向excel中插入数据和图片的操作
2021/01/01 Python
电气个人求职信范文
2014/02/04 职场文书
产品质量承诺书
2014/03/27 职场文书
《雨点儿》教学反思
2014/04/14 职场文书
读书活动总结
2014/04/28 职场文书
一年级语文教学随笔
2015/08/14 职场文书
原来闭幕词是这样写的呀!
2019/07/01 职场文书
JS数组方法some、every和find的使用详情
2021/10/05 Javascript