Cryptographic Specifications

The cryptographic primitives, wire formats, and proof structures that make TRAI evidence court-defensible and machine-verifiable.

Ed25519 + ML-DSA-65 Hybrid Signature

TRAI uses a hybrid signature scheme combining classical Ed25519 with post-quantum ML-DSA-65 (per FIPS 204). This provides both current security and forward protection against quantum computing threats.

Component Standard Implementation
Ed25519 FIPS 186-5 / RFC 8032 ed25519-dalek crate. 32-byte private key, 64-byte signature.
ML-DSA-65 FIPS 204 (final Aug 2024) ml-dsa >= 0.1.0-rc.5. NIST post-quantum standard. 3 Jan-2026 CVEs patched.
Hybrid binding Custom (hybrid-ed25519-mldsa65-jcs-2026) Both signatures are computed over the same content hash. Verification requires both to pass.
Migration path NIST NSM-10 + FIPS 204 Hybrid is current SOTA. PQC-only (drop Ed25519 half) targeted for 2028-01-01 per NIST guidance.

Production requirement: ML-DSA-65 signing requires an external HSM/KMS (AWS KMS or Thales Luna). The dev EphemeralEd25519Signer is NOT for production and only supports Ed25519 without post-quantum hybrid.

COSE_Sign1 Envelope (RFC 9052)

Every TRAI evidence envelope is wrapped in a COSE_Sign1 structure per RFC 9052. This is the canonical wire format for signed evidence.

Structure

COSE_Sign1 = [
    protected: bstr .cbor(          # Protected headers
        1: alg,                       # Algorithm identifier
        "hash": content_hash,         # BLAKE3 hash of content
        "pkfp": primary_key_fingerprint,
        "tsa_token": rfc3161_token,   # Timestamp token (optional)
        "scitt_receipt": receipt      # SCITT receipt (optional)
    ),
    unprotected: empty,               # Empty for TRAI
    payload: bstr,                    # Content being signed
    signature: bstr                   # Ed25519 + ML-DSA-65 hybrid
]

Algorithm identifiers

Algorithm COSE ID Description
EdDSA -8 Ed25519 only (dev mode)
ML-DSA-65 -48 (TBD) Post-quantum only (future)
hybrid-ed25519-mldsa65-jcs-2026 Custom Hybrid Ed25519 + ML-DSA-65 (production)

Wire format

The COSE_Sign1 envelope is serialized as CBOR (Concise Binary Object Representation). The trustlayer envelope JSON (trustlayer.json) carries 18 fields and is stable across v1.x.

# Trustlayer envelope (JSON, ~3 KB)
{
  "schema_version": "1.0",
  "disclosure_type": "ai_generated_text",
  "content_hash": "blake3:...",
  "signer_org_id": "...",
  "timestamp_authority": "Actalis Italia",
  "scitt_inclusion_proof": { ... },
  "chain_position": 42,
  "chain_id": "tenant:org:disclosure_type",
  "created_at": "2026-07-14T12:00:00Z",
  "algorithm": "hybrid-ed25519-mldsa65-jcs-2026",
  ...
}

RFC 3161 Timestamp Format

Every evidence envelope includes an RFC 3161 timestamp token from a Time-Stamp Authority. This proves the content existed at a specific point in time, signed by a trusted third party.

Environment TSA Qualified? Notes
Production Actalis Italia Yes (eIDAS-qualified) EU Long-Term Trust List. 3 fingerprints hardcoded in app/constants.py.
Production (alt) DigiCert / Sectigo Yes (eIDAS-qualified) Alternative qualified TSAs. Buyer provisions own credentials.
Dev/Staging FreeTSA No Clearly labeled. Not suitable for production evidence.

Timestamp token structure

TimeStampToken ::= SEQUENCE {
    status           PKIStatusInfo,
    token            MessageImprint,      # SHA-256 of the COSE_Sign1 protected header
    tstInfo          TSTInfo {            # RFC 3161 TSTInfo
        version              INTEGER (v1),
        policy               OBJECT IDENTIFIER,
        messageImprint       HASH { algo: SHA-256, value: bstr },
        serialNumber         INTEGER,
        genTime              GeneralizedTime,
        accuracy             Accuracy OPTIONAL,
        ordering             BOOLEAN DEFAULT FALSE,
        nonce                INTEGER OPTIONAL,
        tsa                  [0] GeneralName OPTIONAL,
        extensions           [1] Extensions OPTIONAL
    }
}

