@freehold-earth/identity
v0.3.0
Published
W3C DID implementation (did:key, ephemeral DIDs) for Freehold identity management
Maintainers
Readme
@freehold-earth/identity
W3C DID implementation (did:key, ephemeral DIDs) for Freehold identity management.
Overview
This package provides Decentralized Identifier (DID) functionality for the Freehold ecosystem, implementing the W3C did:key method with Ed25519 keys.
Key concepts:
- Root DID: Persistent user identity, stored encrypted in context store
- Ephemeral DID: Generated per-verification, unlinkable to root or other ephemeral DIDs
Installation
pnpm add @freehold-earth/identityUsage
Generate a Root DID
import { generateDID, serializeDIDKeyPair } from '@freehold-earth/identity';
const rootIdentity = await generateDID();
console.log(rootIdentity.did);
// did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
// Store encrypted in context store
const serialized = serializeDIDKeyPair(rootIdentity);Generate Ephemeral DIDs
import { generateEphemeralDID } from '@freehold-earth/identity';
// Each ephemeral DID is completely unlinkable
const ephemeral = await generateEphemeralDID();Sign and Verify
import { signWithDID, verifyDIDSignature } from '@freehold-earth/identity';
const message = new TextEncoder().encode('Verification request');
const signature = await signWithDID(keyPair.privateKey, message);
const isValid = await verifyDIDSignature(
keyPair.publicKey,
message,
signature
);Validate DIDs
import { isValidDIDKey, didToPublicKey } from '@freehold-earth/identity';
if (isValidDIDKey(did)) {
const publicKey = didToPublicKey(did);
}DID Format
Using W3C did:key method:
did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK
│ └─ base58-btc encoded (multicodec + public key)
└─ 'z' prefix indicates base58-btc encodingAPI
Types
DIDKeyPair- Containsdid,publicKey, andprivateKeySerializedDIDKeyPair- JSON-serializable format for storage
Functions
generateDID()- Generate a new did:keygenerateEphemeralDID()- Generate an unlinkable ephemeral DIDpublicKeyToDID(publicKey)- Convert public key to DIDdidToPublicKey(did)- Extract public key from DIDsignWithDID(privateKey, message)- Sign dataverifyDIDSignature(publicKey, message, signature)- Verify signatureisValidDIDKey(did)- Check DID validityserializeDIDKeyPair(keyPair)- Serialize for storagedeserializeDIDKeyPair(serialized)- Deserialize from storagetruncateDID(did)- Truncate for displayauthorizationPreimage(record)- Canonical bytes a root DID signs for an authorization recordencodePreimage(fields)- Canonical preimage encoding of any registered structurecanonicalJson(value)- RFC 8785 canonical JSON, used for record metadata
Signed form of authorization records
An authorization record is signed over the spal/did-authorization/v1
structure from the preimage encoding spec:
a registered domain separator followed by every field with a length prefix, so
moving a boundary between two DIDs can never produce a second record that the
same signature verifies. Any implementation can rebuild the preimage from the
record's fields; the package is tested byte-for-byte against the spec's vectors.
Development
pnpm install
pnpm test # Run tests
pnpm build # Build package
pnpm lint # Type checkRelated Packages
- spec - S-PAL schema and protocols
- context-store - Layer 1: Context Store
- freehold-agent - Layer 2: Personal Agent
- contracts - Layer 3: Smart Contracts
- zkp - Layer 4: Zero-Knowledge Proofs
Future
The planned anchoring path is did:midnight via Midnight Passport (ADR-008); did:prism is supported in design as an alternative. All are W3C compliant and interoperable.
License
Apache-2.0
