# How to get a re-encryption

This document explains how to perform re-encryption. Re-encryption is required when you want a user to access their private data without it being exposed to the blockchain.

To preform the process you will first need to retrieve the ciphertext from the blockchain and then use the client-side code to preform the re-encryption.

Re-encryption allows you to securely convert the encrypted ciphertext from one form - encrypted with a FHE blockchain key - to another - encrypted with a Client-side public key (NaCl public key) without revealing the underlying plaintext in between.

## Retrieve the ciphertext

To retrieve the ciphertext that needs to be re-encrypted, you must implement a view function in your contract. Here's is an example:

```solidity
import "fhevm/lib/TFHE.sol";

contract EncryptedERC20 {
  ...
  function balanceOf(account address) public view returns (bytes euint64) {
    return balances[msg.sender];
  }
  ...
}
```

## Re-encrypt the ciphertext

Then, you can implement the client-side code to re-encrypt the ciphertext. This step is designed to run in a browser, here is an example:

```javascript
import abi from "./abi.json";
import { Contract, BrowserProvider } from "ethers";
import { createInstance } from "fhevmjs";

const CONTRACT_ADDRESS = "";

const provider = new BrowserProvider(window.ethereum);
const accounts = await provider.send("eth_requestAccounts", []);
const USER_ADDRESS = accounts[0];

// Create a fhevmjs instance using the Zama's network and the Zama's Gateway
const instance = await createInstance({
  kmsContractAddress: "0x208De73316E44722e16f6dDFF40881A3e4F86104",
  aclContractAddress: "0xc9990FEfE0c27D31D0C2aa36196b085c0c4d456c",
  networkUrl: "https://devnet.zama.ai/",
  gatewayUrl: "https://gateway.zama.ai/",
});

// Generate the private and public key, used for the reencryption
const { publicKey, privateKey } = instance.generateKeypair();

// Create an EIP712 object for the user to sign.
const eip712 = instance.createEIP712(publicKey, CONTRACT_ADDRESS);

// Request the user's signature on the public key
const params = [USER_ADDRESS, JSON.stringify(eip712)];
const signature = await window.ethereum.request({ method: "eth_signTypedData_v4", params });

// Get the ciphertext to reencrypt
const encryptedERC20 = new Contract(CONTRACT_ADDRESS, abi, signer).connect(provider);
const encryptedBalance = encryptedERC20.balanceOf(userAddress);

// This function will call the gateway and decrypt the received value with the provided private key
const userBalance = instance.reencrypt(
  encryptedBalance, // the encrypted balance
  privateKey, // the private key generated by the dApp
  publicKey, // the public key generated by the dApp
  signature, // the user's signature of the public key
  CONTRACT_ADDRESS, // The contract address where the ciphertext is
  USER_ADDRESS, // The user address where the ciphertext is
);

console.log(userBalance);
```
