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 相关文章推荐
jQuery 插件仿百度搜索框智能提示(带Value值)
Jan 22 Javascript
JavaScript中常见的字符串操作函数及用法汇总
May 04 Javascript
JavaScript动态添加style节点的方法
Jun 09 Javascript
JavaScript如何调试有哪些建议和技巧附五款有用的调试工具
Oct 28 Javascript
AngularJS指令详解及示例代码
Aug 16 Javascript
connection reset by peer问题总结及解决方案
Oct 21 Javascript
jQuery中checkbox反复调用attr('checked', true/false)只有第一次生效的解决方法
Nov 16 Javascript
Bootstrap CSS布局之图像
Dec 17 Javascript
Bootstrap的modal拖动效果
Dec 25 Javascript
VUE+Element UI实现简单的表格行内编辑效果的示例的代码
Oct 31 Javascript
js核心基础之闭包的应用实例分析
May 11 Javascript
jQuery事件绑定和解绑、事件冒泡与阻止事件冒泡及弹出应用示例
May 13 jQuery
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
实用函数8
2007/11/08 PHP
php截取utf-8中文字符串乱码的解决方法
2010/03/29 PHP
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
php中ob_flush函数和flush函数用法分析
2015/03/18 PHP
理解php依赖注入和控制反转
2016/05/11 PHP
php简单截取字符串代码示例
2016/10/19 PHP
php安装dblib扩展,连接mssql的具体步骤
2017/03/02 PHP
Javascript 静态页面实现随机显示广告的办法
2010/11/17 Javascript
javascript中xml操作实现代码
2011/11/21 Javascript
js控制web打印(局部打印)方法整理
2013/05/29 Javascript
AngularJS实现表单验证
2015/01/28 Javascript
深入理解JavaScript系列(36):设计模式之中介者模式详解
2015/03/04 Javascript
javascript拖拽应用实例(二)
2016/03/25 Javascript
jQuery内容折叠效果插件用法实例分析(附demo源码)
2016/04/28 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
2016/07/28 Javascript
js上下视差滚动简单实现代码
2017/03/07 Javascript
深入浅析Node环境和浏览器的区别
2018/08/14 Javascript
通过实例解析js简易模块加载器
2019/06/17 Javascript
使用Vant完成Dialog弹框案例
2020/11/11 Javascript
Python判断列表是否已排序的各种方法及其性能分析
2016/06/20 Python
浅析python中的迭代与迭代对象
2018/10/08 Python
解决python中os.listdir()函数读取文件夹下文件的乱序和排序问题
2018/10/17 Python
对python 操作solr索引数据的实例详解
2018/12/07 Python
Django 路由控制的实现
2019/07/17 Python
PyQt Qt Designer工具的布局管理详解
2019/08/07 Python
python3 图片 4通道转成3通道 1通道转成3通道 图片压缩实例
2019/12/03 Python
Python图片的横坐标汉字实例
2019/12/04 Python
pytorch三层全连接层实现手写字母识别方式
2020/01/14 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
Jupyter Notebook折叠输出的内容实例
2020/04/22 Python
匡威爱尔兰官网:Converse爱尔兰
2019/06/09 全球购物
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
捐书活动总结
2014/05/04 职场文书
四风问题自我剖析材料
2014/10/07 职场文书
如何制定销售人员薪酬制度?
2019/07/09 职场文书
分布式Redis Cluster集群搭建与Redis基本用法
2022/02/24 Redis