Skip to main content

Integrating Shutter API and Shutter SDK for dApp Development

note

This document is designed to be LLM friendly, work with current web standards, enabling fast and accurate responses for seamless communication with AI models.

This guide is designed to teach you (or a generative AI) how to integrate the Shutter API and Shutter SDK into your decentralized application (dApp). The Shutter protocol provides a secure and decentralized commit-and-reveal mechanism that leverages threshold encryption, distributed cryptographic operations, and multi-party computation (MPC) techniques.

Disclaimer:

The Shutter API is in early development stage. Do not use it to manage high-value assets until the network is fully matured and decentralized. Use at your own risk.


Overview of Shutter

The Shutter system facilitates secure commit-and-reveal workflows using:

  • Threshold Encryption: No single entity can compromise the encrypted data.
  • Distributed Keypers: Nodes that monitor on-chain events and handle decryption key releases.
  • API Endpoints & SDK: Simplified interfaces for dApp developers to integrate encryption and decryption functionalities.

The system consists of:

  • Registry Contract: Where identities and time-based decryption triggers are registered.
  • Keypers: Responsible for cryptographic operations and decentralized key management.
  • Shutter API: Provides endpoints for encryption and decryption operations.
  • Shutter SDK: A TypeScript library that abstracts encryption/decryption operations, easing integration in modern dApps.

System Architecture

Key components include:

  • Client dApp: Your application that calls the Shutter API or uses the SDK.
  • Registry Contract: Deployed on-chain (e.g., Chiado or Gnosis) that holds identity and trigger information.
  • Shutter API: Endpoints for identity registration, encryption data retrieval, key retrieval, and decryption.
  • Keypers: Nodes that perform threshold cryptography.

Prerequisites and Setup

Before integrating Shutter into your dApp, ensure you have:

  • API Endpoint Access

    For example:

  • Familiarity with RESTful APIs and Ethereum-based dApp development.

  • Installation of Node.js and npm (if you plan to use the TypeScript SDK).


Integrating the Shutter API

The Shutter API exposes several endpoints to handle the full lifecycle of encryption and decryption in your dApp. The key endpoints are:

Registering an Identity with a Decryption Trigger

This is your first step. Register your identity along with a time-based decryption trigger (a Unix timestamp). The API computes your identity based on your API account address unless you register directly with the registry contract.

Endpoint:  /register_identity
Method: POST

Example Request

curl  -X  POST  https://`API_BASE_URL`/register_identity

-H "Content-Type: application/json"

-d '{

  "decryptionTimestamp": 1735044061,

  "identityPrefix": "0x79bc8f6b4fcb02c651d6a702b7ad965c7fca19e94a9646d21ae90c8b54c030a0"

}'

Example Response

{

  "eon": 1,

  "eon_key": "0x57af5437a84ef50e5ed75772c18ae38b168bb07c50cadb65fc6136604e662255",

  "identity": "0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75",

  "identity_prefix": "0x79bc8f6b4fcb02c651d6a702b7ad965c7fca19e94a9646d21ae90c8b54c030a0",

  "tx_hash": "0x3026ad202ca611551377eef069fb6ed894eae65329ce73c56f300129694f12ba"

}

Note: Replace API_BASE_URL with the appropriate API base URL (Chiado or Mainnet).


Retrieving Encryption Data

After registration, you need to obtain the encryption parameters that are required to encrypt your commitments.

Endpoint:  /get_data_for_encryption
Method: GET

Example Request

curl  -X  GET  "https://`API_BASE_URL`/get_data_for_encryption?address=0xb9C303443c9af84777e60D5C987AbF0c43844918&identityPrefix=0x79bc8f6b4fcb02c651d6a702b7ad965c7fca19e94a9646d21ae90c8b54c030a0"

Example Response

{

  "eon": 1,

  "eon_key": "0x57af5437a84ef50e5ed75772c18ae38b168bb07c50cadb65fc6136604e662255",

  "identity": "0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75",

  "identity_prefix": "0x79bc8f6b4fcb02c651d6a702b7ad965c7fca19e94a9646d21ae90c8b54c030a0",

  "epoch_id": "0x88f2495d1240f9c5523db589996a50a4984ee7a08a8a8f4b269e4345b383310abd2dc1cd9c9c2b8718ed3f486d5242f5"

}

