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 相关文章推荐
复制本贴标题和地址的js代码
Jul 01 Javascript
基于jQuery.Validate验证库知识点的详解
Apr 26 Javascript
JS 打印界面的CSS居中代码适用所有浏览器
Mar 19 Javascript
JavaScript DOM基础
Apr 13 Javascript
AngularJS 简单应用实例
Jul 28 Javascript
使用Ajax与服务器(JSON)通信实例
Nov 04 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
Aug 11 Javascript
浅谈es6 javascript的map数据结构
Dec 14 Javascript
JS实现的字符串数组去重功能小结
Jun 17 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
Sep 17 Javascript
p5.js实现动态图形临摹
Oct 23 Javascript
JavaScript array常用方法代码实例详解
Sep 02 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
win7+apache+php+mysql环境配置操作详解
2013/06/10 PHP
Laravel 5.0 发布 新版本特性详解
2015/02/10 PHP
ThinkPHP在Cli模式下使用模板引擎的方法
2015/09/25 PHP
PHP5.6.8连接SQL Server 2008 R2数据库常用技巧分析总结
2019/05/06 PHP
JavaScript 弹出窗体点击按钮返回选择数据的实现
2010/04/01 Javascript
各浏览器中querySelector和querySelectorAll的实现差异分析
2012/05/23 Javascript
使用Math.floor与Math.random取随机整数的方法详解
2013/05/07 Javascript
jQuery中校验时间格式的正则表达式小结
2013/09/22 Javascript
js重写alert控件(适合学习js的新手朋友)
2014/08/24 Javascript
推荐10 款 SVG 动画的 JavaScript 库
2015/03/24 Javascript
JS通过ajax动态读取xml文件内容的方法
2015/03/24 Javascript
使用Chrome浏览器调试AngularJS应用的方法
2015/06/18 Javascript
jQuery实现右侧显示可向左滑动展示的深色QQ客服效果代码
2015/10/23 Javascript
jquery实现一个简单的表单验证实例
2016/03/30 Javascript
原生JS实现旋转木马式图片轮播插件
2016/04/25 Javascript
js的form表单提交url传参数(包含+等特殊字符)的两种解决方法
2016/05/25 Javascript
Angular懒加载机制刷新后无法回退的快速解决方法
2016/08/30 Javascript
jQuery Collapse1.1.0折叠插件简单使用
2017/08/28 jQuery
js 两个日期比较相差多少天的实例
2017/10/19 Javascript
详解vue-cli脚手架build目录中的dev-server.js配置文件
2017/11/24 Javascript
express+mockjs实现模拟后台数据发送功能
2018/01/07 Javascript
JavaScript 隐性类型转换步骤浅析
2018/03/15 Javascript
vue指令只能输入正数并且只能输入一个小数点的方法
2018/06/08 Javascript
js遍历添加栏目类添加css 再点击其它删除css【推荐】
2018/06/12 Javascript
如何在 JavaScript 中更好地利用数组
2018/09/27 Javascript
实例详解带参数的 npm script
2019/05/28 Javascript
详解基于原生JS验证表单组件xy-form
2019/08/20 Javascript
[04:03][TI9趣味短片] 小鸽子茶话会
2019/08/20 DOTA
python模拟登录并且保持cookie的方法详解
2017/04/04 Python
Django如何使用第三方服务发送电子邮件
2019/08/14 Python
使用canvas压缩图片大小的方法示例
2019/08/02 HTML / CSS
Vans荷兰官方网站:美国南加州的原创极限运动潮牌
2018/01/23 全球购物
Daniel Wellington官方海外旗舰店:丹尼尔惠灵顿DW手表
2018/02/22 全球购物
六五普法宣传标语
2014/10/06 职场文书
2015大学生入党个人自传
2015/06/26 职场文书
Canvas三种动态画圆实现方法说明(小结)
2021/04/16 Javascript