如何修复EthCrypto.js中的‘Bad MAC’解密错误?
Bad MAC错误原因及修复方案(EthCrypto.js加解密场景)
错误原因
Bad MAC错误本质是解密时生成的消息认证码与加密后存储的MAC不匹配,核心问题在于签名恢复公钥时使用的哈希值和前端personal.sign签名时的哈希值不一致:
- Web3的
personal.sign方法会自动给待签名消息添加固定前缀:\x19Ethereum Signed Message:\n${消息长度},再对拼接后的完整内容做Keccak256哈希后进行签名。 - 你当前代码直接对原始消息
'Signature verification for video file encryption'做Keccak256哈希,导致恢复出的公钥并非签名账户对应的正确公钥,用错误公钥加密的内容,用正确私钥解密必然触发MAC验证失败。
修复方案
需要在恢复公钥时,构造与personal.sign完全一致的带前缀消息,再计算哈希用于公钥恢复:
修正后的公钥恢复代码
const signature = '0x27b76aa76e75d3a723883629b532b771ec860edb338b0c8421244bbd1f3d0f7078eb7bd17aad73823b0d401e917e7edcc5ca267a34623f4c7e4b3cefbfab7ac31b'; const plaintext = 'test message'; const originalMessage = 'Signature verification for video file encryption'; // 构造personal.sign使用的带前缀消息 const prefixedMessage = `\x19Ethereum Signed Message:\n${originalMessage.length}${originalMessage}`; // 计算带前缀消息的Keccak256哈希 const messageHash = EthCrypto.hash.keccak256(prefixedMessage); // 用带前缀的哈希恢复正确公钥 const publicKey = EthCrypto.recoverPublicKey(signature, messageHash); // 后续加密流程保持不变 const encrypted = await EthCrypto.encryptWithPublicKey(publicKey, plaintext); return EthCrypto.cipher.stringify(encrypted);
额外验证点
- 确认解密用的
privateKey确实属于账户0x500694d00eFc0315Cac629b83Dfd11C8b038AfAa,可通过EthCrypto.publicKeyByPrivateKey(privateKey)生成公钥,与恢复出的公钥对比是否一致。 - 确保加密对象字符串化和解析过程中没有丢失或篡改字段(如iv、ephemPublicKey、ciphertext、mac的格式需完整无修改)。
内容的提问来源于stack exchange,提问作者Boris K
相关产品推荐
相关产品推荐

