Search code examples
javascriptcryptographyethereum

How do I fix this "Bad MAC" error from EthCrypto.js?


I am trying to encrypt and decrypt messages with EthCrypto.js.

I am getting a signature on the front end via

const accounts = await window.ethereum.request({method: 'eth_requestAccounts'});
          const account = accounts[0];
          const signatureHash = await web3.value.eth.personal.sign('Signature verification for video file encryption', account);

The account address is 0x500694d00eFc0315Cac629b83Dfd11C8b038AfAa

Encryption works fine:

        const signature = '0x27b76aa76e75d3a723883629b532b771ec860edb338b0c8421244bbd1f3d0f7078eb7bd17aad73823b0d401e917e7edcc5ca267a34623f4c7e4b3cefbfab7ac31b'
        const plaintext = 'test message'
        const publicKey = EthCrypto.recoverPublicKey(
            signature,
            EthCrypto.hash.keccak256('Signature verification for video file encryption')
        );
        
        const encrypted = await EthCrypto.encryptWithPublicKey(publicKey, plaintext);
        return EthCrypto.cipher.stringify(encrypted);

I get back an object which looks right:

{
  "iv": "89f37bdafdcb156603804be2bbc4acb3",
  "ephemPublicKey": "04a0e2b193a5e00442f72c69ca035e9f29d9d98e719b8e86d172f14dae1912e443bb35333a776a43b63d6b87108e1f0b1bf0fcdab0e47a7669da9d80b7d7e644ba",
  "ciphertext": "46d5b09c5aad80cbe9e264133afa13e0",
  "mac": "c8237beb6bcee4f5afd361ce0d20364e4bfa533cb530fd1c3821c6e220b8bf7a"
}

then stringify it: const encrypted = await EthCrypto.encryptWithPublicKey(publicKey, plaintext);

The resulting string destringifies into the original object just fine: const parsed = EthCrypto.cipher.parse(ciphertext);

But when I try to decrypt with the private key const decrypted = await EthCrypto.decryptWithPrivateKey(privateKey,parsed); I get a Bad MAC error.

Why is this? It seems like a bug. How do I fix it?


Solution

  • Solved here:

    https://ethereum.stackexchange.com/questions/135888/how-do-i-create-a-signature-with-web3-js-which-ethcrypto-can-process-properly/135900?noredirect=1#comment156154_135900

    The issue is that web3.eth.personal.sign() appends additional characters to the string. Therefore, recovering the public key or address from the signature needs to be done thusly:

    const address2 = EthCrypto.recover( signature, EthCrypto.hash.keccak256( "\x19Ethereum Signed Message:\n" + message.length + message ) );