---
title: "Signing & Trust Blocks"
description: "API reference for content signing, trust block embedding, and verification."
published: 2026-02-18T18:06:46.269612+00:00
updated: 2026-02-18T18:06:46.269612+00:00
tags: ["api", "signing", "verification", "trust"]
url: https://xiobjects.com/docs/xio/api/signing
source: XI Objects
---

<!-- xion:doctype xion+markdown -->
<!-- xion:metadata
{
  "version": "1.0",
  "content_type": "application/xion\u002Bmarkdown",
  "source_type": "xi-content/doc",
  "generator": "xio-content-publisher/1.0.0",
  "generated": "2026-02-18T18:04:33.6182310\u002B00:00",
  "encoding": "utf-8",
  "render_intent": "markdown",
  "title": "Signing \u0026 Trust Blocks",
  "slug": "xio/api/signing",
  "copyright": "\u00A9 2026 XI Objects Inc"
}
-->

# Signing & Trust Blocks

## Overview

Content signing in XI Objects works by embedding a **trust block** directly into documents. The trust block contains an Ed25519 signature, BLAKE3 content hash, and the signer's X.509 certificate chain, making the signed artifact self-contained and independently verifiable.

Signing is performed by the **Xio.Trust** library.

## Trust Block Format

When content is signed, a JSON trust header is computed and embedded. The trust header has the following structure:

```json
{
  "v": 1,
  "canon_v": 1,
  "ctx": "signing-context-identifier",
  "hash_blake3_hex": "a1b2c3d4e5f6...",
  "hash_sha256_hex": "f6e5d4c3b2a1...",
  "sig_alg": "ed25519",
  "sig_b64": "<base64url Ed25519 signature>",
  "pubkey_b64": "<base64url 32-byte Ed25519 public key>",
  "x509_chain_pem": [
    "<leaf certificate PEM>",
    "<intermediate certificate PEM>"
  ],
  "key_id": "<base64url(BLAKE3-256(raw pubkey))>",
  "created_at": "2026-02-17T12:00:00Z"
}
```

### Trust Header Fields

| Field | Type | Description |
|-------|------|-------------|
| `v` | `int` | Trust block version (currently `1`) |
| `canon_v` | `int` | Canonicalization version (currently `1`) |
| `ctx` | `string` | Context string identifying the signing purpose |
| `hash_blake3_hex` | `string` | BLAKE3-256 hex digest of canonicalized content |
| `hash_sha256_hex` | `string?` | Optional SHA-256 hex digest for interop |
| `sig_alg` | `string` | Signature algorithm (`"ed25519"`) |
| `sig_b64` | `string` | Base64url-encoded Ed25519 signature |
| `pubkey_b64` | `string` | Base64url-encoded 32-byte Ed25519 public key |
| `x509_chain_pem` | `string[]` | X.509 certificate chain (PEM, leaf-first) |
| `key_id` | `string` | BLAKE3-256 hash of the raw public key (base64url) |
| `created_at` | `string` | ISO 8601 timestamp of signing |

## Signing Flow

The signing process follows a deterministic pipeline:

```mermaid
flowchart TD
    A[Input Document] --> B[Strip Existing Trust Block]
    B --> C[Canonicalize Content]
    C --> D["Compute Hash: BLAKE3-256(ctx || canonical_bytes)"]
    D --> E[Ed25519 Sign Canonical Bytes]
    E --> F[Build Trust Header JSON]
    F --> G[Embed Trust Block in Document]
    G --> H[Signed Document]
    
    style A fill:#1a1a2e,stroke:#7a4a9e,color:#e1d5b9
    style D fill:#582c7e,stroke:#7a4a9e,color:#fff
    style E fill:#582c7e,stroke:#7a4a9e,color:#fff
    style H fill:#0a0e1a,stroke:#ff3a00,color:#e1d5b9
```

1. **Strip**: Remove any existing trust block from the document
2. **Canonicalize**: Normalize the document text (BOM handling, newline normalization)
3. **Hash**: Compute BLAKE3-256 over `[context || canonical_bytes]`
4. **Sign**: Ed25519 sign the canonical bytes using the signer's private key (via delegate)
5. **Build**: Assemble the trust header JSON with hash, signature, public key, and certificate chain
6. **Embed**: Insert the trust block back into the document

### Signing Options

