1、下载
npm i rsa-oaep-encryption crypto-js @types/crypto-js
2、AES 加解密方法
TypeScript
import CryptoJS from 'crypto-js';
const aesKeys = "JMxEscETzuTGjsdwhDgqkHxAAqYWH/b0FWoQzM6gmLI="
export const generateAesKey = (length: number): Promise<any> => {
return new Promise((resolve, reject) => {
uni.getRandomValues({
length,
success: (res: any) => {
const buffer = res.randomValues.buffer || res.randomValues;
resolve(buffer)
},
fail: reject
});
});
};
/**
* 在 uni-app 中加密数据(兼容微信小程序、H5、App)
* @param data 任意可 JSON.stringify 的数据
* @param aesKeyBase64 16字节 AES 密钥的 Base64 字符串(如 "abc123==")。可以调用 generateAesKey(32) 生成
* @returns 格式:base64_iv:base64_ciphertext
*/
export const aesEncrypt = async (data: any, aesKeyBase64: ArrayBuffer): Promise<string> => {
const plaintext = JSON.stringify(data);
const aesKey = uni.arrayBufferToBase64(aesKeyBase64);
const key = CryptoJS.enc.Base64.parse(aesKey);
const ivBuffer = await generateAesKey(16)
const ivWordArray = CryptoJS.lib.WordArray.create(new Uint8Array(ivBuffer));
const encrypted = CryptoJS.AES.encrypt(plaintext, key, {
iv: ivWordArray,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 转为 Base64 字符串
const ivBase64 = CryptoJS.enc.Base64.stringify(ivWordArray);
const ciphertextBase64 = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
return `${ivBase64}:${ciphertextBase64}`;
};
// 解密
export const aesDecrypt = (encryptedData: string): string => {
const parts = encryptedData.split(':');
if (parts.length !== 2) {
throw new Error('Invalid encrypted data format. Expected "iv:encrypted"');
}
const [ivBase64, encryptedBase64] = parts;
const key = CryptoJS.enc.Base64.parse(aesKeys);
const iv = CryptoJS.enc.Base64.parse(ivBase64);
// 执行解密
const decrypted = CryptoJS.AES.decrypt(
encryptedBase64,
key,
{
iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
}
);
// 转换为 UTF-8 字符串
const plaintext = decrypted.toString(CryptoJS.enc.Utf8);
if (plaintext === '') {
throw new Error('Decryption succeeded but result is empty (possibly wrong key)');
}
return plaintext;
}
3、RSA加密方法
TypeScript
// ✅ 只导入需要的部分
import { importPublicKey, sha256 } from 'rsa-oaep-encryption';
const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwaepXXet7q3Je2X/2BX8
bW3vkv8L+zvWOi53b8E70EKz+E2c6nXQXWXRtY96HebV3ShqrRHzztxPYNKTs8Jm
rM+sfix0X3jZj9ObKuFWcFJbJzXY5oS2Z7QnHSdMsmmXDGijnJ3HGHor26OmaWqc
eWw+PX6B3CTY90K2M9Y3B5K34WGpMmVTd4j32+ja6fEh/fgd/nLUDHZalAxraFxl
KLKz1tw8QIaMHQ8YbCUj8CBygJnLsWG1zi/0ASaScnqpPJpVWYGcDRjvBz199iYc
RAo+SDV8tvsKOtpBnaKX9JHTAOIFOU4IaITJdzyQoPhYsnrhlxDZ0OVFlvpC7Aig
yQIDAQAB
-----END PUBLIC KEY-----`;
export const rsaEncrypt = async (data: string): Promise<string> => {
if (typeof data !== 'string') {
throw new Error('RSA 加密输入必须是字符串');
}
const publicKey = await importPublicKey(publicKeyPem);
const encryptedBytes = await publicKey.encrypt(data, sha256.create());
return uni.arrayBufferToBase64(encryptedBytes);
};
4、使用
TypeScript
import ajax, { AjaxRequestConfig } from 'uni-ajax';
import { aesDecrypt, aesEncrypt, generateAesKey } from './crypto/AES';
import { rsaEncrypt } from './crypto/RSA';
const instance = ajax.create({
baseURL: 'http://localhost:8080/api',
});
instance.interceptors.request.use(
async (config: AjaxRequestConfig) => {
let userInfo = uni.getStorageSync("userInfo");
if (userInfo && userInfo.token) {
config.header['Authorization'] = 'Bearer ' + userInfo.token;
}
if (config.method == 'POST' && config.data) {
const aesKey = await generateAesKey(32);
config.data = {
data: await aesEncrypt(config.data, aesKey),
aesKey: await rsaEncrypt(uni.arrayBufferToBase64(aesKey))
}
}
return config
},
error => {
// 对请求错误做些什么
console.log(error);
return Promise.reject(error)
}
)
// 添加响应拦截器
instance.interceptors.response.use(
response => {
response.data = JSON.parse(aesDecrypt(response.data))
// 对响应数据做些什么
if ((!response.config.responseType || response.config.responseType != 'arraybuffer') && (response.data.code != 200)) {
uni.showToast({ title: response.data.message, icon: 'none' })
}
if (response.data.code == 401) {
uni.removeStorageSync("userInfo")
uni.navigateTo({ url: '/pages/login/index' })
}
return response
},
error => {
// 对响应错误做些什么
console.log(error);
try {
} catch (e) {
console.log(e);
}
uni.showToast({ title: error?.data?.message ?? error.statusCode, icon: 'none' })
return Promise.reject(error)
}
)
export default instance