Skip to content

Trusted Encryption Service (TES)

The Trusted Encryption Service (TES) is a backend service that provides encryption/decryption capabilities and user metadata management for the ZeroLedger ecosystem.

Overview

TES handles:

  • Encryption/Decryption: Secure data encryption and decryption with wallet-based authentication. This is only required when you want to send a transaction to a user who has not yet registered their view account public key with TES.
  • User Metadata Management: User data storage and retrieval
  • Challenge Authentication: Wallet-based authentication system

Access Restrictions

Current Limitations: The TES service is currently restricted to the official ZeroLedger web application only due to CORS (Cross-Origin Resource Sharing) policies. This means:

  • Official Web App Only: Only the official ZeroLedger web app can access TES endpoints
  • CORS Protection: Third-party applications cannot directly integrate with TES
  • Security Measure: This restriction ensures controlled access and prevents unauthorized usage

Future Plans: An independent TES service will be deployed later to enable third-party application integration.

API Endpoints

Authentication Flow

TES uses a two-step authentication process:

  1. Challenge Request: Get a random challenge from /challenge/init/{viewAddress}
  2. Challenge Solve: Submit signed challenge to /challenge/solve to get JWT token and CSRF token

Core Endpoints

/challenge

Authentication endpoints:

  • GET /challenge/init/{viewAddress}: Get random challenge for authentication
  • GET /challenge/solve: Submit signed challenge to get JWT and CSRF tokens
  • GET /challenge/validate: Validate view account for a given owner

Authentication Flow:

// 1. Get challenge
const challengeResponse = await fetch(
  `${tesUrl}/challenge/init/${viewAddress}`
);
const { random } = await challengeResponse.json();
 
// 2. Sign challenge with view account
const signature = await viewAccount.signMessage({ message: { raw: random } });
 
// 3. Create auth token
const authToken = encodeAbiParameters(
  ["address", "bytes", "address", "bytes"],
  [viewAddress, signature, ownerAddress, delegationSignature]
);
 
// 4. Solve challenge
const solveResponse = await fetch(`${tesUrl}/challenge/solve`, {
  headers: { Authorization: `Bearer ${authToken}` },
});
const { exp, csrf } = await solveResponse.json();

/encryption

Encryption/decryption endpoints:

  • GET /encryption/tepk: Get trusted encryption public key
  • POST /encryption/decrypt: Decrypt transaction metadata

Usage:

// Get trusted encryption public key
const tepkResponse = await fetch(`${tesUrl}/encryption/tepk`, {
  headers: { "x-custom-tes-csrf": csrf },
});
const { tepk } = await tepkResponse.json();
 
// Decrypt metadata
const decryptResponse = await fetch(`${tesUrl}/encryption/decrypt`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-custom-tes-csrf": csrf,
  },
  body: JSON.stringify({
    block: encryptedBlock,
    token: tokenAddress,
    poseidonHash: commitmentHash,
  }),
});
const { decryptedCommitment } = await decryptResponse.json();

/userMetadata

User metadata endpoints:

  • GET /userMetadata/publicKey/{address}: Get encryption public key for address
  • GET /userMetadata/decoyRecipient: Get random decoy recipients

Usage:

// Get public key for address
const publicKeyResponse = await fetch(
  `${tesUrl}/userMetadata/publicKey/${address}`
);
const { publicKey } = await publicKeyResponse.json();
 
// Get decoy recipients
const decoyResponse = await fetch(
  `${tesUrl}/userMetadata/decoyRecipient?amount=3`
);
const decoyRecipients = await decoyResponse.json();

/sync

Sync service endpoints:

  • GET /sync?token={token}&fromBlock=${fromBlock}&toBlock={toBlock}: Get random decoy recipients

Request Parameters:

  • token: Token contract address
  • fromBlock: Optional. Start block number
  • toBlock: Optional. End block number

Response:

{
  "events": [
    {
      "eventName": "CommitmentCreated",
      "args": {
        "owner": "0x...",
        "token": "0x...",
        "poseidonHash": "0x...",
        "metadata": "0x..."
      },
      "blockNumber": "12345678",
      "transactionIndex": 0,
      "transactionHash": "0x..."
    }
  ],
  "syncedBlock": "12345678"
}