The `TrustOptions` model configures a signing operation:

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `PublicKey` | `byte[32]` | Yes | Ed25519 public key (raw 32 bytes) |
| `Signer` | Signing delegate | Yes | Async delegate that signs data with the private key |
| `Context` | `string` | Yes | Context string for domain separation |
| `X509ChainPem` | `string[]?` | No | PEM certificate chain (leaf-first) |
| `KeyId` | `string?` | No | Precomputed key ID (auto-derived from public key if omitted) |
| `HashAlgorithm` | `HashAlgorithm` | No | `Blake3_256` (default) or `Sha256` |

> **Note:** The private key is never passed directly. Instead, an async signing delegate is provided, allowing the private key to be held in a secure backend (file, Key Vault, HSM) without exposing it to the trust library.

## Verification

Verification checks the full trust chain of a signed document.

### Verification Steps

1. **Extract trust block**: Parse the trust header JSON from the document
2. **Canonicalize**: Rebuild the canonical form (strip trust block, normalize)
3. **Hash check**: Recompute BLAKE3-256 hash and compare to `hash_blake3_hex`
4. **Signature check**: Verify the Ed25519 signature against the embedded public key
5. **Certificate chain**: Validate the X.509 chain from leaf → intermediate → Institute of Provenance Root CA
6. **Revocation check**: Verify no certificate in the chain has been revoked (via Sparse Merkle proofs from Orbital)
7. **Temporal check**: Confirm the leaf certificate was valid at `created_at`

### Wire Protocol Verification

For content registered on the Orbital network, verification data is carried as `XSIGN` records (type 65003) in the wire protocol. The client can resolve signing metadata for a `.xio` domain:

```
Query: example.xio / XSIGN
→ Returns signing metadata (certificate chain, signatures, attribution)
```

The Sparse Merkle proof in the Additional section provides cryptographic proof that the record and certificate state are authentic.

## Cryptographic Details

### Ed25519

- **Key size:** 32-byte private key, 32-byte public key
- **Signature size:** 64 bytes
- **Deterministic:** Same input always produces the same signature (no random nonce)

### BLAKE3

- **Hash size:** 256 bits (32 bytes)
- **Context binding:** Hash is computed over `[context_string || content_bytes]` for domain separation
- **Performance:** Multi-threaded, SIMD-optimized; significantly faster than SHA-256

### SHA-256 (Optional)

- Available as an optional secondary hash in the trust header for interoperability
- Not used for signature computation; included in the trust header metadata only

## XSIGN Record

The signing metadata record in the wire protocol carries certificate chain, signature, and attribution data associated with a `.xio` domain name.

## Error Conditions

