Skip to main content

Identity-based encryption (IBE)

Advanced
vetKeys
Identity-based encryption

The vetKeys feature enables Identity-based encryption (IBE), allowing data to be encrypted directly to an identity, such as a principal, an Internet Identity, an email address, or even an Ethereum address.

At a high level, IBE uses the following workflow:

  1. A single master public key is generated and made available to all users.
  2. The sender encrypts a message using the master public key and the recipient's identity. The same master key can be used to encrypt messages to any recipient.
  3. The recipient authenticates using their identity to obtain a matching private decryption key, which is then used to decrypt the message.

The underlying design of the vetKD protocol is based on a threshold-variant of Boneh-Franklin IBE, and incorporates the following features:

  • The master public key is generated and maintained in a distributed manner on an ICP subnet.

  • The vetkd_public_key API can be used to obtain the master public key of an IBE, which is then used to encrypt messages to identities.

  • The vetkd_derive_key API can be used to derive the user decryption key. The decryption key is securely encrypted using the user-provided transport key.

  • Canisters can enforce access control, ensuring that users are only able to request keys for their own identities.

IBE works differently than the distributed key management service (DKMS). In DKMS, one or more users share the same symmetric key, and only those users can encrypt and decrypt data using that key. In contrast, IBE is an asymmetric encryption scheme. Anyone can encrypt messages to a given identity, but only the holder of the corresponding decryption key can decrypt them.

How to use IBE

This example will explain how to use IBE with vetKeys using the basic IBE example, which implements a simple IBE messaging system between principals.

In the example, users authenticate using their principals, encrypt messages, then store the cipher texts in the canister. Then, the recipient retrieves their messages and encrypted IBE private key, decrypts and verifies the private (decryption) key, and finally decrypts the encrypted messages. In this scenario, communication and key retrieval happen in the same canister.

Step 1: Obtain the IBE public key from the backend

Expose a canister endpoint that can fetch the IBE public key of the canister.

examples/basic_ibe/backend/src/lib.rs
loading...

The public key only needs to be fetched once and can then be reused to encrypt data for multiple recipients by deriving the corresponding subkeys locally. To ensure cryptographic separation and prevent cross-protocol interference, it's good practice to include a domain separator in the context when using IBE. This distinguishes IBE usage from any other potential applications of vetKeys that the canister may support. The domain separator can be any unique and arbitrary byte string.

Step 2: Obtain the IBE public key and encrypt data in the frontend

Use the frontend @dfinity/vetkeys library to encrypt data and store it in the frontend canister. To encrypt messages, the sender uses the recipient's principal as the encryption identity (set in the input variable of the vetkd_derive_key arguments).

examples/basic_ibe/frontend/src/main.ts
loading...

Step 3: Obtain the IBE private key from the backend

Expose a canister endpoint that can fetch the IBE private key of the user making the call.

examples/basic_ibe/backend/src/lib.rs
loading...

The transport public key used for the call is a temporary, throwaway key generated on the frontend by the @dfinity/vetkeys library. The corresponding private key only needs to be fetched once and can be reused to decrypt multiple cipher texts, regardless of the senders’ identities.

Step 4: Obtain the IBE private key and decrypt data in the frontend

Obtain the encrypted data from the canister or another storage location. Decrypt the IBE-encrypted data in the frontend using the @dfinity/vetkeys frontend library.

For a detailed overview of the basic flow for obtaining vetKeys, refer to the API documentation.

examples/basic_ibe/frontend/src/main.ts
loading...

Examples