Skip to content

Tenor supports cryptographic signing of interchange bundles and WASM evaluator binaries. Signing establishes a chain of trust: the contract author signs the bundle, and the runtime verifies the signature before evaluation.

Ed25519 Signing

Tenor uses Ed25519 for all cryptographic signatures. Ed25519 is fast, deterministic, and widely supported.

Generate a Keypair

Generate a new Ed25519 keypair:

bash
tenor keygen

This produces two files:

  • tenor-secret.key — the private signing key (keep this secret)
  • tenor-public.key — the public verification key (distribute this)

You can specify output paths:

bash
tenor keygen --secret-key ./keys/signing.key --public-key ./keys/verify.key

Sign a Bundle

Sign an elaborated interchange bundle:

bash
tenor sign contract.json --key tenor-secret.key

This produces a signed bundle (contract.signed.json) that includes the original interchange JSON plus a detached Ed25519 signature. The signature covers the entire interchange content — any modification invalidates it.

Verify a Bundle

Verify a signed bundle:

bash
tenor verify contract.signed.json

The verify command checks:

  1. The signature is valid Ed25519 over the interchange content
  2. The interchange JSON passes schema validation
  3. The bundle has not been modified since signing

If verification fails, the command exits with a non-zero code and prints the failure reason.

WASM Evaluator Signing

The Tenor evaluator can run as a WASM module (in browsers, edge runtimes, or sandboxed environments). WASM binaries can also be signed to establish that the evaluator itself is authentic:

bash
tenor sign-wasm evaluator.wasm --key tenor-secret.key --bundle-etag ETAG

The --bundle-etag parameter binds the WASM signature to a specific interchange bundle version. This ensures the evaluator binary and the contract it's evaluating are a matched pair.

Verify a signed WASM binary:

bash
tenor verify-wasm evaluator.wasm --sig evaluator.wasm.sig --pubkey tenor-public.key

Trust Obligations

The Tenor specification defines three trust obligations (E18-E20) for runtime implementations:

E18: Bundle Integrity

The runtime must verify that the interchange bundle has not been modified since elaboration. If a signature is present, it must be verified. If no signature is present, the runtime must indicate that the bundle is unsigned.

E19: Evaluator Authenticity

When using a WASM evaluator, the runtime must verify the WASM signature against a known public key. This prevents substitution of a modified evaluator that might produce incorrect verdicts or action spaces.

E20: Provenance Chain

Every verdict and every state transition must record sufficient metadata to reconstruct the decision chain. The provenance record must be cryptographically bound to the bundle that produced it — proving that this specific contract version, evaluated against these specific facts, produced this specific outcome.

Key Management Best Practices

  • Store secret keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.). Never commit secret keys to version control.
  • Rotate keys regularly. Generate new keypairs on a schedule. Old signatures remain valid — they were signed with the key that was current at the time.
  • Use different keys for different environments. Production, staging, and development should have separate keypairs.
  • Include the public key in your TenorManifest. This allows automated verification without out-of-band key exchange.