Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decrypt is rejected with message of "MetaMask DecryptMessage: User denied message decryption." even though the user clicks on "Decrypt" on Metamask #4139

Closed
Eric1015 opened this issue Jun 12, 2023 · 4 comments
Assignees
Labels
investigate Under investigation and may be a bug. v6 Issues regarding v6

Comments

@Eric1015
Copy link

Eric1015 commented Jun 12, 2023

Ethers Version

6.5.1

Search Terms

metamask, decrypt, eth_decrypt, ethers.js

Describe the Problem

I was trying to test the encrypt and decrypt feature of ethers.js with the public and private keys from the metamask wallet and built a really simple application that will retrieve the public key and encrypt the user's provided string, then decrypt the encrypted message to see if it will go back to the original message. When I clicked on "Decrypt" after initiating decryption, it throws the error saying the user is denying the decryption action. Screen recording attached.

Screen.Recording.2023-06-12.at.1.13.23.AM.mov

The full code can be found here too: https://github.com/Eric1015/metamask-encrypt-file-example

Code Snippet

Here is the code of how I am decrypting the message:

  const decryptMessage = useCallback(
    async (encryptedMessage: string) => {
      const { provider } = state;
      if (provider == null) return;
      const accounts: string[] = await provider.send('eth_requestAccounts', []);
      return await provider.send('eth_decrypt', [
        encryptedMessage,
        accounts[0],
      ]);
    },
    [state]
  );

The provider inside of the state is created in the following manner and stored as state:

      const { ethereum } = window;

      const provider = new ethers.BrowserProvider(ethereum);

Errors

Error: user rejected action (action="unknown", reason="rejected", info={ "error": { "code": -32603, "data": { "originalError": {  } }, "message": "MetaMask DecryptMessage: User denied message decryption." }, "payload": { "id": 9, "jsonrpc": "2.0", "method": "eth_decrypt", "params": [ "cynO2IeYe/weLFuV3/Ec2hhpxFFg5OU=", "<address>" ] } }, code=ACTION_REJECTED, version=6.5.1)

Environment

Ethereum (mainnet/ropsten/rinkeby/goerli)

Environment (Other)

Sepolia

@Eric1015 Eric1015 added investigate Under investigation and may be a bug. v6 Issues regarding v6 labels Jun 12, 2023
@ricmoo
Copy link
Member

ricmoo commented Jun 13, 2023

I don't think this has anything to do with ethers.It looks like MetaMask returned a rejected error.

I know MetaMask is deprecating the decrypt method as there are potential security vulnerabilities with it. Did you recently update and maybe they are enforcing the deprecation now? Or does it maybe need to be enabled in the MetaMask settings?

Can you try adding provider.on("debug", console.log) to get more context on what the provider is actually sending across the wire.

@Eric1015
Copy link
Author

Thank you for your comment. I have tried above to get more logs, but it does not seem to give me extra information, only the following:

{
    "action": "receiveEip1193Error",
    "error": {
        "code": -32603,
        "data": {
            "originalError": {}
        },
        "payload": {
            "method": "eth_decrypt",
            "params": [
                "jRjoEJbW8OqHcf27nB/UmW+fwRqHHxY=",
                "<wallet_address>"
            ]
        }
    }
}

As much as I know receiveEip1193Error represents users rejecting the action, so it still means the same thing as above.

For reference:
Metamask deprecating decrypt and getEncryptionPublicKey methods: https://medium.com/metamask/metamask-api-method-deprecation-2b0564a84686

@promet99
Copy link

promet99 commented Jul 1, 2023

@Eric1015, I guess the api doc you read is a bit insufficient, and therefore mislead you.

The first argument isn't just the encrypted string itself, but it is either a) stringified JSON of the whole encryption result (ciphertext, nonce, version, and ephemPublicKey), or roughly a JSON-Buffer-HexString encoded version of aforementioned a). (code example is provided below)

The encrypt function mentioned above is x25519-xsalsa20-poly1305 encryption, like below.
https://metamask.github.io/eth-sig-util/latest/functions/encrypt.html
It returns a object with type as:

export type EthEncryptedData = {
  version: string;
  nonce: string;
  ephemPublicKey: string;
  ciphertext: string;
};

So the first argument of eth_decypt can be like:
(Assuming variable encryptionResult of type EthEncryptedData)
a) console.log(JSON.stringify(encryptionResult), "utf8");
b) `0x${Buffer.from(JSON.stringify(encryptionResult), "utf8").toString("hex")}`);

The following link may help.
https://betterprogramming.pub/exchanging-encrypted-data-on-blockchain-using-metamask-a2e65a9a896c

@Eric1015
Copy link
Author

@promet99 Thank you for your comment, yeah you are right. It seems like I was using them in the wrong way.

Closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigate Under investigation and may be a bug. v6 Issues regarding v6
Projects
None yet
Development

No branches or pull requests

3 participants