/** * Enclave identity and consent primitives for Personal Servers. * * Owner/Web -> Gateway -> Agent(CVM): derive wallet and quote * Web verifies evidence; Account authenticates and encrypts the EIP-191 master * signature to the enclave key; Gateway relays it blind; Agent decrypts/seals. * * @category Protocol */ import { type Address, type Hex } from "viem"; import { type ECIESProvider } from "../crypto/ecies/interface.js"; import type { ServerRegistrationMessage } from "./eip712.js"; export declare const ENCLAVE_IDENTITY_EVIDENCE_VERSION = 1; export declare const USER_PS_ID_DOMAIN = "vana.ps-enclave.v1"; export declare const ENCLAVE_WALLET_PURPOSE = "vana.ps-enclave.wallet.v1"; export declare const MASTER_SIGNATURE_DELIVERY_VERSION = "vana.ps-enclave.delivery.v1"; /** Agent rejects deliveries when `|now - issuedAt|` exceeds this value. */ export declare const MASTER_SIGNATURE_DELIVERY_MAX_AGE_SECONDS = 600; export declare const SEALED_ENVELOPE_VERSION = 1; /** `keccak256(encodePacked([string,uint256,address], [USER_PS_ID_DOMAIN,chainId,owner]))`. */ export type UserPsId = Hex; /** Attested identity evidence returned by the enclave agent. */ export interface EnclaveIdentityEvidence { v: typeof ENCLAVE_IDENTITY_EVIDENCE_VERSION; userPsId: UserPsId; chainId: number; ownerAddress: Address; /** Path suffix `users/{id}/wallet/ethereum/secp256k1/v{epoch}`. */ epoch: number; address: Address; /** 65-byte uncompressed `0x04..`; `publicKeyToAddress(publicKey) == address`. */ publicKey: Hex; /** 20-byte dstack `app_id`. */ appId: Hex; /** 32-byte compose hash. */ composeHash: Hex; /** Omitted when the OS does not expose its image hash. */ osImageHash?: Hex; /** Must equal `ENCLAVE_WALLET_PURPOSE`. */ purpose: string; /** `[appRoot over link 0, kmsRoot over link 1]`; see `appRootPreimage` and `kmsIssuedPreimage`. */ signatureChain: [Hex, Hex]; /** Raw TDX quote with report_data `keccak256(userPsId || address)`; not parsed. */ quote: Hex; eventLog?: string; /** `keccak256` of the uncompressed KMS root public key. */ kmsRootFingerprint: Hex; } /** Identity values the caller expects the evidence to bind. */ export interface ExpectedIdentity { ownerAddress: Address; chainId: number; epoch: number; } /** Request for an owner-scoped enclave identity. */ export interface IdentityRequest { ownerAddress: Address; chainId: number; } /** Lifecycle state of an enclave identity. */ export type IdentityState = "prepared" | "registered" | "sealed" | "retired"; /** Gateway response containing enclave identity state and registration data. */ export interface IdentityResponse { identity: EnclaveIdentityEvidence; state: IdentityState; created: boolean; /** Exact `ServerRegistration.serverUrl` the owner signs. */ serverUrl: string; serverId?: Hex; serverStatus?: "pending" | "submitting" | "confirmed" | "finalized" | "failed"; sealed: boolean; } /** Versioned server-registration request for an enclave identity. */ export type IdentityRegistrationRequest = { version: "v2"; message: ServerRegistrationMessage; } | { version: "v3"; message: ServerRegistrationMessage & { nonce: string; deadline: string; }; }; /** Accepted identity-registration response. */ export interface IdentityRegistrationResponse { serverId: Hex; state: "registered"; serverStatus: "pending"; } /** Inner plaintext of the ECIES box. */ export interface MasterSignatureDelivery { v: typeof MASTER_SIGNATURE_DELIVERY_VERSION; userPsId: UserPsId; epoch: number; enclaveAddress: Address; ownerAddress: Address; /** 65-byte EIP-191 signature over `MASTER_KEY_MESSAGE`. */ masterSignature: Hex; /** Unix seconds; see `MASTER_SIGNATURE_DELIVERY_MAX_AGE_SECONDS`. */ issuedAt: number; } /** Enclave-bound ciphertext submitted for sealing. */ export interface SealedSecretSubmission { userPsId: UserPsId; epoch: number; enclaveAddress: Address; /** `iv(16) || ephemPub(65) || ct || mac(32)` to `evidence.publicKey`. */ ciphertext: Hex; } /** Confirmation that the enclave sealed a submitted secret. */ export interface SealedSecretResponse { sealed: true; /** `sha256(ciphertext)`. */ secretHash: Hex; sealedAt: string; } /** AES-GCM fields encoded as base64 strings. */ export interface AesGcmBox { /** Base64 initialization vector. */ iv: string; /** Base64 ciphertext. */ ciphertext: string; /** Base64 authentication tag. */ tag: string; } /** Persisted enclave envelope; the Gateway treats it as opaque text. */ export interface SealedEnvelope extends AesGcmBox { v: typeof SEALED_ENVELOPE_VERSION; wrappedContentKey: AesGcmBox; } /** Fleet-pinned KMS root and allowed dstack application IDs. */ export interface EnclaveTrustAnchors { kmsRootPubkey: Hex; appIds: readonly Hex[]; } /** Fleet-provisioned trust anchors keyed by Vana chain ID. */ export declare const ENCLAVE_TRUST_ANCHORS: Readonly>>; /** * Derives the deterministic Personal Server ID used by enclave paths. * * @param chainId - Vana chain ID. * @param ownerAddress - Checksummed owner address. * @returns The path-compatible keccak256 digest. */ export declare function userPsId(chainId: number, ownerAddress: Address): UserPsId; /** * Builds keccak256(utf8(purpose || ":" || lowercase hex(compressed pubkey))). * * Matches `dstack/guest-agent/src/rpc_service.rs:612-628`. */ export declare function appRootPreimage(purpose: string, publicKey: Hex): Hex; /** * Hashes the KMS prefix, raw app ID bytes, and compressed app-root public key. * * Matches `dstack/kms/src/crypto.rs:23-40`; there is no separator between the * raw 20-byte app ID and the compressed key. */ export declare function kmsIssuedPreimage(appId: Hex, appRootPublicKey: Hex): Hex; /** * Verifies the enclave wallet binding against fleet-provisioned trust anchors. * * @param evidence - Identity evidence returned by the enclave agent. * @param anchors - Pinned KMS root and allowed dstack app IDs. * @param expected - Owner, chain, and epoch requested by the caller. * * @remarks * The dstack chain signs only `purpose || publicKey` and `appId || appRootPub`; * owner, chain and epoch are bound to the key by the TDX quote report_data * (`keccak256(userPsId || address)`), which v1 stores but does not verify * (DCAP is step 4). Until then the agent's derivation check is the backstop. * @throws When any identity binding or trust check fails. */ export declare function verifyEnclaveIdentityEvidence(evidence: EnclaveIdentityEvidence, anchors: EnclaveTrustAnchors, expected: ExpectedIdentity): Promise; /** * Builds the authenticated master-signature plaintext delivered to an enclave. * * @param evidence - Verified enclave identity evidence. * @param masterSignature - EIP-191 signature over the master-key message. * @param now - Issuance time in Unix seconds. * @returns The authenticated plaintext delivery object. * @throws When the signature is malformed or does not belong to the owner. */ export declare function buildMasterSignatureDelivery(evidence: EnclaveIdentityEvidence, masterSignature: Hex, now?: number): Promise; /** * Encrypts a master-signature delivery in the SDK's ECIES wire format. * * @param delivery - Plaintext delivery object. * @param publicKey - Enclave 65-byte uncompressed public key. * @param ecies - Platform-specific ECIES provider. * @returns The 0x-prefixed serialized ciphertext. * @throws When the public key is malformed or belongs to another enclave. */ export declare function encryptMasterSignatureDelivery(delivery: MasterSignatureDelivery, publicKey: Hex, ecies: ECIESProvider): Promise;