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 相关文章推荐
javascript RadioButtonList获取选中值
Apr 09 Javascript
JS实现刷新父页面不弹出提示框的方法
Jun 22 Javascript
基于vue的下拉刷新指令和滚动刷新指令
Dec 23 Javascript
基于复选框demo(分享)
Sep 27 Javascript
微信小程序实现YDUI的ScrollNav组件
Feb 02 Javascript
详解ng-alain动态表单SF表单项设置必填和正则校验
Jun 11 Javascript
Vue程序调试的方法
Jun 17 Javascript
js/jQuery实现全选效果
Jun 17 jQuery
使用ThinkJs搭建微信中控服务的实现方法
Aug 08 Javascript
如何使用50行javaScript代码实现简单版的call,apply,bind
Aug 14 Javascript
JavaScript数组及常见操作方法小结
Nov 13 Javascript
typescript编写微信小程序创建项目的方法
Jan 29 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
php 图片加水印与上传图片加水印php类
2010/05/12 PHP
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
2010/10/12 PHP
smarty模板引擎基础知识入门
2015/03/30 PHP
thinkphp中AJAX返回ajaxReturn()方法分析
2016/12/06 PHP
jQuery不使用插件及swf实现无刷新文件上传
2014/12/08 Javascript
javascript判断变量是否有值的方法
2015/04/20 Javascript
javascript实现鼠标拖动改变层大小的方法
2015/04/30 Javascript
详解JavaScript中的every()方法
2015/06/08 Javascript
AngularJS前端页面操作之用户修改密码功能示例
2017/03/27 Javascript
小程序云开发实战小结
2018/10/25 Javascript
Vue实现商品分类菜单数量提示功能
2019/07/26 Javascript
js实现课堂随机点名系统
2019/11/21 Javascript
vue 使用饿了么UI仿写teambition的筛选功能
2021/03/01 Vue.js
Python Paramiko模块的安装与使用详解
2016/11/18 Python
Python编程之字符串模板(Template)用法实例分析
2017/07/22 Python
浅析Python中return和finally共同挖的坑
2017/08/18 Python
python之virtualenv的简单使用方法(必看篇)
2017/11/25 Python
PyQt5实现无边框窗口的标题拖动和窗口缩放
2018/04/19 Python
Python使用try except处理程序异常的三种常用方法分析
2018/09/05 Python
Python中的引用和拷贝实例解析
2019/11/14 Python
Python合并2个字典成1个新字典的方法(9种)
2019/12/19 Python
python3 配置logging日志类的操作
2020/04/08 Python
Python 中由 yield 实现异步操作
2020/05/04 Python
Python字符串查找基本操作代码案例
2020/10/27 Python
Css3圆角边框制作代码
2015/11/18 HTML / CSS
css3动画效果小结(推荐)
2016/07/25 HTML / CSS
JSF面试题:Jsf中导航的标签是什么
2013/04/20 面试题
住房公积金接收函
2014/01/09 职场文书
师范生求职自荐信
2014/06/14 职场文书
治安消防安全责任书
2014/07/23 职场文书
小学红领巾广播稿(3篇)
2014/09/13 职场文书
大学生推广普通话演讲稿
2014/09/21 职场文书
2014年化验室工作总结
2014/11/21 职场文书
大学生个人总结范文
2015/02/15 职场文书
评奖评优个人先进事迹材料
2015/11/04 职场文书
志愿服务心得体会
2016/01/15 职场文书