SCITT Receipt (RFC 9943)

SCITT (Supply Chain Integrity, Transparency and Trust) receipts provide cryptographic proof that a signed statement was registered in a transparency log. TRAI implements RFC 9943 with RFC 9162 Merkle inclusion proofs.

Receipt structure

SCITT_Receipt ::= SEQUENCE {
    log_id          OBJECT IDENTIFIER,     # Transparency log identifier
    inclusion_proof MerkleInclusionProof {
        leaf_hash        HASH,             # BLAKE3(leaf_data)
        log_index        INTEGER,          # Position in the log
        tree_size        INTEGER,          # Total entries at time of proof
        audit_path       SEQUENCE OF HASH, # Merkle audit path
        root_hash        HASH              # Root hash of the Merkle tree
    },
    signature       BIT STRING              # Log operator's signature over the proof
}

RFC 9162 Merkle inclusion proof

The inclusion proof demonstrates that the leaf hash (containing the COSE_Sign1 envelope) was included in the Merkle tree at the claimed position. Verification requires:

  1. Recompute the leaf hash from the signed statement
  2. Walk the audit path from leaf to root using the provided hashes
  3. Compare the computed root hash with the stored root hash
  4. Verify the log operator's signature over the inclusion proof

Not yet live: The SCITT receipt format and Merkle inclusion proofs are implemented and tested (tests/scitt_cross_validation.rs). However, production transparency log anchoring is a roadmap item (Q4 2026). Dev mode uses mock SCITT.

BLAKE3 Hash Chain

Each evidence event is appended to a BLAKE3 hash chain scoped to the tenant's organization ID. This ensures sequential ordering and makes tampering with historical records detectable.

Chain structure

ChainEntry {
    chain_id:       "tenant:{org_id}:{disclosure_type}",
    sequence:       42,                    # Position in chain
    previous_hash:  blake3(entry_41),      # Hash of previous entry
    current_hash:   blake3(current_data),  # Hash of this entry's data
    timestamp:      RFC3161_token,
    org_id:         OrgId,                 # Newtype wrapper
}

Chain verification

# Verify chain integrity
for i in 1..chain.len() {
    assert_eq!(
        chain[i].previous_hash,
        chain[i-1].current_hash,
        "Chain break at position {}", i
    );
}

The chain is scoped per-tenant using the pattern tenant:{org_id}:{disclosure_type}. Each tenant maintains independent chains for different disclosure types.

PDF Certificate Layout

The TRAI PDF certificate is a hand-rolled PDF 1.4 document (implemented in tl-pdf-core, replacing printpdf 0.9.1 to eliminate 9 transitive RUSTSECs).

Layout specification

Section Content Font
Header Certificate title, TRAI mark, generation timestamp Helvetica Bold 14pt
L1 Summary Disclosure type, signer, verification status, chain position Helvetica 10pt
Cryptographic Details Algorithm, key fingerprint, hash value, TSA response details Courier 8pt (monospace)
L2 Raw CWT Base64-encoded COSE_Sign1 protected header Courier 7pt (monospace)
L3 Verification Steps Step-by-step verification instructions Helvetica 9pt
QR Code Embedded QR linking to /v1/verify/{cert_id} Generated via reportlab.graphics.barcode.qr.QrCodeWidget
Footer Hash chain position, previous hash, chain ID Courier 7pt (monospace)

PDF generation pipeline

  1. trai-evidence finalizes the COSE_Sign1 envelope
  2. tl-pdf-core renders the A4 PDF with all sections
  3. QR code is embedded via reportlab
  4. Visible watermark stamp is applied when token_ids are supplied
  5. PDF is persisted to PDF_OUTPUT_DIR and served via /packets/{id}/pdf

Cryptographic specifications are subject to change as standards evolve. The implementations in the source code are the authoritative reference. All claims are independently verifiable against the test suites and source code.