| Condition | Description |
|-----------|-------------|
| Hash mismatch | Content has been modified since signing; BLAKE3 hash does not match |
| Signature invalid | Ed25519 signature verification failed; content or signature corrupted |
| Chain broken | Certificate chain cannot be traced to the Institute of Provenance Root CA |
| Certificate revoked | A certificate in the chain has been revoked (verified via SMT proof) |
| Certificate expired | The leaf certificate was not valid at the time of signing |
| Trust block malformed | Trust header JSON cannot be parsed or is missing required fields |
<!-- xion:trust
{
  "v": 1,
  "canon_v": 1,
  "ctx": "xiobjects.com/content",
  "hash_blake3_hex": "949929080008fa1f11a3fafb65190f0861cc7d76b4dfbd29805b2e96fbcd30ac",
  "hash_sha256_hex": null,
  "sig_alg": "ed25519",
  "sig_b64": "FwxAWlkBCCNscWDDNmgbhxpiSGnI0FTQzH1zd622u32jCxq83LZKpmux-H5sR2GBKu8Wobt4szqVvTqYVjLSCg",
  "pubkey_b64": "ff4Npz7sRQH_vUn9FY8Wrc8v_00Z49h15EyQgKVTHR0",
  "x509_chain_pem": [
    "-----BEGIN CERTIFICATE-----\r\nMIIB9TCCAaegAwIBAgIRAM4lRb8aI/FYHOJD5OYqefQwBQYDK2VwMC4xLDAqBgNV\r\nBAMMI1hJIE9iamVjdHMgSW5jIENvbnRyb2wgSW50ZXJtZWRpYXRlMB4XDTI2MDIx\r\nNTIyMDg0OFoXDTI2MDMxNzIyMDg0OFowSzEeMBwGA1UEAwwVeGlvLWNvbnRlbnQt\r\ncHVibGlzaGVyMRcwFQYDVQQKDA5YSSBPYmplY3RzIEluYzEQMA4GA1UECwwHQ29u\r\ndGVudDAqMAUGAytlcAMhAH3\u002BDac\u002B7EUB/71J/RWPFq3PL/9NGePYdeRMkIClUx0d\r\no4G8MIG5MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG\r\nCCsGAQUFBwMkMGUGA1UdIwReMFyAFDspt5hZsP6rNX4Cq7owpMYa05OyoS6kLDAq\r\nMSgwJgYDVQQDDB9JbnN0aXR1dGUgb2YgUHJvdmVuYW5jZSBSb290IENBghRSYDf4\r\nsUJ\u002B9h\u002Bod0\u002BZRK/X/JSUBTAdBgNVHQ4EFgQUP5BTxnjCAxVKgMvFhx40ljlGOAkw\r\nBQYDK2VwA0EAjKlSBzHgXpPM2PA\u002BSJ/rMso5OEqtWIHGo/zr2QSuZRXhSWafIbk9\r\nZnl0kKZCqUB2HpCfgnpOGCPK6SlefwQsAQ==\r\n-----END CERTIFICATE-----\r\n",
    "-----BEGIN CERTIFICATE-----\r\nMIIByDCCAXqgAwIBAgIUUmA3\u002BLFCfvYfqHdPmUSv1/yUlAUwBQYDK2VwMCoxKDAm\r\nBgNVBAMMH0luc3RpdHV0ZSBvZiBQcm92ZW5hbmNlIFJvb3QgQ0EwHhcNMjUxMTAy\r\nMDMxNzEyWhcNMzAxMTAxMDMxNzEyWjAuMSwwKgYDVQQDDCNYSSBPYmplY3RzIElu\r\nYyBDb250cm9sIEludGVybWVkaWF0ZTAqMAUGAytlcAMhAFSS/pggSRmTcAMko7uc\r\nATH8OHgxVymd5mBFlPXbJkgio4GtMIGqMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD\r\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQ7KbeYWbD\u002BqzV\u002BAqu6MKTGGtOTsjBlBgNV\r\nHSMEXjBcgBQAZRTDswSVORu\u002BkUOKX6WvrOvmQKEupCwwKjEoMCYGA1UEAwwfSW5z\r\ndGl0dXRlIG9mIFByb3ZlbmFuY2UgUm9vdCBDQYIUJqoJlpiSFg\u002B7W5IJLMrLttgR\r\nQp4wBQYDK2VwA0EA5FOht7YOsVRPp/FOKMQ\u002B3Mo9JxrvGR3ylKWAWNm6OUV7N3DB\r\nI9cD62wU5I0d0EKDBy0CX9DnoqUyxv5yguraAA==\r\n-----END CERTIFICATE-----\r\n",
    "-----BEGIN CERTIFICATE-----\r\nMIIBaTCCARugAwIBAgIUJqoJlpiSFg\u002B7W5IJLMrLttgRQp4wBQYDK2VwMCoxKDAm\r\nBgNVBAMMH0luc3RpdHV0ZSBvZiBQcm92ZW5hbmNlIFJvb3QgQ0EwHhcNMjUxMTAy\r\nMDMwNTEyWhcNMzUxMDMxMDMwNTEyWjAqMSgwJgYDVQQDDB9JbnN0aXR1dGUgb2Yg\r\nUHJvdmVuYW5jZSBSb290IENBMCowBQYDK2VwAyEAEWNZl\u002Br3IC7\u002BgBh90Yo1kWk1\r\npZCVzVuFdFT7qBBU8W2jUzBRMB0GA1UdDgQWBBQAZRTDswSVORu\u002BkUOKX6WvrOvm\r\nQDAfBgNVHSMEGDAWgBQAZRTDswSVORu\u002BkUOKX6WvrOvmQDAPBgNVHRMBAf8EBTAD\r\nAQH/MAUGAytlcANBAO6QeydOFNrN75qNyftggYudsxMyl4w9qWkSdZ6hlhrRcbSr\r\niG9Si0kbrIJOwYB/LTBU0RM4Rl\u002Bo9PM3Qp0mPwo=\r\n-----END CERTIFICATE-----\r\n"
  ],
  "key_id": "-GCB4sEBzFethc5Pd0Rzyn_6ySyHB4QaqD9DAoW9ViE",
  "created_at": "2026-02-18T18:04:33Z"
}
-->