fhEVM
WebsiteLibrariesProduct & ServicesDevelopersSupport
0.3
0.3
  • <- Home
  • What is Zama's fhEVM
    • Overview
    • Whitepaper
  • Getting Started
    • Connecting to Zama Devnet
    • Using Zama Faucet
    • Local dev node
  • How to
    • Write contract
      • Using Hardhat
      • Using Remix
      • Other development environment
    • Use encrypted types
    • Operations on encrypted types
    • Generate random number
    • Write conditions
    • Decrypt and reencrypt
    • Estimate gas
    • Common pitfalls and best practises
  • API
    • Function specifications
  • Client SDK
    • Getting started
      • Using Node
      • Using a template
      • Other frontend tooling
      • Using CLI
    • Setup an instance
    • Encrypt an input
    • Get a reencryption
    • Examples
      • Transfer tokens (node)
      • Get balance (node)
  • Resources
    • Examples
    • Tutorials
    • Repositories
  • Future Developments
    • Development Roadmap
  • 🔗Support
    • Community forum
    • Telegram
    • FHE.org discord
    • Twitter
Powered by GitBook

Libraries

  • TFHE-rs
  • Concrete
  • Concrete ML
  • fhEVM

Developers

  • Blog
  • Documentation
  • Github
  • FHE resources

Company

  • About
  • Introduction to FHE
  • Media
  • Careers
On this page
  • How it works
  • Using EIP-712
  • Generate your typed data structure
  • Decrypt a reencrypted value
  • Reuse previously signed public key

Was this helpful?

Export as PDF
  1. Client SDK

Get a reencryption

PreviousEncrypt an inputNextExamples

Last updated 1 year ago

Was this helpful?

How it works

When user needs to access encrypted data, there are two solution for the smart contract developer:

  • Return a decryption of this value. In this case, the becomes public and the confidentiality is compromised.

  • Return a reencryption of this value. In this case, the user provides a public key, the value will be reencrypted from the blockchain's FHE public key to this public key.

A value reencryption is accessible through a view function. However, it's important to note that there's a potential vulnerability where msg.sender can be spoofed, and you cannot guarantee that the msg.sender truly represents the user.

Using EIP-712

To prevent this issue, the smart contract can use the . It describes how data is structured, hashed, and signed. By utilizing this data format and having it signed by the user, a secure process of reencrypting data becomes possible within a smart contract. The signed structure includes the necessary information, including the public key, which allows for seamless reencryption of the data.

  1. The user provides the signature of the EIP-712 object and the public key

  2. The contract verify the signature by generating the EIP-712 with the provided public key. The signature must match the msg.sender

  3. If the signature match, the contract can return the reencryption of the value with the provided public key

fhevmjs provides a convenient function that generates this structured object and store user's signatures.

Generate your typed data structure

You can generate the data to sign:

const instance = getInstance();
const reencryption = instance.generatePublicKey("0x1c786b8ca49D932AFaDCEc00827352B503edf16c");
const params = [userAddress, JSON.stringify(reencryption.eip712)];
const sign = await window.ethereum.request({
  method: "eth_signTypedData_v4",
  params,
});

const encryptedBalance = await contract.balanceOf(reencryption.publicKey, sign);

Decrypt a reencrypted value

When generating the public key using generatePublicKey, the corresponding private key is kept by the fhEVM instance and linked to the specified contract. To decrypt a value using the user's private key, you only need to provide the contract address and the encrypted value.

const encryptedBalance = await contract.balanceOf(reencryption.publicKey, sign);
const balance = instance.decrypt("0x1c786b8ca49D932AFaDCEc00827352B503edf16c", encryptedBalance);

Reuse previously signed public key

Upon the user's signing of the public key, it is advisable to keep the signature for potential use in other reencryption requests. The library offers the setPublicKeySignature method to link this signature with the contract's public key.

const instance = getInstance();
const reencryption = instance.generatePublicKey("0x1c786b8ca49D932AFaDCEc00827352B503edf16c");
const params = [userAddress, JSON.stringify(reencryption.eip712)];
const sign = await window.ethereum.request({
  method: "eth_signTypedData_v4",
  params,
});

instance.setPublicKeySignature("0x1c786b8ca49D932AFaDCEc00827352B503edf16c", sign);

When the signature is saved, you can reuse it with getPublicKey().

const reencryption = instance.getPublicKey("0x1c786b8ca49D932AFaDCEc00827352B503edf16c");

const encryptedBalance = await contract.balanceOf(reencryption.publicKey, reencryption.signature);

You can merge these two functions to create one that returns both the public key and the signature. To check if a signed key pair already exists for a specific contract, you can use the hasKeypair() method provided by the instance.

const getPublicKey = async (contractAddress) => {
  const instance = getInstance();
  if (!instance.hasKeypair(contractAddress)) {
    const reencryption = instance.generatePublicKey("0x1c786b8ca49D932AFaDCEc00827352B503edf16c");
    const params = [userAddress, JSON.stringify(reencryption.eip712)];
    const sign = await window.ethereum.request({
      method: "eth_signTypedData_v4",
      params,
    });
    instance.setPublicKeySignature(contractAddress, sign);
  }
  return instance.getPublicKey(contractAddress);
};

const reencryption = await getPublicKey(contractAddress);
const encryptedBalance = await contract.balanceOf(reencryption.publicKey, reencryption.signature);

Note: only signed keypairs are returned by hasKeypair() and getPublicKey.

EIP-712 standard