IdentityBundle Refactor Plan
Status: In Progress
Goal: Replace KeyPair with DidKey enum in IdentityBundle to enable hardware-backed signing
Overview
The current IdentityBundle embeds a KeyPair which assumes software-based private key material exists in memory. This blocks hardware backends (HSM/TPM) which never expose private keys.
Changes Required
Phase A1: Update IdentityBundle Core
File: icn-identity/src/bundle.rs
Replace field:
// OLD: did_keypair: KeyPair, // NEW: did_key: DidKey,Update constructors:
generate()- Create software DidKeyfrom_keypair()- Convert KeyPair to software DidKeyfrom_stored()- Reconstruct software DidKey from bytes- Add new:
from_did_key()- Direct construction
Update accessors:
- Keep
did()- unchanged - Update
keypair()- deprecate or return only for software keys - Add
did_key()- return reference to DidKey - Add
sign()- delegate to DidKey or separate signer
- Keep
Update signing:
- Current: Uses
did_keypair.sign() - New: Handle both software and hardware paths
- For software: Sign directly with secret bytes
- For hardware: Require external signer implementation
- Current: Uses
Phase A2: Update Keystore Integration
File: icn-identity/src/keystore.rs
Update load methods to create DidKey instead of KeyPair:
load_v4()line 936:from_stored_with_kem()load_v3()line 1020:from_stored()load_v2()line 1086:from_stored()
Keep backward compatibility:
- Still store secret bytes for software keys
- Don't break existing keystores
Phase A3: Update Downstream Usages
Files to check:
icn-identity/src/keystore_pkcs11.rs- HSM backendicn-identity/src/keystore_tpm.rs- TPM backendicn-gateway/src/auth.rs- Authenticationicn-gateway/src/api/*.rs- API endpointsicn-snapshot/src/*.rs- State snapshots
Common pattern:
// OLD:
bundle.keypair().sign(message)
// NEW - Software:
bundle.sign(message)? // or bundle.did_key().sign_software(message)?
// NEW - Hardware (requires signer):
signer.sign(message)? // where signer implements DidSigner
Phase A4: Testing
Update existing tests:
- All tests in
bundle.rs - Keystore tests
- Gateway integration tests
- All tests in
Add new tests:
- Software DidKey creation
- Hardware DidKey creation (mock)
- Signing with software keys
- Error handling for hardware keys without signer
Migration Path
For Software Keys (Current Default)
No visible change to users. Backend converts KeyPair → DidKey automatically.
For Hardware Keys (Future)
Will require:
- Backend-specific initialization (HSM/TPM)
- External signer implementation
- Explicit "hardware mode" flag
Follow-Up Issues
Issue 1: Add Signing Backend to IdentityBundle
Problem: IdentityBundle needs optional signing backend
Solution: Add Option<Box<dyn DidSigner>> field
Issue 2: PKCS#11 Backend Integration
Problem: PKCS#11 backend needs to create hardware DidKey
Solution: Update init() to return DidKey::Hardware
Issue 3: TPM Backend Integration
Problem: TPM backend needs to create hardware DidKey
Solution: Implement sealing then create DidKey::Hardware
Issue 4: Gateway Authentication with Hardware Keys
Problem: Auth middleware uses bundle.keypair().sign()
Solution: Use bundle.sign() or injected signer
Issue 5: State Snapshot with Hardware Keys
Problem: Snapshots may try to serialize private keys
Solution: Only serialize public keys for hardware mode
Success Criteria
- IdentityBundle uses DidKey instead of KeyPair
- All tests pass
- No breaking changes to software key flow
- Hardware keys are supported (preparation)
- Documentation updated
- Follow-up issues created
Timeline
Estimated: 1-2 commits, ~2-3 hours
Security Considerations
- Backward Compatible: Existing software keystores continue working
- No Dummy Keys: Hardware keys cannot be misused as software keys
- Type Safety: Compiler prevents accessing non-existent secrets
- Zeroization: Software key material remains zeroized on drop
References
- TPM Implementation Plan:
docs/tpm-implementation-plan.md - DidSigner trait:
icn-identity/src/did_signer.rs - Current KeyPair:
icn-identity/src/keybundle.rs