Firefox调用window.crypto.subtle.decrypt触发DOMException错误求助
问题根源
你的代码核心错误出现在deriveKeyFromPassword函数对salt的处理上:
- 加密阶段生成的是
Uint8Array类型的随机salt,传入该函数后,错误调用encoder.encode(salt)将其转换为字符串的字节编码(实际会把Uint8Array对象转为"[object Uint8Array]"的字节),而非直接使用原始二进制salt数据。 - 这导致加密、解密时推导的AES密钥完全不一致,最终触发Firefox中AES-GCM解密的通用
DOMException(密钥不匹配导致解密验证失败)。
修复方案
修改deriveKeyFromPassword函数,直接使用传入的原始salt二进制数据,移除错误的encoder.encode(salt)调用:
// 修正后的密钥推导函数 async function deriveKeyFromPassword(password, salt) { const encoder = new TextEncoder(); const keyMaterial = await crypto.subtle.importKey( 'raw', encoder.encode(password), { name: 'PBKDF2' }, false, ['deriveBits', 'deriveKey'] ); const derivedKey = await crypto.subtle.deriveKey( { name: 'PBKDF2', salt: salt, // 直接使用传入的二进制salt,不再编码 iterations: 100000, hash: 'SHA-256' }, keyMaterial, { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt'] ); return derivedKey; }
同时建议在解密函数中增加错误捕获与格式校验,方便定位后续问题:
async function decryptTextWithAES(encryptedText, password) { try { const [encryptedDataBase64, ivBase64, saltBase64] = encryptedText.split(':'); // 校验加密文本格式,避免split后出现undefined if (!encryptedDataBase64 || !ivBase64 || !saltBase64) { throw new Error('加密文本格式错误'); } const encryptedData = base64ToArrayBuffer(encryptedDataBase64); const iv = base64ToArrayBuffer(ivBase64); const salt = base64ToArrayBuffer(saltBase64); const key = await deriveKeyFromPassword(password, salt); const decryptedData = await window.crypto.subtle.decrypt( { name: 'AES-GCM', iv }, key, encryptedData ); const decoder = new TextDecoder(); return decoder.decode(decryptedData); } catch (err) { console.error('解密失败:', err); throw err; } }
其他注意事项
- 你设置的salt(16字节)和IV(12字节)长度均符合AES-GCM与PBKDF2的标准要求,无需调整。
- 100000次PBKDF2迭代次数在当前硬件环境下兼顾安全性与性能,是合理设置。
内容的提问来源于stack exchange,提问作者Jason 'Slingshot' Miller
相关产品推荐
相关产品推荐