Retrieving the Decryption Key

Once the specified decryption timestamp has passed, you can retrieve the decryption key. This key is used later to decrypt the encrypted commitments.

Endpoint:  /get_decryption_key
Method: GET

Example Request

curl  -X  GET  "https://`API_BASE_URL`/get_decryption_key?identity=0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75"

Example Response

{

  "decryption_key": "0x99a805fc26812c13041126b25e91eccf3de464d1df7a95d1edca8831a9ec02dd",

  "decryption_timestamp": 1735044061,

  "identity": "0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75"

}

Decrypting Commitments

With the decryption key in hand, you can now decrypt any previously encrypted commitments.

Endpoint:  /decrypt_commitment
Method: GET

Example Request

curl  -X  GET  "https://`API_BASE_URL`/decrypt_commitment?identity=0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75&encryptedCommitment=0x03b5685a460a95ba628e04b24155d6722f7c4e376a1627f714a4ae9cecd2982e005eff12ac8150b8842c29f8d5eaf4d0da0b626f762b4826d779d8969b577acb28df96cab026aa57c00cd74b07ca51e8c0c1a59933e29a728311900ebfc26c6804260914c96cb10dbd6d2ed3f6cb77788a74b5aae5f4ce6f40be53310a0524d42d5a6f03b5c1517ec097553733e228276fcdfc4b569f7ef4311a461d68819d634c"

Example Response

{

  "decrypted_message": "0x706c6561736520686964652074686973206d657373616765"

}

Tip: The decrypted message is returned in hexadecimal format. Convert it to a string (e.g., using web3.js or ethers.js) to reveal the original message.


Integrating the Shutter SDK

The Shutter SDK is a TypeScript library that simplifies the encryption and decryption process. It wraps the lower-level operations of the Shutter protocol into high-level functions that you can easily integrate into your dApp.

Installation

To install the Shutter SDK in your project, run:

npm install @shutter-network/shutter-sdk


Encrypting Data (TypeScript)

Below is a sample code snippet that demonstrates how to use the SDK to encrypt data:

import  {  encryptData  }  from  "@shutter-network/shutter-sdk";

import { stringToHex } from "viem";

// Define the encryption data from the API

const eonKeyHex = "0x57af5437a84ef50e5ed75772c18ae38b168bb07c50cadb65fc6136604e662255";

const identityPreimageHex = "0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75";

const message = "please hide this message";

const sigmaHex = "0x312c10b186086d502ba683cffc2ae650d53b508904b3c430df8e7d5aa336c0f5";

// Encrypt the message

const encryptedCommitment = await encryptData(message, eonKeyHex, identityPreimageHex, sigmaHex);

console.log("Encrypted Commitment:", encryptedCommitment);

Decrypting Data (TypeScript)

To decrypt an encrypted commitment, use the decrypt function provided by the SDK:

import  {  decrypt  }  from  "@shutter-network/shutter-sdk";

const encryptedData = "0x03a975256b0098bc981da31762a73e50a07c79f5bf3e17c44121b9567033cedaf9e203f0300b709dec3458a88baa18963c0e503f437bff7adb31231941585ea1bb14e8ce98c7dc1471666e4b07c592cbeda30acc22f23dcb84d58d41848e72af0804d348d5c5cb65a52dc3b697ea4caae9679b97e395a30807f9657ebc85bbf2fcadaa9a458a86bffb78dde89f7626a26eb84f4781d3b6759c06629ea321a8b757";

const decryptionKey = "0x81cfcfceebfc69b3cb3fe074f4b3751e7844f6d62b3040563ccb3a2430110f259d109519c73682735f4c02651492c740";

// Decrypt the data

const decryptedData = await decrypt(encryptedData, decryptionKey);

console.log("Decrypted Message:", decryptedData);

Example in Go

For dApps or backend services written in Go, you can use the provided example to encrypt commitments. This sample leverages the shcrypto package from Shutter's repository.

package  main

