SDIS: Secure Distributed Identity System
Design snapshot: this document mixes implemented flows and planned endpoint models. For currently wired gateway routes, use
icn/crates/icn-gateway/src/api/sdis/mod.rs.
Overview
SDIS is ICN's multi-device identity management and recovery system. It allows users to:
- Enroll new devices securely
- Manage trusted recovery anchors
- Recover identities after device loss
- Maintain cryptographic proof chains
- Delegate recovery authority to trusted contacts
Architecture
Components
- Enrollment System: Secure device onboarding with challenge-response
- Anchor Management: Trusted device/contact registration for recovery
- Proof System: Cryptographic verification of identity claims
- Recovery Mechanism: Multi-anchor identity restoration
Data Model
Enrollment Record
struct EnrollmentRecord {
enrollment_id: String, // Unique enrollment identifier
root_did: String, // Primary identity DID
device_did: String, // New device DID
device_label: String, // Human-readable device name
device_pubkey: Vec<u8>, // Ed25519 public key
challenge: Vec<u8>, // Enrollment challenge
challenge_expires_at: u64, // Challenge expiration timestamp
approved: bool, // Enrollment approval status
approved_at: Option<u64>, // Approval timestamp
created_at: u64, // Creation timestamp
}
Recovery Anchor
struct RecoveryAnchor {
anchor_id: String, // Unique anchor identifier
owner_did: String, // Identity owning this anchor
anchor_type: AnchorType, // Device or Contact
label: String, // Human-readable label
pubkey: Vec<u8>, // Ed25519 public key
contact_did: Option<String>, // DID if contact anchor
created_at: u64, // Creation timestamp
revoked_at: Option<u64>, // Revocation timestamp
}
enum AnchorType {
Device, // User's own device
Contact, // Trusted contact's device
}
Proof Chain
struct ProofRecord {
proof_id: String, // Unique proof identifier
claim_type: ClaimType, // Type of claim being proven
subject_did: String, // DID making the claim
issuer_did: String, // DID verifying the claim
signature: Vec<u8>, // Ed25519 signature
created_at: u64, // Creation timestamp
expires_at: Option<u64>, // Optional expiration
}
enum ClaimType {
DeviceOwnership, // Claim: "I own this device"
DeviceEnrollment, // Claim: "This device is enrolled"
RecoveryCapability, // Claim: "I can recover this identity"
IdentityBinding, // Claim: "These DIDs belong together"
}
Enrollment Flow
Route note: some endpoint examples in this design section use legacy naming. For currently wired route shapes, see
docs/sdis/SDIS_API_GUIDE.mdanddocs/sdis/SDIS_STATUS.md.
1. Initiate Enrollment (New Device)
The new device generates a keypair and requests enrollment:
POST /v1/sdis/enroll
{
"root_did": "did:icn:z6Mk...",
"device_did": "did:icn:z6Mk...",
"device_label": "My Laptop",
"device_pubkey": "base64_encoded_public_key"
}
Response:
{
"enrollment_id": "enr_abc123",
"challenge": "base64_encoded_challenge",
"expires_at": 1704067200
}
2. Approve Enrollment (Existing Device)
User approves on an already-enrolled device:
POST /v1/sdis/enroll/{enrollment_id}/approve
{
"signature": "base64_ed25519_signature"
}
Response:
{
"status": "approved",
"proof_id": "proof_xyz789"
}
3. Complete Enrollment (New Device)
New device verifies and saves the approval:
GET /v1/sdis/enroll/{enrollment_id}
Response:
{
"enrollment_id": "enr_abc123",
"root_did": "did:icn:z6Mk...",
"device_did": "did:icn:z6Mk...",
"approved": true,
"approved_at": 1704063600
}
Anchor Management
Add Recovery Anchor
POST /v1/sdis/anchors
{
"anchor_type": "device", // or "contact"
"label": "My Phone",
"pubkey": "base64_encoded_key",
"contact_did": "did:icn:z6Mk..." // optional, for contact anchors
}
Response:
{
"anchor_id": "anc_def456",
"created_at": 1704063600
}
List Anchors
GET /v1/sdis/anchors
Response:
{
"anchors": [
{
"anchor_id": "anc_def456",
"owner_did": "did:icn:z6Mk...",
"anchor_type": "device",
"label": "My Phone",
"pubkey": "...",
"created_at": 1704063600,
"revoked_at": null
}
]
}
Revoke Anchor
POST /v1/sdis/anchors/{anchor_id}/revoke
Response:
{
"status": "revoked",
"revoked_at": 1704067200
}
Recovery Process
1. Initiate Recovery
Lost device or new device initiates recovery:
POST /v1/sdis/recover/initiate
{
"root_did": "did:icn:z6Mk...",
"new_device_did": "did:icn:z6Mk...",
"new_device_pubkey": "...",
"anchor_pubkeys": ["...", "..."] // Public keys of recovery anchors
}
Response:
{
"recovery_id": "rec_ghi789",
"required_approvals": 2, // Threshold (e.g., 2 of 3)
"pending_approvals": []
}
2. Approve Recovery (Anchor Devices)
Each recovery anchor approves:
POST /v1/sdis/recover/{recovery_id}/approve
{
"anchor_id": "anc_def456",
"signature": "base64_signature" // Sign recovery_id + new_device_did
}
Response:
{
"approvals": 1,
"required": 2,
"status": "pending" // or "approved" when threshold met
}
3. Complete Recovery
Once threshold is met, new device completes recovery:
GET /v1/sdis/recover/{recovery_id}
Response:
{
"recovery_id": "rec_ghi789",
"status": "approved",
"new_device_did": "did:icn:z6Mk...",
"approvals": [
{
"anchor_id": "anc_def456",
"approved_at": 1704063600
},
{
"anchor_id": "anc_xyz123",
"approved_at": 1704063700
}
]
}
Security Model
Challenge-Response Protocol
- Server generates random challenge (32 bytes)
- Approving device signs challenge with its private key
- Server verifies signature against stored public key
- Prevents replay attacks with short-lived challenges (5 minutes)
Multi-Anchor Recovery
- Threshold signatures required (e.g., 2 of 3 anchors)
- Prevents single point of failure
- Balances security and usability
- Anchors can be device OR trusted contacts
Proof Chains
Every identity operation creates a cryptographic proof:
- Enrollment proof: Root device → New device
- Recovery proof: Anchor devices → Recovered device
- Anchor registration proof: Root device → Anchor device
Proofs are:
- Signed with Ed25519
- Timestamped
- Immutable once created
- Optionally expirable
Revocation
- Anchors can be revoked at any time
- Revoked anchors cannot approve new recoveries
- Existing approvals from revoked anchors remain valid
- Consider compromised device scenarios
Integration Points
Gateway API
- Enrollment:
/v1/sdis/enrollment/*and steward workflow routes (/v1/sdis/status/*,/v1/sdis/vouch/*,/v1/sdis/reject/*) - Anchors:
/v1/sdis/anchor/* - Recovery:
/v1/sdis/recovery/* - Proofs:
/v1/sdis/ephemeral/*and verification routes (/v1/sdis/verify/*)
Pilot UI
- Enrollment Wizard:
components/enrollment-wizard.js - Identity Viewer:
components/identity-viewer.js - Anchor Manager:
components/anchor-manager.js - Recovery Assistant:
components/recovery-assistant.js(TODO)
Mobile SDK
- iOS/Android: React Native integration via SDK
- Secure Enclave: Hardware-backed key storage
- Biometric Auth: Face ID / Fingerprint for approvals
- QR Code Scanning: For enrollment challenges
Best Practices
For Users
- Register Multiple Anchors: At least 2-3 recovery anchors
- Mix Anchor Types: Combine devices AND trusted contacts
- Label Clearly: Use descriptive names for devices
- Review Regularly: Audit anchor list monthly
- Revoke Promptly: Remove lost/stolen devices immediately
For Developers
- Validate Signatures: Always verify Ed25519 signatures
- Check Expiration: Enforce challenge expiration
- Rate Limit: Prevent enrollment spam
- Audit Log: Record all SDIS operations
- Secure Storage: Encrypt private keys at rest
For Operators
- Monitor Metrics: Track enrollment success rate
- Set Thresholds: Configure anchor approval requirements
- Backup Proofs: Replicate proof chains across nodes
- Alert on Anomalies: Detect unusual recovery patterns
- Provide Support: Help users with recovery failures
Status Snapshot
Phase 1 Complete ✅
- Data models defined
- Enrollment flow implemented
- Anchor management implemented
- Gateway API endpoints
- Pilot UI components (enrollment, anchors)
- Basic security measures
Phase 2 In Progress 🚧
- Recovery flow implementation
- Proof chain verification
- Mobile SDK integration
- QR code enrollment
- Biometric approval
Phase 3 Planned 📋
- Threshold signatures
- Hardware security module support
- Cross-coop recovery
- Social recovery protocols
- Advanced auditing
API Reference
See docs/api/sdis.md for complete API documentation.
Testing
# Run SDIS tests
cd icn
cargo test -p icn-identity sdis
cargo test -p icn-gateway sdis
# Integration tests
cd web/pilot-ui
npm test -- sdis
Troubleshooting
Enrollment Fails
Problem: Challenge expired Solution: Re-initiate enrollment within 5 minutes
Problem: Signature verification failed Solution: Ensure device_pubkey matches signing key
Recovery Fails
Problem: Insufficient approvals Solution: Ensure threshold anchors approve
Problem: Anchor revoked Solution: Use different anchor or re-register
General Issues
- Check node logs:
kubectl logs -n icn <pod-name> - Verify DID format: Must be
did:icn:z6Mk... - Confirm network connectivity between devices
Future Enhancements
- Hardware Tokens: YubiKey, Ledger support
- Social Recovery: N-of-M friend recovery
- Time-Locked Recovery: Delayed recovery for security
- Cross-Network Recovery: Recover across different ICN networks
- Biometric Enrollment: Passwordless onboarding