Sigil’s cryptographic surface is intentionally narrow. Every signing operation uses Ed25519. Every hash uses BLAKE3. Threshold signatures use FROST. Canonical serialisation uses JCS (RFC 8785).

Ed25519 signatures

Every transaction is signed with an Ed25519 keypair derived from the signing DID. The signing scheme is ed25519-dalek v2 (Rust), @noble/ed25519 v2 (TypeScript), and crypto/ed25519 (Go). Sigil signs over the canonicalised transaction envelope:
signature = ed25519_sign(
  signing_key,
  blake3("sigil/tx/v1\n" || jcs(tx_envelope))
)
The sigil/tx/v1 domain separator prevents signature reuse across protocols. JCS canonicalisation ensures the byte representation is reproducible regardless of language or library. Key derivation uses HKDF-SHA256 with the parent DID as salt:
child_key = hkdf_expand(
  prk = hkdf_extract(salt = parent_did_bytes, ikm = master_seed),
  info = "sigil/key/" || child_did_bytes,
  len = 32
)
This is the SLIP-0010-compatible derivation used by OAS SDKs. The full spec is in oas/oas/docs/oas/SPECIFICATION.md.

BLAKE3 hashing

BLAKE3 is the only hash function used in consensus. It hashes:
  • Transaction envelopes for signing.
  • Address derivation from DIDs.
  • State root computation.
  • NFT and collection IDs.
  • Storage commitments.
  • Lineage anchor commitments.
Two domain separators are common:
H_addr(did)       = blake3("sigil/addr/v1\n" || canonical(did))[..32]
H_state(root)     = blake3("sigil/state/v1\n" || encode(partitions))
H_tx(envelope)    = blake3("sigil/tx/v1\n"    || jcs(envelope))
BLAKE3 is hardware-accelerated on modern x86_64 and aarch64, which keeps state-root computation off the critical path for block production.

FROST threshold signatures

Multi-human roots (did:oas:sigil:mhr:...) sign under FROST, a t-of-n threshold Ed25519 scheme. The signature is verifiable as a standard Ed25519 signature against the group public key. Verifiers do not need to know which t signers participated. FROST is used for:
  • Multi-human root signing.
  • Recovery ceremonies (guardian thresholds).
  • Foundation and treasury multisigs.
  • Username dispute resolution (3-of-5 multisig).
The FROST implementation lives in aegis/aegis-keys/src/threshold.rs. Distributed Key Generation (DKG) is run off-chain via the Aegis ceremony coordinator; the resulting group public key is registered on-chain via RegisterMhrRoot.

JCS canonical serialisation

Sigil signs and hashes over JCS-canonicalised JSON (RFC 8785). JCS gives deterministic byte representations:
  • Object keys sorted lexicographically.
  • Numbers serialised per ECMAScript Number.prototype.toString.
  • Strings escaped per JSON spec, with UTF-8 normalisation.
  • No insignificant whitespace.
Every Sigil SDK ships a JCS implementation. Cross-language parity is enforced by the Rust WASM crypto module that non-Rust SDKs link against. Reference implementation: node/sigil-core/src/jcs.rs (Rust), oas/oas-sdk-typescript/src/jcs.ts (TypeScript), and the WASM bridge for Go/Python/Swift/Kotlin.

What Sigil does not use

  • No secp256k1. Ed25519 is faster, has better implementations, and is misuse-resistant.
  • No SHA-2 in consensus. BLAKE3 replaces it everywhere in the state machine. SHA-256 appears only inside HKDF and inside OAS-external bridges.
  • No BLS. FROST gives threshold Ed25519 without the BLS pairing dependency.
  • No Keccak. Sigil does not aim for EVM compatibility.
  • No ZK proofs in consensus. Validators verify state transitions directly. Optional ZK rollups remain a v2 research item; see no L0 for v1.