import (

  "crypto/rand"

  "encoding/hex"

  "fmt"

  "log"

  "strings"

  "github.com/shutter-network/shutter/shlib/shcrypto"

)

func main() {

  // Encryption data from the Shutter API

  identityHex := "0x8c232eae4f957259e9d6b68301d529e9851b8642874c8f59d2bd0fb84a570c75"

  eonPublicKeyHex := "0x57af5437a84ef50e5ed75772c18ae38b168bb07c50cadb65fc6136604e662255"

  message := []byte("please hide this message")

  identityHex = strings.TrimPrefix(identityHex, "0x")

  eonPublicKeyHex = strings.TrimPrefix(eonPublicKeyHex, "0x")

  // Convert hex strings to bytes

  identity, err := hex.DecodeString(identityHex)

  if err != nil {

    log.Fatalf("Failed to decode identity: %v", err)

  }

  eonPublicKeyBytes, err := hex.DecodeString(eonPublicKeyHex)

  if err != nil {

    log.Fatalf("Failed to decode eon public key: %v", err)

  }

  // Unmarshal the public key

  eonPublicKey := &shcrypto.EonPublicKey{}

  if err := eonPublicKey.Unmarshal(eonPublicKeyBytes); err != nil {

    log.Fatalf("Failed to unmarshal EonPublicKey: %v", err)

  }

  // Compute the Epoch ID from the identity

  epochID := shcrypto.ComputeEpochID(identity)

  // Generate a random sigma value

  sigma, err := shcrypto.RandomSigma(rand.Reader)

  if err != nil {

    log.Fatalf("Failed to generate random sigma: %v", err)

  }

  // Encrypt the message

  encryptedCommitment := shcrypto.Encrypt(message, eonPublicKey, epochID, sigma)

  // Marshal the encrypted commitment and encode to hex

  encryptedCommitmentBytes := encryptedCommitment.Marshal()

  encryptedCommitmentHex := "0x" + hex.EncodeToString(encryptedCommitmentBytes)

  fmt.Printf("Encrypted Commitment: %s\n", encryptedCommitmentHex)

}

Building a New dApp with Shutter API

When building a new dApp with the Shutter API, follow these steps:

  1. Set Up Your Environment

    Ensure you have access to the appropriate API endpoints (Chiado or Mainnet) and that your project includes a web3 provider for interacting with the registry contract.

  2. Register an Identity

    Use the /register_identity endpoint to register a new identity and set a decryption trigger.

    Tip: If you want full control over your address, consider registering directly with the registry contract.

  3. Retrieve Encryption Data

    Once your identity is registered, call /get_data_for_encryption to obtain the parameters needed to encrypt commitments.

  4. Encrypt Commitments

    Use either the provided SDK (TypeScript) or native implementations (Go, etc.) to encrypt your sensitive messages or commitments before storing or transmitting them.

  5. Store and Manage Encrypted Data

    Persist the encrypted commitments within your dApp (for example, on-chain, in IPFS, or a centralized database) until the decryption trigger is activated.

  6. Retrieve and Decrypt Data

    After the trigger time passes, use the /get_decryption_key endpoint to fetch the decryption key, and then call /decrypt_commitment or use the SDK's decrypt function to reveal the original message.

  7. User Interaction and UI

    Integrate WebSocket or polling mechanisms to notify your users when decryption keys become available. Future releases of Shutter will enhance real-time notifications.


Future Features and Considerations

  • Event-Based & Block-Based Triggers

    In future versions, decryption triggers may be based on blockchain events or block numbers, offering more flexibility.

  • Real-Time Notifications

    Planned WebSocket integrations will enable real-time notifications for key releases.

  • Enhanced Decentralization

    As more Keypers join the network, the decentralization and resilience of the system will continue to improve.


FAQs

What if a Keyper goes offline?

The system is designed to handle downtime gracefully. Any missed decryption key releases will be processed when the network recovers.

How secure is the Shutter system?

Using threshold encryption and distributed key management, Shutter ensures that no single party can compromise the encrypted data. However, as the network evolves, always monitor updates and recommendations.

Can I use my own address for identity registration?

Yes. By default, the API uses the account address to compute the identity. If you prefer to use your own address, register directly with the registry contract.


Additional Resources