从零开始构建前后端AES加密通信
推荐
这里推荐使用ECB方式
CBC方式还是有问题,后端没有解密成功
使用方式
前端加密接口参数
后端解密参数,返回正常数据
下包
npm i -S crypto-js
aes的ECB加密方式
新建crypto.js文件,构建crypto类
import CryptoJS from 'crypto-js';
class CryptoFile {
constructor () {
// 秘钥
this.key = CryptoJS.enc.Utf8.parse('CRYPTOJSKEY00000'); // 16位
this.iv = CryptoJS.enc.Utf8.parse('CRYPTOJSKEY00000');
}
// 加密
encrypt(word) {
let words = CryptoJS.enc.Utf8.parse(word);
let encrypted = CryptoJS.AES.encrypt(words, this.key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
return encrypted.toString();
}
// 解密
decrypt(word) {
let decrypt = CryptoJS.AES.decrypt(word, this.key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
return decryptedStr.toString();
}
}
export default new CryptoFile()
前端使用
引入类
import crypto from './crypto';
在需要的地方使用
我们可以自己测试,看看是不是加密,解密成功
let data = '你加密的数据'
let encryptData = crypto.encrypt(JSON.stringify(data)); // 加密后的数据
let decryptData = crypto.decrypt(encryptData) // 解密后的数据
后端java使用
java不支持Pkcs7,这个需要自己去下jar包设置
package com.CryptPacket;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* AES加解密工具
* AES-128: key和iv都是16个字节,16*8=128bit,java似乎只支持AES-128
*/
public class AESCrypt {
/**
* AES ECB 加密
* @param message 需要加密的字符串
* @param key 密匙
* @return 返回加密后密文,编码为base64
*/
public static String encryptECB(String message, String key) {
final String cipherMode = "AES/ECB/PKCS5Padding";
final String charsetName = "UTF-8";
try {
byte[] content = new byte[0];
content = message.getBytes(charsetName);
//
byte[] keyByte = key.getBytes(charsetName);
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
Cipher cipher = Cipher.getInstance(cipherMode);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] data = cipher.doFinal(content);
final Base64.Encoder encoder = Base64.getEncoder();
final String result = encoder.encodeToString(data);
return result;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* AES ECB 解密
* @param messageBase64 密文,base64编码
* @param key 密匙,和加密时相同
* @return 解密后数据
*/
public static String decryptECB(String messageBase64, String key) {
final String cipherMode = "AES/ECB/PKCS5Padding";
final String charsetName = "UTF-8";
try {
final Base64.Decoder decoder = Base64.getDecoder();
byte[] messageByte = decoder.decode(messageBase64);
//
byte[] keyByte = key.getBytes(charsetName);
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
Cipher cipher = Cipher.getInstance(cipherMode);
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] content = cipher.doFinal(messageByte);
String result = new String(content, charsetName);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 测试
*/
public static void Test()
{
String key = "1234567890123456";
String iv = "1234567890000000";
String msg = "这是一个测试这是一个测试这是一个测试";
{
String encrypt = AESCrypt.encryptCBC(msg, key, iv);
System.out.println(encrypt);
String decryptStr = AESCrypt.decryptCBC(encrypt, key, iv);
System.out.println(decryptStr);
}
{
String encrypt = AESCrypt.encryptECB(msg, key);
System.out.println(encrypt);
String decryptStr = AESCrypt.decryptECB(encrypt, key);
System.out.println(decryptStr);
}
}
}
aes的CBC加密方式
前端构建crypto类
import CryptoJS from 'crypto-js';
class CryptoFile {
constructor () {
// 秘钥
this.key = CryptoJS.enc.Utf8.parse('CRYPTOJSKEY00000'); // 16位
this.iv = CryptoJS.enc.Utf8.parse('CRYPTOJSKEY00000');
}
// 加密
encrypt(word) {
let words = CryptoJS.enc.Utf8.parse(word);
let encrypted = CryptoJS.AES.encrypt(words, this.key, { iv: this.iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
return encrypted.ciphertext.toString().toUpperCase();
}
// 解密
decrypt(word) {
let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
let words = CryptoJS.enc.Base64.stringify(encryptedHexStr);
let decrypt = CryptoJS.AES.decrypt(words, this.key, { iv: this.iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
return decryptedStr.toString();
}
}
export default new CryptoFile()
前端使用
引入类
import crypto from './crypto';
在需要的地方使用
我们可以自己测试,看看是不是加密,解密成功
let data = '你加密的数据'
let encryptData = crypto.encrypt(JSON.stringify(data)); // 加密后的数据
let decryptData = crypto.decrypt(encryptData) // 解密后的数据
后端java使用
java不支持Pkcs7,这个需要自己去下jar包或者自己设置
package com.CryptPacket;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
* AES加解密工具
* AES-128: key和iv都是16个字节,16*8=128bit,java似乎只支持AES-128
*/
public class AESCrypt {
/**
* AES CBC 加密
* @param message 需要加密的字符串
* @param key 密匙
* @param iv IV,需要和key长度相同
* @return 返回加密后密文,编码为base64
*/
public static String encryptCBC(String message, String key, String iv) {
final String cipherMode = "AES/CBC/PKCS5Padding";
final String charsetName = "UTF-8";
try {
byte[] content = new byte[0];
content = message.getBytes(charsetName);
//
byte[] keyByte = key.getBytes(charsetName);
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
//
byte[] ivByte = iv.getBytes(charsetName);
IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
Cipher cipher = Cipher.getInstance(cipherMode);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] data = cipher.doFinal(content);
final Base64.Encoder encoder = Base64.getEncoder();
final String result = encoder.encodeToString(data);
return result;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* AES CBC 解密
* @param messageBase64 密文,base64编码
* @param key 密匙,和加密时相同
* @param iv IV,需要和key长度相同
* @return 解密后数据
*/
public static String decryptCBC(String messageBase64, String key, String iv) {
final String cipherMode = "AES/CBC/PKCS5Padding";
final String charsetName = "UTF-8";
try {
final Base64.Decoder decoder = Base64.getDecoder();
byte[] messageByte = decoder.decode(messageBase64);
//
byte[] keyByte = key.getBytes(charsetName);
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
//
byte[] ivByte = iv.getBytes(charsetName);
IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
Cipher cipher = Cipher.getInstance(cipherMode);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] content = cipher.doFinal(messageByte);
String result = new String(content, charsetName);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 测试
*/
public static void Test()
{
String key = "1234567890123456";
String iv = "1234567890000000";
String msg = "这是一个测试这是一个测试这是一个测试";
{
String encrypt = AESCrypt.encryptCBC(msg, key, iv);
System.out.println(encrypt);
String decryptStr = AESCrypt.decryptCBC(encrypt, key, iv);
System.out.println(decryptStr);
}
{
String encrypt = AESCrypt.encryptECB(msg, key);
System.out.println(encrypt);
String decryptStr = AESCrypt.decryptECB(encrypt, key);
System.out.println(decryptStr);
}
}
}
参考资料
个人学习随笔,不一定原创,不定时更新
[gitHub]: https://github.com/MicahZJ
[博客]: https://micahzj.github.io/MicahZJ.github.io/
[掘金]: https://juejin.im/user/5c1355ebe51d4521030cfe84/posts/
有关问题,或者想和本人讨论
欢迎通过本人QQ872219020联系
或者在github上提issues,虽然我不一定会去看o
[gitHub]: https://github.com/MicahZJ
[博客]: https://micahzj.github.io/MicahZJ.github.io/
[掘金]: https://juejin.im/user/5c1355ebe51d4521030cfe84/posts/
有关问题,或者想和本人讨论
欢迎通过本人QQ872219020联系
或者在github上提issues,虽然我不一定会去看o