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:
- Challenge Request: Get a random challenge from
/challenge/init/{viewAddress} - Challenge Solve: Submit signed challenge to
/challenge/solveto get JWT token and CSRF token
Core Endpoints
/challenge
Authentication endpoints:
GET /challenge/init/{viewAddress}: Get random challenge for authenticationGET /challenge/solve: Submit signed challenge to get JWT and CSRF tokensGET /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 keyPOST /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 addressGET /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 addressfromBlock: Optional. Start block numbertoBlock: 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"
}