Learn how to get CVM attestation on Phala Cloud using dashboard or dstack SDK.
Get attestation reports from your CVM to prove it’s running in genuine TEE hardware. You can check the dashboard for quick verification, or use the dstack SDK to generate quotes programmatically with custom data.
The attestation quote includes a 64-byte reportData field for your custom data. Important: The SDK throws an error if you exceed 64 bytes—it does not auto-hash.Two patterns:
Short data (≤64 bytes): Nonces, small challenges, or hashes—pass directly
Long data (>64 bytes): Any arbitrary data—hash it first with SHA256 (produces 32 bytes)
import { DstackClient } from '@phala/dstack-sdk';import crypto from 'crypto';const client = new DstackClient();// Pattern 1: Short data (≤64 bytes) - pass directly// Example: 32-byte nonce for challenge-responseconst nonce = crypto.randomBytes(32);const quote1 = await client.getQuote(nonce);// Pattern 2: Long data (>64 bytes) - hash it first// Example: JSON with arbitrary dataconst userData = JSON.stringify({ version: '1.0.0', timestamp: Date.now(), user_id: 'alice', public_key: '0x1234...'});// Hash to fit in 64 bytes (SHA256 produces 32 bytes)const hash = crypto.createHash('sha256').update(userData).digest();const quote2 = await client.getQuote(hash);console.log('Quote:', quote2.quote);console.log('Event Log:', quote2.event_log);
import jsonimport timeimport hashlibimport secretsfrom dstack_sdk import DstackClientclient = DstackClient()# Pattern 1: Short data (≤64 bytes) - pass directly# Example: 32-byte nonce for challenge-responsenonce = secrets.token_bytes(32)quote1 = client.get_quote(nonce)# Pattern 2: Long data (>64 bytes) - hash it first# Example: JSON with arbitrary datauser_data = json.dumps({ "version": "1.0.0", "timestamp": time.time(), "user_id": "alice", "public_key": "0x1234..."})# Hash to fit in 64 bytes (SHA256 produces 32 bytes)data_hash = hashlib.sha256(user_data.encode()).digest()quote2 = client.get_quote(data_hash)print('Quote:', quote2.quote)print('Event Log:', quote2.event_log)
reportData Parameter RequiredThe getQuote() method requires a reportData parameter. If you don’t need custom data, pass an empty value: '' in TypeScript or b'' in Python. Calling getQuote() without any parameter will fail.
Expose attestation endpoints so external verifiers can validate your CVM. The /attestation endpoint provides the quote for hardware verification, while /info provides the application configuration for code verification:
import express from 'express';import { DstackClient } from '@phala/dstack-sdk';const app = express();const client = new DstackClient();app.get('/attestation', async (req, res) => { const result = await client.getQuote(''); res.json({ quote: result.quote, event_log: result.event_log, vm_config: result.vm_config // Required by dstack-verifier });});app.get('/info', async (req, res) => { const info = await client.info(); res.json(info);});app.listen(8080);
from flask import Flask, jsonifyfrom dstack_sdk import DstackClientapp = Flask(__name__)client = DstackClient()@app.route('/attestation')def get_attestation(): result = client.get_quote(b'') return jsonify({ 'quote': result.quote, 'event_log': result.event_log, 'vm_config': result.vm_config # Required by dstack-verifier })@app.route('/info')def get_info(): info = client.info() return jsonify(info)if __name__ == '__main__': app.run(host='0.0.0.0', port=8080)
These endpoints allow external verifiers to fetch attestation data and verify your CVM. See Verify Your Application for how verifiers use these endpoints.