## Tutorial on how to use native MetaMask encryption-decryption functions

Every Ethereum account is associated with private/public key pair. A natural question is how to use these keys for encrypting data? Does MetaMask support encryption? This tutorial will show a user-friendly way to use MetaMask to exchange encrypted messages on a blockchain.

Throughout this tutorial, I am using TypeScript notation because I think it helps understand what’s going on. Please remove the types from the code if you use JavaScript.

When developing our latest project FELToken — a tool for decentralized privacy-preserving machine learning — we needed to exchange data only between concrete accounts on the blockchain. Every account is associated with a key pair, which primary purpose is for signing transactions. However, it can be used for encryption as well. The only issue is that users’ wallets usually handle these keys, and asking users to copy their private keys is terrible. Using functions provided by the wallet is a much cleaner solution.

Here is just a quick review of public-key cryptography. The core idea is that you have public and private keys linked by some mathematical properties. If you encrypt a message with the public key, only the private key can decrypt it. This means that you can share the public key with other people. They can then use it for encrypting messages which only you can decrypt. Moreover, encryption works the other way round, commonly used for signing messages.

Essential for us is that if Alice wants to send a secret message to Bob, it requires the following steps:

- Bob sends Alice his public key
- Alice encrypts the message using Bob’s public key
- Alice sends the encrypted message to Bob
- Bob decrypts the message using his private key

Cryptography is a crucial part of the web, regardless of the number, and in my opinion, every developer should know at least the basics of cryptography. For more practical info, I recommend the following book:

Luckily, there is a native **decryption **function inside MetaMask. On the other hand, the encryption mechanism isn’t standardised, so this function most likely isn’t supported by other wallets. Regardless of that, let’s look at the MetaMask decryption in more detail.

Most information about this function is provided in the MetaMask documentation:

I will mention this later as well, but the documentation skipped the fact that the decryption works only if the plain text contains valid UTF-8. It won’t work for arbitrary bytes sequences!

## 1. Bob sends Alice his public key

The first step is to obtain Bob’s public key and send it to Alice. This key is necessary for encryption, and it can be publicly shared. In fact, you share this key with every blockchain transaction you send. You might already know that the account address isn’t the same as the public key. The address is calculated as a hash of the public key, making it impossible to easily calculate the public key for based on user address (untunate decision, in my opinion).

We first need to request a public key from MetaMask. We can use function `eth_getEncryptionPublicKey`

provided by MetaMask. Using this function is relatively straightforward; just pass the account address. The app must have access to a specified account; Passing a random account will fail.