小程序RSA、AES加密

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
相关推荐
高级程序源4 小时前
django招聘网站信息爬取与分析系统79704-计算机课程设计、毕业设计
后端·python·mysql·小程序·django·flask·课程设计
zhangminghuan8 小时前
UniApp / 微信小程序实战拓展面试题|业务坑点、工程化、跨端踩坑(2026 前端进阶)
小程序
Kingexpand_com16 小时前
企业车队运营痛点解析:传统人工模式如何实现数字化升级
小程序·app·软件开发·app定制开发·打车用车app·车队
2601_949950631 天前
练题簿在线练题全流程:从资料导入到模拟考试与错题复盘
学习·考研·小程序·刷题·小程序推荐
投票竞赛1 天前
线上投票海报生成教程,一键制作带小程序码投票海报
小程序
海鸥两三1 天前
小程序文档预览 · 进阶面试题
小程序·uni-app·uniapp
m0_587383001 天前
上海24小时自助健身房系统软件开发实战指南:从架构到部署
人工智能·小程序·数据挖掘·系统架构·需求分析
海鸥两三1 天前
微信小程序 PDF 预览实践(uni.downloadFile → uni.openDocument)
小程序·uni-app
河北清兮网络科技2 天前
开发软件怎么找靠谱的公司?普通人最全筛选避坑指南
小程序·app·短剧·短剧app·广告联盟
奶油喜多多2 天前
深度测评2026培训机构消课系统,课时核算落地经验
小程序·需求分析