Skip to main content

Session Signer

The Session Signer is a server-side Ed25519 keypair that signs every inference receipt, providing cryptographic proof that the response was generated through Lucid’s infrastructure.

How It Works

Client Request → TrustGate → LLM Provider → Response

              Generate Receipt

              Sign with Ed25519

          Return response + receipt_id
  1. When an inference completes, Lucid generates a receipt containing hashes of the input and output
  2. The session signer creates an Ed25519 signature over: receipt_id || input_hash || output_hash || timestamp
  3. The signature is stored alongside the receipt
  4. Anyone can verify the signature using the signer’s public key

Get the Public Key

The signer’s public key is always available via the API:
const { publicKey } = await lucid.signer.pubkey();
console.log("Public key:", publicKey); // hex-encoded Ed25519 public key
curl https://api.lucid.foundation/v1/signer/pubkey \
  -H "Authorization: Bearer $LUCID_API_KEY"

Verify a Signature

TypeScript

import { verify } from "@noble/ed25519";

const receipt = await lucid.receipts.get(receiptId);
const { publicKey } = await lucid.signer.pubkey();

const message = Buffer.concat([
  Buffer.from(receipt.id),
  Buffer.from(receipt.inputHash),
  Buffer.from(receipt.outputHash),
  Buffer.from(receipt.timestamp),
]);

const valid = await verify(
  Buffer.from(receipt.signature, "hex"),
  message,
  Buffer.from(publicKey, "hex")
);

console.log("Signature valid:", valid);

Python

from nacl.signing import VerifyKey

verify_key = VerifyKey(bytes.fromhex(public_key))
message = (receipt_id + input_hash + output_hash + timestamp).encode()
signature = bytes.fromhex(receipt_signature)

try:
    verify_key.verify(message, signature)
    print("Valid")
except:
    print("Invalid")

Security Model

PropertyDescription
AlgorithmEd25519 (EdDSA over Curve25519)
Key storageServer-side only, never exposed to clients
Key rotationSupported — old signatures remain valid with the old key
Public key accessAlways available via /v1/signer/pubkey
Signature scopeCovers receipt ID, input hash, output hash, and timestamp

Why Ed25519?

  • Fast verification (important for batch receipt checking)
  • Small signatures (64 bytes)
  • Deterministic — same input always produces the same signature
  • Widely supported across languages and blockchains (including Solana)

Relationship to Epochs

Individual receipt signatures prove authenticity. Epochs batch multiple receipts into a Merkle Mountain Range and anchor the root hash on Solana, providing blockchain-level immutability on top of the cryptographic signatures.