小程序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
相关推荐
游戏开发爱好者830 分钟前
抓包工具有哪些?代理抓包、数据流抓包、拦截转发工具
android·ios·小程序·https·uni-app·iphone·webview
棒棒的唐1 小时前
vant小程序版弹窗穿透滚动的解决方案
小程序
翔云 OCR API2 小时前
NFC护照识读鉴伪解决方案-小程序/app端护照鉴伪
小程序
禾高网络5 小时前
互联网医院定制|互联网医院|禾高互联网医院搭建
java·大数据·人工智能·小程序
qq_12498707535 小时前
基于微信小程序的付费自习室系统的设计与实现(源码+论文+部署+安装)
spring boot·微信小程序·小程序·毕业设计·计算机毕业设计·毕设源码
一室易安6 小时前
uniapp vue3 小程序中 手写模仿京东淘宝加入购物车红点曲线飞入样式效果 简化版代码
小程序·uni-app
00后程序员张6 小时前
混合 App 怎么加密?分析混合架构下常见的安全风险
android·安全·小程序·https·uni-app·iphone·webview
qq_12498707536 小时前
校园失物招领微信小程序设计与实现(源码+论文+部署+安装)
spring boot·微信小程序·小程序·毕业设计·毕设
梦想要有6 小时前
盲盒小程序有哪些比较不错的功能推荐
小程序
kdniao17 小时前
小程序和电商商家物流查询监控解决方案
大数据·小程序