小程序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
相关推荐
2501_915921432 小时前
傻瓜式 HTTPS 抓包,简单抓取iOS设备数据
android·网络协议·ios·小程序·https·uni-app·iphone
2501_915918415 小时前
把 iOS 性能监控融入日常开发与测试流程的做法
android·ios·小程序·https·uni-app·iphone·webview
2601_949804926 小时前
开源多商户商城源码最新版_适配微信小程序+H5+APP+PC多端
微信小程序·小程序
2601_949804927 小时前
宇鹿家政服务系统小程序ThinkPHP+UniApp(
小程序·uni-app
2501_933907219 小时前
上海本凡科技的微信小程序公司主要提供哪些服务?
科技·微信小程序·小程序
码农客栈9 小时前
小程序学习(十七)之获取前台分类数据并渲染
小程序
2601_949804929 小时前
【全开源】AJAX家政上门服务系统小程序自营+多商家(高级授权)+独立端
小程序
h7ml9 小时前
查券返利机器人图像识别:OpenCV 模板匹配对抗淘宝小程序动态化骨架屏
opencv·小程序·机器人
低代码布道师9 小时前
教培管家第14讲:家长端——打造合规且顺畅的登录门户
低代码·小程序·云开发
说私域10 小时前
私域流量生态重构:链动2+1模式S2B2C商城小程序的流量整合与价值创造
人工智能·小程序·流量运营·私域运营