欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

CryptoJS中AES实现前后端通用加解密技术

程序员文章站 2022-06-22 15:56:59
在项目中如果要对前后端传输的数据双向加密, 比如避免使用明文传输用户名,密码等数据。 就需要对前后端数据用同种方法进行加密,方便解密。这里介绍使用 cryptojs 实现...

在项目中如果要对前后端传输的数据双向加密, 比如避免使用明文传输用户名,密码等数据。 就需要对前后端数据用同种方法进行加密,方便解密。这里介绍使用 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[] 结果,得到的都会是乱码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。