React Native中Node.js加密代码转crypto-es实现问题求助
修正后的React Native Expo TypeScript实现
import { useCallback, useMemo } from 'react'; import CryptoES from 'crypto-es'; export type CryptographyProps = { readonly text: string; }; const ENCRYPTION_KEY = 'some-random-key-12345'; // 原Node.js用ASCII编码生成salt,Utf8对ASCII字符兼容,无需修改 const SALT = CryptoES.enc.Utf8.parse(ENCRYPTION_KEY); const iterationCount = 1000; const getKeyAndIv = () => { // 原Node.js生成48字节(32字节key + 16字节iv),对应crypto-es的keySize=12(每单位是4字节) const keyDerivation = CryptoES.PBKDF2(ENCRYPTION_KEY, SALT, { keySize: 12, iterations: iterationCount, hasher: CryptoES.algo.SHA1, }); // 直接从WordArray截取对应字节,避免Hex转换的潜在误差 const key = CryptoES.lib.WordArray.create( keyDerivation.words.slice(0, 8), // 8个32位字 = 32字节 32 ); const iv = CryptoES.lib.WordArray.create( keyDerivation.words.slice(8), // 4个32位字 = 16字节 16 ); return { key, iv }; }; export const useNewCryptography = () => { const encrypt = useCallback(({ text }: CryptographyProps): string => { const { key, iv } = getKeyAndIv(); // 使用Utf16LE编码(对应Node.js的utf16le),而非默认的Utf16(大端序) const encrypted = CryptoES.AES.encrypt( CryptoES.enc.Utf16LE.parse(text), key, { iv: iv, padding: CryptoES.pad.Pkcs7, mode: CryptoES.mode.CBC, } ); return encrypted.toString(); // 默认输出Base64,和原Node.js逻辑一致 }, []); const decrypt = useCallback(({ text }: CryptographyProps): string => { const { key, iv } = getKeyAndIv(); const decrypted = CryptoES.AES.decrypt(text, key, { iv: iv, padding: CryptoES.pad.Pkcs7, mode: CryptoES.mode.CBC, }); // 用Utf16LE解码,对应原Node.js的utf16le输出 return CryptoES.enc.Utf16LE.stringify(decrypted); }, []); return useMemo(() => ({ encrypt, decrypt }), [encrypt, decrypt]); };
关键错误点与修正说明
UTF-16编码端序不匹配:
原Node.js代码使用utf16le(小端序)处理文本,而crypto-es默认的CryptoES.enc.Utf16是大端序(UTF-16BE),这会导致文本编码完全错误。修正为CryptoES.enc.Utf16LE即可对齐原逻辑。PBKDF2 keySize计算与WordArray处理错误:
原Node.js通过pbkdf2Sync生成48字节数据(32字节密钥+16字节IV),crypto-es的keySize参数是以**32位字(4字节)**为单位,因此48字节对应keySize: 12(48/4=12)。
原代码通过Hex字符串截取再解析的方式容易引入误差,直接操作WordArray的words数组截取对应部分更准确。冗余的Hex转换:
原实现中将PBKDF2结果转为Hex字符串再截取解析,完全没必要,直接从WordArray的原始数据中分割密钥和IV更高效且避免转换误差。
内容的提问来源于stack exchange,提问作者Tonespy
相关产品推荐
相关产品推荐

