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 相关文章推荐
学习YUI.Ext 第三天
Mar 10 Javascript
在IE中调用javascript打开Excel的代码(downmoon原作)
Apr 02 Javascript
改写一个简单的菜单 弹性大小
Dec 02 Javascript
使用时间戳解决ie缓存的问题
Aug 20 Javascript
jQuery计算文本框字数及限制文本框字数的方法
Mar 01 Javascript
javascript检测移动设备横竖屏
May 21 Javascript
jQuery插件uploadify实现ajax效果的图片上传
Jun 18 Javascript
微信小程序 swiper组件轮播图详解及实例
Nov 16 Javascript
angular将html代码输出为内容的实例
Sep 30 Javascript
深入了解Vue.js 混入(mixins)
Jul 23 Javascript
Bootstrap告警框(alert)实现弹出效果和短暂显示后上浮消失的示例代码
Aug 27 Javascript
Vue自定义表单内容检查rules实例
Oct 30 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 程式大小
2006/12/06 PHP
PHP 数组遍历顺序理解
2009/09/09 PHP
PHP OPCode缓存 APC详细介绍
2010/10/12 PHP
PHP判断搜索引擎蜘蛛并自动记忆到文件的代码
2012/02/04 PHP
PHP实现RSA签名生成订单功能【支付宝示例】
2017/06/06 PHP
PHP Include文件实例讲解
2019/02/15 PHP
JavaScript 入门·JavaScript 具有全范围的运算符
2007/10/01 Javascript
js常见表单应用技巧
2008/01/09 Javascript
javascript,jquery闭包概念分析
2010/06/19 Javascript
jquery的index方法实现tab效果
2011/02/16 Javascript
javascript模拟实现ajax加载框实例
2014/10/15 Javascript
全面解析JavaScript中apply和call以及bind(推荐)
2016/06/15 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
Javascript中indexOf()和lastIndexOf应用方法实例
2016/08/24 Javascript
JavaScript动态检验密码强度的实现方法
2016/11/09 Javascript
Vue常用指令V-model用法
2017/03/08 Javascript
React Native预设占位placeholder的使用
2017/09/28 Javascript
vue.extend实现alert模态框弹窗组件
2018/04/28 Javascript
详解基于Koa2开发微信二维码扫码支付相关流程
2018/05/16 Javascript
微信小程序中的canvas 文字断行和省略号显示功能的处理方法
2018/11/14 Javascript
vue远程加载sfc组件思路详解
2019/12/25 Javascript
[01:08:44]NB vs VP 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python中类和实例如何绑定属性与方法示例详解
2017/08/18 Python
Python实现正整数分解质因数操作示例
2018/08/01 Python
Python常见数据结构之栈与队列用法示例
2019/01/14 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
解决python -m pip install --upgrade pip 升级不成功问题
2020/03/05 Python
python实现简单俄罗斯方块
2020/03/13 Python
Ubuntu20.04环境安装tensorflow2的方法步骤
2021/01/29 Python
C语言编程练习
2012/04/02 面试题
求职自荐信格式
2013/12/04 职场文书
函授本科自我鉴定
2014/02/04 职场文书
数学与统计学院学生个人职业生涯规划书
2014/02/10 职场文书
世界遗产导游词
2015/02/13 职场文书
2015年感恩节活动总结
2015/03/24 职场文书
晚会开场白和结束语
2015/05/29 职场文书