基于Expo的React Native AES加密实现方法问询
没错,你说得对——expo-crypto确实只提供哈希相关的工具,没有直接支持AES加密/解密的API。不过好在有几个靠谱的方案能在Expo项目里实现AES加密,我给你整理了最常用的几种:
方案1:使用
crypto-js库(最简便) 这是最直接的方式,crypto-js是一个成熟的JavaScript加密库,完全兼容Expo环境,不需要额外的原生配置。
首先安装依赖:
npx expo install crypto-js
然后可以封装一个加密/解密工具函数:
import CryptoJS from 'crypto-js'; // 加密函数 export const encryptAES = (data, key) => { // 将密钥转换为WordArray格式 const parsedKey = CryptoJS.enc.Utf8.parse(key); // 生成随机IV(初始向量) const iv = CryptoJS.lib.WordArray.random(16); // 执行AES-CBC加密 const encrypted = CryptoJS.AES.encrypt(data, parsedKey, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 将IV和加密结果拼接(解密时需要用到IV) return iv.toString(CryptoJS.enc.Base64) + ':' + encrypted.toString(); }; // 解密函数 export const decryptAES = (encryptedData, key) => { const parsedKey = CryptoJS.enc.Utf8.parse(key); // 拆分IV和加密内容 const [ivBase64, encryptedText] = encryptedData.split(':'); const iv = CryptoJS.enc.Base64.parse(ivBase64); // 执行解密 const decrypted = CryptoJS.AES.decrypt(encryptedText, parsedKey, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 将解密结果转换为字符串 return decrypted.toString(CryptoJS.enc.Utf8); };
注意:密钥长度建议用128位(16字符)或256位(32字符),确保加密强度;另外,IV必须是随机的,不要固定使用同一个IV,否则会降低安全性。
方案2:使用Web Crypto API(原生支持,无需额外库)
Expo的JavaScript运行环境(Hermes或JSC)其实支持Web Crypto API,你可以直接用它来实现AES加密,不需要依赖第三方库。
这里是一个示例实现:
// 生成加密密钥(可以缓存密钥,不用每次加密都生成) const generateAESKey = async (keyString) => { // 将密钥字符串转换为Uint8Array const keyBuffer = new TextEncoder().encode(keyString); // 导出密钥(使用SHA-256哈希确保密钥长度符合要求) const hashedKey = await crypto.subtle.digest('SHA-256', keyBuffer); // 生成CryptoKey对象 return crypto.subtle.importKey( 'raw', hashedKey, { name: 'AES-CBC', length: 256 }, false, ['encrypt', 'decrypt'] ); }; // 加密函数 export const encryptWithWebCrypto = async (data, keyString) => { const key = await generateAESKey(keyString); // 生成随机IV const iv = crypto.getRandomValues(new Uint8Array(16)); // 加密数据 const encryptedBuffer = await crypto.subtle.encrypt( { name: 'AES-CBC', iv: iv }, key, new TextEncoder().encode(data) ); // 将IV和加密结果转换为Base64并拼接 const ivBase64 = btoa(String.fromCharCode(...iv)); const encryptedBase64 = btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer))); return `${ivBase64}:${encryptedBase64}`; }; // 解密函数 export const decryptWithWebCrypto = async (encryptedData, keyString) => { const key = await generateAESKey(keyString); const [ivBase64, encryptedBase64] = encryptedData.split(':'); // 将Base64转换为Uint8Array const iv = new Uint8Array(atob(ivBase64).split('').map(c => c.charCodeAt(0))); const encryptedBuffer = new Uint8Array(atob(encryptedBase64).split('').map(c => c.charCodeAt(0))); // 解密数据 const decryptedBuffer = await crypto.subtle.decrypt( { name: 'AES-CBC', iv: iv }, key, encryptedBuffer ); // 转换为字符串 return new TextDecoder().decode(decryptedBuffer); };
注意:Web Crypto API是异步的,所以所有操作都需要用async/await;另外,确保你的Expo项目使用的是支持Web Crypto的运行环境(Hermes在0.70+版本支持,JSC也支持)。
方案3:自定义Expo模块(适合需要原生级加密的场景)
如果上面的方案都满足不了你的需求(比如需要和原生系统的加密API深度集成),你可以基于expo-modules-core开发一个自定义模块,调用iOS的CommonCrypto或Android的javax.crypto实现AES加密。不过这个方案需要一定的原生开发知识,适合复杂场景。
内容的提问来源于stack exchange,提问作者Sadiq Sadiq
相关产品推荐
相关产品推荐

