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 相关文章推荐
从数据结构的角度分析 for each in 比 for in 快的多
Jul 07 Javascript
纯JS实现动态时间显示代码
Feb 08 Javascript
jQuery中DOM树操作之复制元素的方法
Jan 23 Javascript
jQuery实现复选框批量选择与反选的方法
Jun 17 Javascript
JQuery validate插件Remote用法大全
May 15 Javascript
jQuery ajax中使用confirm,确认是否删除的简单实例
Jun 17 Javascript
jQuery实现的图片轮播效果完整示例
Sep 12 Javascript
Node.js的基本知识简单汇总
Sep 19 Javascript
js实现碰撞检测特效代码分享
Oct 16 Javascript
angular指令笔记ng-options的使用方法
Sep 18 Javascript
bing Map 在vue项目中的使用详解
Apr 09 Javascript
在vue中使用el-tab-pane v-show/v-if无效的解决
Aug 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
浅析get与post的一些特殊情况
2014/07/28 PHP
PHP实现图片上传并压缩
2015/12/22 PHP
利用腾讯的ip地址库做ip物理地址定位
2010/07/24 Javascript
JQuery 弹出框定位实现方法
2010/12/02 Javascript
超轻量级的基于jquery的三级展开列表
2011/04/26 Javascript
JS解析XML实例分析
2015/01/30 Javascript
jQuery实现左右切换焦点图
2015/04/03 Javascript
深入讲解AngularJS中的自定义指令的使用
2015/06/18 Javascript
jQuery实现动画效果circle实例
2015/08/06 Javascript
jQuery实现信息提示框(带有圆角框与动画)效果
2015/08/07 Javascript
基于JQuery实现图片轮播效果(焦点图)
2016/02/02 Javascript
极易被忽视的javascript面试题七问七答
2016/02/15 Javascript
你所未知的3种Node.js代码优化方式
2016/02/25 Javascript
JS常用倒计时代码实例总结
2017/02/07 Javascript
zTree 树插件实现全国五级地区点击后加载的示例
2018/02/05 Javascript
使用vue-router设置每个页面的title方法
2018/02/11 Javascript
JavaScript学习笔记之图片库案例分析
2019/01/08 Javascript
vue自定义指令之面板拖拽的实现
2019/04/14 Javascript
[01:45]IMBATV TI4前线报道-选手到达
2014/07/07 DOTA
详解Python的Django框架中的模版相关知识
2015/07/15 Python
Python实现截屏的函数
2015/07/26 Python
Python读取图片属性信息的实现方法
2016/09/11 Python
python在每个字符后添加空格的实例
2018/05/07 Python
从django的中间件直接返回请求的方法
2018/05/30 Python
详解Python3注释知识点
2019/02/19 Python
Python整数对象实现原理详解
2019/07/01 Python
Django之创建引擎索引报错及解决详解
2019/07/17 Python
pyinstaller打包程序exe踩过的坑
2019/11/19 Python
Keras自定义IOU方式
2020/06/10 Python
Python利用myqr库创建自己的二维码
2020/11/24 Python
利用HTML5+CSS3实现3D转换效果实例详解
2017/05/02 HTML / CSS
美国指甲油品牌:Deco Miami
2017/01/30 全球购物
学生个人自我鉴定
2014/03/26 职场文书
承诺书的格式范文
2014/03/28 职场文书
以权谋私检举信范文
2015/03/02 职场文书
服装店员工管理制度
2015/08/07 职场文书