Summary
Add support for cryptographically signing chat messages using Schnorr signatures (secp256k1), aligned with the live SolidOS solid-ui implementation.
Reference Implementation (Live in SolidOS)
SolidOS solid-ui already implements this:
How It Works (Live Implementation)
Signing a Message (chatLogic.js)
import{signMsg,SEC}from'./signature'import{getPrivateKey}from'./keys'// When sending a message:constprivateKey=awaitgetPrivateKey(me)constsig=signMsg(msg,privateKey)sts.push($rdf.st(message,$rdf.sym(`${SEC}proofValue`),$rdf.lit(sig),chatDocument))Verifying a Message (message.js)
import{verifySignature,SEC}from'./signature'import{getPublicKey}from'./keys'// When rendering a message:constsignature=store.any(msgId,$rdf.sym(`${SEC}proofValue`))if(!signature?.value){unsignedMessage=truedebug.warn(msgId.uri+' is unsigned')}else{getPublicKey(creator).then(publicKey=>{if(!verifySignature(signature?.value,msg,publicKey)){debug.warn('invalid signature')}})}// UI: unsigned messages get red backgroundif(unsignedMessage)messageRow.setAttribute('style','background-color: red')RDF Storage
@prefix sec: <https://w3id.org/security#> .
# Signature stored directly on message<#msg-1234567890>a wf:Message ;
sioc:content "Hello, world!" ;
dct:created "2026-01-11T12:00:00Z" ;
foaf:maker <https://melvincarvalho.com/#me> ;
sec:proofValue "e3b0c44298fc1c149afbf4c8996fb924..." . # Schnorr signature hex
Message Object for Signing
constmsg={id: msgId.uri,// Message URIcreated: '2026-01-11T12:00:00Z',// dct:createdcontent: 'Hello, world!',// sioc:content maker: 'https://melvincarvalho.com/#me'// foaf:maker}// Sign: JSON.stringify(msg) → SHA-256 → Schnorr signconstsig=signMsg(msg,privateKey)// Returns hex stringKey Storage in Pod
# Public key (world-readable)<#me> solid:publicKey "a1b2c3d4..." . # 64 char hex# Private key (owner-only ACL)<#me> solid:privateKey "f1e2d3c4..." . # 64 char hex
Cryptography
- Algorithm: Schnorr signatures on secp256k1 curve
- Library:
@noble/curves/secp256k1 + @noble/hashes/sha256 - Process:
- Serialize message to JSON
- SHA-256 hash the JSON
- Schnorr sign the hash
- Store as
sec:proofValue hex string
Security Considerations
Risks of Storing Private Keys in Pods
| Risk | Description | Severity |
|---|
| Server admin access | Pod operators could read private keys | Medium |
| ACL misconfiguration | Wrong permissions could expose keys | High |
| No encryption at rest | Keys stored as plaintext | Medium |
| Pod compromise | Hacked pod = compromised keys | High |
Mitigations
- ACL restricts private key to owner-only
- Dedicated
/settings/keys/ container with strict ACL - Key rotation support if compromised
Browser Extensions for Enhanced Security
For users who don't want private keys in their pod:
- Podkey - Browser extension for Solid key management
- Keeps private keys in browser extension storage
- Signs messages without exposing keys to pod server
- Intercepts signing requests from Solid apps
Implementation Tasks for solid-chat/app
Dependencies
{
"@noble/curves": "^1.2.0",
"@noble/hashes": "^1.3.0"
}References
Summary
Add support for cryptographically signing chat messages using Schnorr signatures (secp256k1), aligned with the live SolidOS solid-ui implementation.
Reference Implementation (Live in SolidOS)
SolidOS solid-ui already implements this:
src/chat/signature.ts- sign/verify functionssrc/chat/keys.ts- key managementsrc/chat/chatLogic.js- signing on sendsrc/chat/message.js- verification on renderHow It Works (Live Implementation)
Signing a Message (chatLogic.js)
Verifying a Message (message.js)
RDF Storage
Message Object for Signing
Key Storage in Pod
Cryptography
@noble/curves/secp256k1+@noble/hashes/sha256sec:proofValuehex stringSecurity Considerations
Risks of Storing Private Keys in Pods
Mitigations
/settings/keys/container with strict ACLBrowser Extensions for Enhanced Security
For users who don't want private keys in their pod:
Implementation Tasks for solid-chat/app
@noble/curvesand@noble/hashesdependencieskeys.tssignature.tssec:proofValuetriple when sending messagesDependencies
{ "@noble/curves": "^1.2.0", "@noble/hashes": "^1.3.0" }References