Why Signatures Matter
Every piece of content in Seed Hypermedia is cryptographically signed. This is the foundation of the entire trust model — you can verify that content was created by the claimed author without trusting any intermediary.
Unlike the traditional web where trust depends on TLS certificates and domain registrars, SHM trust is intrinsic to the content itself. A signed document remains verifiable even if the server hosting it is compromised.
Key Pairs
SHM uses Ed25519 key pairs derived from BIP-39 mnemonics via a specific derivation path:
Derivation path: m/44'/104109'/0'
where 104109 = 'hm' in ASCIIThe public key becomes your account identifier, encoded as a did:key (e.g., z6Mk...). This identifier is permanent and globally unique — it's derived directly from your cryptographic key.
Generating Keys
Via the daemon gRPC API:
# Generate a mnemonic
grpcurl -plaintext -d '{}' localhost:55002 \
com.seed.daemon.v1alpha.Daemon/GenMnemonic
# Register a key from mnemonic
grpcurl -plaintext -d '{
"name": "mykey",
"mnemonic": ["word1", "word2", ...]
}' localhost:55002 com.seed.daemon.v1alpha.Daemon/RegisterKeyVia the desktop app: Settings → Keys → Create New Key. The app handles mnemonic generation and storage.
Key Storage
By default, keys are stored in the operating system's keyring (macOS Keychain, GNOME Keyring, Windows Credential Manager). For headless servers, a file-based keystore can be used by setting the SEED_FILE_KEYSTORE=1 environment variable.
Back up your mnemonic phrase! If you lose your keys and mnemonic, you permanently lose the ability to update your documents. There is no password reset or key recovery service.
Blob Signing
Content in SHM is stored as CBOR-encoded blobs. Each blob is signed using this process:
1. Create the blob with a zeroed-out signature field (64 zero bytes)
2. CBOR-encode the blob with zero signature
3. Sign the CBOR bytes with Ed25519
4. Replace the zero bytes with the actual signature
5. CBOR-encode the final blob with real signature
// Pseudocode for blob signing
const blob = createBlob(changes, signerPublicKey, zeroSignature);
const cborBytes = cborEncode(blob);
const signature = ed25519Sign(privateKey, cborBytes);
blob.signature = signature;
const finalCbor = cborEncode(blob);This sign-then-replace pattern ensures the signature covers all fields of the blob including its own position. The CID (Content Identifier) is computed from the final CBOR bytes.
Verification
Anyone can verify a blob's authenticity:
1. Extract the signature from the blob
2. Replace the signature with 64 zero bytes
3. CBOR-encode the modified blob
4. Verify the signature against the signer's public key and CBOR bytes
This verification happens automatically when the daemon receives blobs from peers. Invalid signatures are rejected.
Delegation and Access Control
Key owners can grant write access to other keys using the AccessControl API:
# Grant WRITER role to another account
grpcurl -plaintext -d '{
"signing_key_name": "mykey",
"delegate": "z6MkOTHER...",
"account": "z6MkMYACCOUNT...",
"path": "/",
"role": "WRITER"
}' localhost:55002 \
com.seed.documents.v3alpha.AccessControl/CreateCapabilityRoles available:
• WRITER — Can create and edit documents under the specified path
• EDITOR — Can edit existing documents but not create new paths
Delegation is itself a signed operation, creating a verifiable chain of trust from the account owner to the delegate.
Security Considerations
• Keep your private keys secure — anyone with your private key can publish as you
• Back up your mnemonic — store it offline in a safe place
• Key rotation is not yet supported — plan for long-term key management
• Revocation is limited — you can delete delegations but can't retroactively invalidate signed content
• Content is permanent — once signed and distributed, content can't be fully erased from the network