Summary
Design and implement a Lockbox-native contact sharing model where public-key discovery/import is separate from trust verification.
The recommended direction is:
- Lockbox-native contacts are the core model.
- A tiny rendezvous server can provide the default convenient sharing path.
- Offline export/email/QR remains available when the server is unavailable.
- Existing infrastructure such as HTTPS well-known directories, OpenPGP WKD, and enterprise directories can be added later as discovery methods.
- Verification decisions remain local and explicit.
Security model
A key source only provides a candidate key. It must not automatically make the key trusted.
share/import/fetch -> candidate key
verify -> trusted contact key
key change -> pending changed key requiring verification
The server, if used, should be a relay/rendezvous service only. It must not be trusted to verify identity or key ownership.
A phone/video verification code prevents server-side key substitution, but it does not prove the caller is the claimed person. It only proves the person on that channel controls the key being verified. For stronger identity assurance, use an existing verified channel, in-person QR exchange, enterprise/domain policy, or a trusted prior key.
Recommended MVP flow
Alice shares her Lockbox public key:
lockbox share alice@example.com
CLI output:
Share code: 482913
Verification code: 71-44-92
Expires: 15 minutes
Bob fetches the candidate key:
lockbox contact add alice@example.com --share-code 482913
Bob's CLI displays the verification code derived from the actual candidate key. Bob confirms that code with Alice over an independent channel such as phone, video call, or in person.
lockbox contact verify alice@example.com
After verification:
lockbox access add project.lbox alice@example.com
Verification code requirements
The verification code should be derived from data that binds the claimed identity to the actual public key, for example:
hash("lockbox contact verify v1" || identity || public_key || share_nonce)
This ensures that if a compromised or malicious server substitutes a key, Bob sees a different verification code than Alice.
The share code is only a rendezvous code. It is not the trust mechanism.
Key replacement / rotation
Key replacement should be explicit and should distinguish signed continuity from an unsigned replacement.
Signed replacement using the old key
This is the preferred path when Alice still has access to her old verified Lockbox private key.
Alice generates or selects a new Lockbox key, then publishes a replacement claim signed by the old key:
lockbox contact replace alice@example.com --new-key alice-new.pub --sign-with alice-old.key
or, using the default local private key:
lockbox contact replace alice@example.com --new-key alice-new.pub --sign-current
The CLI should produce a share code and verification code, and upload or export a replacement payload containing:
identity
old_public_key_fingerprint
new_public_key
new_public_key_fingerprint
replacement_nonce
signature_by_old_key
created_at
expiry
Bob fetches the replacement:
lockbox contact update alice@example.com --share-code 615204
If Bob already has Alice's old key verified, Lockbox verifies the signature with the old trusted key:
Replacement is signed by Alice's previously verified key.
Old fingerprint: B84F 91C2 ...
New fingerprint: 9C10 552A ...
Trust: continuity verified
Bob accepts the replacement:
lockbox contact accept alice@example.com
After acceptance, the new key becomes the current verified key and the old key is retained in contact history.
Unsigned replacement
This is required when Alice lost the old private key or the old key may be compromised.
Alice initiates an unsigned replacement:
lockbox contact replace alice@example.com --new-key alice-new.pub --unsigned
Bob fetches it:
lockbox contact update alice@example.com --share-code 615204
Lockbox must stage the key as changed and warn that continuity is not proven:
WARNING: alice@example.com has a verified key, but this replacement is not signed by the old key.
Existing fingerprint: B84F 91C2 ...
New fingerprint: 9C10 552A ...
This may be legitimate key recovery, or it may be impersonation.
Verify through a stronger independent channel before accepting.
Bob must explicitly verify and accept:
lockbox contact verify alice@example.com --pending --method fingerprint
lockbox contact accept alice@example.com
For high-risk contacts, unsigned replacement should prefer in-person QR, enterprise/domain policy, or an already verified messaging channel. Phone-only verification should be labelled medium assurance because it is vulnerable to social and AI impersonation.
Replacement behavior rules
- A signed replacement can be treated as verified continuity if the signing key is the current verified key for that contact.
- An unsigned replacement must never overwrite the current verified key automatically.
access add should keep using the old verified key while a replacement is pending.
- If the old key is marked compromised, existing lockboxes should prompt the owner to remove or rotate access entries for that key.
- Contact history should retain old fingerprints, replacement metadata, verification method, and acceptance time.
Offline fallback
Support direct contact export/import from the first version so sharing works when the rendezvous server is unavailable.
Alice:
lockbox contact export alice@example.com --out alice.lockbox-contact
or:
lockbox share alice@example.com --offline
Bob:
lockbox contact add alice@example.com alice.lockbox-contact
lockbox contact verify alice@example.com
The offline import should show the same fingerprint/verification-code style confirmation and require out-of-band verification before marking the contact trusted.
QR support
QR codes are useful as a convenience format for share links, share codes, or complete offline contact payloads.
Examples:
lockbox share alice@example.com --qr
lockbox contact add --qr contact.png
QR reduces typing and copy/paste errors. It does not remove the need for verification unless Bob scans the QR directly from Alice's device in person.
Contact trust states
Initial states should stay simple:
unverified
verified
changed
revoked
Behavior:
contact add creates an unverified contact when no prior key exists.
contact verify promotes the current candidate key to verified.
- Adding the same verified key again should not reset trust.
- Adding a different key for an existing verified contact should stage it as a pending changed key.
access add should prefer verified keys and warn or refuse on unverified/changed keys.
Future richer states may include:
domain-validated
pgp-validated
enterprise-ca-validated
transparency-verified
Later infrastructure support
Add discovery methods in this order:
- HTTPS well-known Lockbox directory
lockbox contact add alice@company.com --method well-known
Fetch from a domain-controlled path such as:
https://company.com/.well-known/lockbox/alice.pub
- Domain policy / enterprise directory
Allow organizations to configure a trusted directory for their email domain.
- OpenPGP WKD
lockbox contact add alice@example.com --method pgp-wkd
This improves discovery for users or organizations that already publish OpenPGP keys. It does not eliminate first-contact verification unless the user already trusts the PGP identity or the domain policy.
- Transparency log
If the rendezvous/directory service becomes important, add append-only key history so the service cannot silently show different keys to different users without detection.
Non-goals for the first version
- Do not make native OpenPGP wrapping the initial design.
- Do not treat WhatsApp, iMessage, or email as key directories.
- Do not make server-returned keys automatically trusted.
- Do not rely on a PIN/share code as the verification mechanism.
Core principle
The server helps find keys.
The user or trusted organization verifies keys.
Lockbox remembers trust and detects changes.
Summary
Design and implement a Lockbox-native contact sharing model where public-key discovery/import is separate from trust verification.
The recommended direction is:
Security model
A key source only provides a candidate key. It must not automatically make the key trusted.
The server, if used, should be a relay/rendezvous service only. It must not be trusted to verify identity or key ownership.
A phone/video verification code prevents server-side key substitution, but it does not prove the caller is the claimed person. It only proves the person on that channel controls the key being verified. For stronger identity assurance, use an existing verified channel, in-person QR exchange, enterprise/domain policy, or a trusted prior key.
Recommended MVP flow
Alice shares her Lockbox public key:
CLI output:
Bob fetches the candidate key:
Bob's CLI displays the verification code derived from the actual candidate key. Bob confirms that code with Alice over an independent channel such as phone, video call, or in person.
After verification:
Verification code requirements
The verification code should be derived from data that binds the claimed identity to the actual public key, for example:
This ensures that if a compromised or malicious server substitutes a key, Bob sees a different verification code than Alice.
The share code is only a rendezvous code. It is not the trust mechanism.
Key replacement / rotation
Key replacement should be explicit and should distinguish signed continuity from an unsigned replacement.
Signed replacement using the old key
This is the preferred path when Alice still has access to her old verified Lockbox private key.
Alice generates or selects a new Lockbox key, then publishes a replacement claim signed by the old key:
or, using the default local private key:
The CLI should produce a share code and verification code, and upload or export a replacement payload containing:
Bob fetches the replacement:
If Bob already has Alice's old key verified, Lockbox verifies the signature with the old trusted key:
Bob accepts the replacement:
After acceptance, the new key becomes the current verified key and the old key is retained in contact history.
Unsigned replacement
This is required when Alice lost the old private key or the old key may be compromised.
Alice initiates an unsigned replacement:
Bob fetches it:
Lockbox must stage the key as changed and warn that continuity is not proven:
Bob must explicitly verify and accept:
For high-risk contacts, unsigned replacement should prefer in-person QR, enterprise/domain policy, or an already verified messaging channel. Phone-only verification should be labelled medium assurance because it is vulnerable to social and AI impersonation.
Replacement behavior rules
access addshould keep using the old verified key while a replacement is pending.Offline fallback
Support direct contact export/import from the first version so sharing works when the rendezvous server is unavailable.
Alice:
lockbox contact export alice@example.com --out alice.lockbox-contactor:
Bob:
The offline import should show the same fingerprint/verification-code style confirmation and require out-of-band verification before marking the contact trusted.
QR support
QR codes are useful as a convenience format for share links, share codes, or complete offline contact payloads.
Examples:
QR reduces typing and copy/paste errors. It does not remove the need for verification unless Bob scans the QR directly from Alice's device in person.
Contact trust states
Initial states should stay simple:
Behavior:
contact addcreates an unverified contact when no prior key exists.contact verifypromotes the current candidate key to verified.access addshould prefer verified keys and warn or refuse on unverified/changed keys.Future richer states may include:
Later infrastructure support
Add discovery methods in this order:
Fetch from a domain-controlled path such as:
Allow organizations to configure a trusted directory for their email domain.
This improves discovery for users or organizations that already publish OpenPGP keys. It does not eliminate first-contact verification unless the user already trusts the PGP identity or the domain policy.
If the rendezvous/directory service becomes important, add append-only key history so the service cannot silently show different keys to different users without detection.
Non-goals for the first version
Core principle