Signing Data Structures the Right Way
Technical deep-dive on the domain separation problem in cryptographic signing and how FOKS's Snowpack IDL solves it.
🔑 Key Insights
- Structural Collision: Different message types can serialize to identical bytes, allowing attackers to forge signatures
- Domain Separators: FOKS embeds random 64-bit separators directly in the IDL (e.g.,
@0x92880d38b74de9fb) - Type System Enforcement: Only structs with domain separators can be signed—compiler prevents errors
- Domain separator not included in serialization (saves bytes)—both parties know it via shared protocol spec
The Problem
Two different message types can have identical field layouts:
message TreeRoot { int64 timestamp = 1; bytes hash = 2; }
message KeyRevoke { int64 timestamp = 1; bytes hash = 2; }
An attacker could take a signed TreeRoot and forge a KeyRevoke with the same bytes, tricking verifiers.
Real-world attacks have succeeded in:
- Bitcoin (transaction malleability)
- Ethereum DEXs
- TLS
- JWTs
- AWS
The Solution: Snowpack IDL
FOKS's Snowpack IDL puts domain separators directly in the protocol spec:
struct TreeRoot @0x92880d38b74de9fb {
timestamp @0 : Uint;
hash @1 : Blob;
}
Signing concatenates the domain separator with the serialized object. Verification fails if types don't match.
Additional Features
- Canonical Encoding: Minimum-size integer encoding, no multi-key dictionaries
- Forward/Backward Compatibility: Old decoders can read new formats (missing fields = 0)
- AI-resistant: Compiler ensures all separators are unique within a project
Explored: 2026-04-02 | Rating: 4/5