191 lines
12 KiB
Markdown
191 lines
12 KiB
Markdown
# Amber Integration Analysis for PQ Nostr Web App
|
|
|
|
> **⚠️ Design-only research document.** This is an analysis of a possible integration, not an
|
|
> implemented feature. The current system is a research prototype and does not make Nostr
|
|
> identities post-quantum secure by itself.
|
|
|
|
## Amber Capabilities (from source code analysis)
|
|
|
|
[Amber](https://github.com/greenart7c3/Amber) is an Android Nostr event signer that keeps the nsec segregated in a dedicated app. Based on source code inspection:
|
|
|
|
### Seed Phrase Support ✅
|
|
- **NIP-06 key derivation**: Uses `com.vitorpamplona.quartz.nip06KeyDerivation.Bip39Mnemonics` and `Nip06` for deriving secp256k1 keys from mnemonics
|
|
- **Stores seed words**: `DataStoreAccess.SEED_WORDS` persists the mnemonic in Android encrypted storage ([`DataStoreAccess.kt`](../Amber/app/src/main/java/com/greenart7c3/nostrsigner/DataStoreAccess.kt:41))
|
|
- **Generates new seeds**: Login screen generates random entropy → `Bip39Mnemonics.toMnemonics(entropy)` ([`LoginScreen.kt`](../Amber/app/src/main/java/com/greenart7c3/nostrsigner/ui/LoginScreen.kt:428))
|
|
- **Mnemonic login**: UI supports 12 or 24 word entry with account index selection ([`MnemonicLoginInput.kt`](../Amber/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MnemonicLoginInput.kt:48))
|
|
- **Seed backup**: Account export includes encrypted seed words ([`AccountExportService.kt`](../Amber/app/src/main/java/com/greenart7c3/nostrsigner/service/AccountExportService.kt:193))
|
|
|
|
### Signing Operations ✅
|
|
Amber supports these signer types ([`SignerType.kt`](../Amber/app/src/main/java/com/greenart7c3/nostrsigner/models/SignerType.kt:5)):
|
|
- `SIGN_EVENT` — sign any Nostr event
|
|
- `GET_PUBLIC_KEY` — return npub
|
|
- `NIP04_ENCRYPT` / `NIP04_DECRYPT`
|
|
- `NIP44_ENCRYPT` / `NIP44_DECRYPT`
|
|
- `NIP44_V3_ENCRYPT` / `NIP44_V3_DECRYPT` (new v3 cipher with kind+scope context)
|
|
- `DECRYPT_ZAP_EVENT`
|
|
|
|
### NIP-46 Remote Signing ✅
|
|
- Amber acts as a NIP-46 signing device — "your smartphone act as a NIP-46 signing device without any need for servers or additional hardware"
|
|
- Web apps can connect to Amber via NIP-46 (nostrconnect:// URI)
|
|
- Supports permission management per-app
|
|
|
|
### Multiple Accounts ✅
|
|
- Supports multiple accounts, each with its own nsec/seed words
|
|
|
|
---
|
|
|
|
## How Amber Fits the PQ Web App Vision
|
|
|
|
### The Key Insight
|
|
|
|
Amber already stores the **seed phrase** (BIP39 mnemonic) and uses it to derive secp256k1 keys via NIP-06. The seed phrase is algorithm-agnostic — it's just 128/256 bits of entropy. Our plan's **Component 1** (seed phrase as root of trust) means PQ keys can be derived from the *same seed* using different derivation paths.
|
|
|
|
### Three Architecture Options
|
|
|
|
#### Option A: Web App + Amber Signing (Minimal Amber Changes)
|
|
|
|
```
|
|
┌─────────────────┐ NIP-46 ┌──────────────────┐
|
|
│ Web App │ ◄──────────────► │ Amber │
|
|
│ (browser) │ │ (Android) │
|
|
│ │ │ │
|
|
│ 1. User enters │ getPublicKey │ Returns npub │
|
|
│ seed phrase │ ──────────────► │ │
|
|
│ (client-side │ │ │
|
|
│ only, WASM) │ signEvent │ Signs key-link │
|
|
│ │ (key-link) │ event with │
|
|
│ 2. Derives PQ │ ──────────────► │ secp256k1 │
|
|
│ keys from │ │ │
|
|
│ seed (WASM) │ │ │
|
|
│ │ │ │
|
|
│ 3. PQ-signs │ │ │
|
|
│ key-link │ │ │
|
|
│ client-side │ │ │
|
|
│ │ │ │
|
|
│ 4. Assembles & │ │ │
|
|
│ publishes │ │ │
|
|
│ key-link │ │ │
|
|
│ event │ │ │
|
|
└─────────────────┘ └──────────────────┘
|
|
```
|
|
|
|
**Flow**:
|
|
1. User connects to Amber via NIP-46 for secp256k1 signing
|
|
2. User enters their seed phrase in the web app (client-side only, WASM, never sent to server)
|
|
3. Web app derives PQ keys (ML-DSA, ML-KEM, SLH-DSA) from seed using liboqs-WASM
|
|
4. Web app requests Amber to sign the key-link event content with secp256k1
|
|
5. Web app PQ-signs the key-link event content client-side
|
|
6. Web app assembles the complete key-link event (secp256k1 sig + PQ sigs) and publishes to relays
|
|
7. Web app requests OpenTimestamps attestation via NIP-03
|
|
|
|
**Pros**: No Amber modifications needed. Full PQ key derivation in browser.
|
|
**Cons**: User must enter seed phrase in browser (even though client-side only). Trust model requires user to verify the web app isn't exfiltrating the seed.
|
|
|
|
#### Option B: Extend Amber for PQ Key Derivation (Best Security)
|
|
|
|
```
|
|
┌─────────────────┐ NIP-46 ┌──────────────────┐
|
|
│ Web App │ ◄──────────────► │ Amber │
|
|
│ (browser) │ │ (Android) │
|
|
│ │ │ │
|
|
│ 1. Connect to │ new method: │ Derives PQ keys │
|
|
│ Amber via │ pq_derive_keys │ from stored seed │
|
|
│ NIP-46 │ ──────────────► │ (liboqs native) │
|
|
│ │ │ │
|
|
│ 2. Requests PQ │ Returns PQ │ Returns PQ │
|
|
│ pubkey list │ ◄────────────── │ pubkeys only │
|
|
│ │ │ (privkeys stay │
|
|
│ 3. Requests │ new method: │ in Amber) │
|
|
│ key-link │ pq_sign │ │
|
|
│ signing │ ──────────────► │ PQ-signs event │
|
|
│ │ │ with PQ privkeys │
|
|
│ 4. Requests │ signEvent │ │
|
|
│ secp256k1 │ (existing) │ secp256k1 signs │
|
|
│ signing │ ──────────────► │ │
|
|
│ │ │ │
|
|
│ 5. Assembles & │ │ │
|
|
│ publishes │ │ │
|
|
└─────────────────┘ └──────────────────┘
|
|
```
|
|
|
|
**Flow**:
|
|
1. User connects to Amber via NIP-46
|
|
2. Web app calls new NIP-46 method `pq_derive_keys` — Amber derives PQ keys from its stored seed phrase using liboqs (native Android)
|
|
3. Amber returns only the PQ *public* keys (private keys never leave Amber)
|
|
4. Web app constructs the key-link event content with all pubkeys
|
|
5. Web app calls `pq_sign` — Amber PQ-signs the event content with each PQ private key
|
|
6. Web app calls `signEvent` — Amber secp256k1-signs the event
|
|
7. Web app assembles and publishes the complete key-link event
|
|
|
|
**Pros**: Seed phrase never leaves Amber. PQ private keys never leave Amber. Best security model — consistent with Amber's philosophy of "private keys should be exposed to as few systems as possible."
|
|
**Cons**: Requires Amber modifications (new NIP-46 methods, liboqs integration for Android).
|
|
|
|
#### Option C: Hybrid (Pragmatic)
|
|
|
|
```
|
|
┌─────────────────┐ NIP-46 ┌──────────────────┐
|
|
│ Web App │ ◄──────────────► │ Amber │
|
|
│ (browser) │ │ (Android) │
|
|
│ │ │ │
|
|
│ User chooses: │ │ │
|
|
│ │ │ │
|
|
│ Path 1 (Amber │ signEvent │ Signs with │
|
|
│ has seed): │ ──────────────► │ secp256k1 │
|
|
│ Request secp │ │ │
|
|
│ sig from Amber │ │ │
|
|
│ Enter seed in │ │ │
|
|
│ web app for PQ │ │ │
|
|
│ key derivation │ │ │
|
|
│ (client-side) │ │ │
|
|
│ │ │ │
|
|
│ Path 2 (raw │ signEvent │ Signs with │
|
|
│ nsec, no seed │ ──────────────► │ secp256k1 │
|
|
│ in Amber): │ │ │
|
|
│ Generate new │ │ │
|
|
│ seed in web app │ │ │
|
|
│ (client-side), │ │ │
|
|
│ derive PQ keys, │ │ │
|
|
│ request secp │ │ │
|
|
│ sig from Amber │ │ │
|
|
└─────────────────┘ └──────────────────┘
|
|
```
|
|
|
|
**Pros**: Works for both existing seed-phrase users and raw-nsec users. No Amber changes required for initial launch. Can upgrade to Option B later.
|
|
**Cons**: Seed phrase still enters browser for PQ derivation. Two code paths.
|
|
|
|
---
|
|
|
|
## Recommendation: Option B (Extend Amber)
|
|
|
|
This aligns with:
|
|
1. **Amber's security philosophy**: "Private keys should be exposed to as few systems as possible"
|
|
2. **Our plan's Component 1**: Seed phrase as algorithm-agnostic root of trust — Amber already stores it
|
|
3. **Our plan's Component 2**: Cross-signed key-link events — Amber can sign with both secp256k1 and PQ keys
|
|
4. **Community discussion** (Issue #1971): trbouma and mikedilger both advocate for HSM/enclave-based PQ key storage
|
|
|
|
### Required Amber Changes
|
|
|
|
1. **Add liboqs dependency**: Native library for PQ algorithms (ML-DSA, ML-KEM, SLH-DSA)
|
|
2. **PQ key derivation from seed**: New function that takes the stored BIP39 seed and derives PQ keys using a deterministic scheme (e.g., `HKDF(seed, "nostr-pq-ml-dsa-44")` → PQ private key)
|
|
3. **New NIP-46 methods**:
|
|
- `pq_get_public_keys` — return array of PQ public keys with algorithm identifiers
|
|
- `pq_sign` — sign a message with a specified PQ algorithm's private key
|
|
4. **Permission management**: New permission types for PQ signing operations
|
|
5. **UI updates**: Show PQ key information, approval screens for PQ signing requests
|
|
|
|
### Required Web App Components
|
|
|
|
1. **NIP-46 client**: Connect to Amber, send signing requests
|
|
2. **Key-link event builder**: Construct the event content with all pubkeys, request signatures, assemble final event
|
|
3. **OpenTimestamps client**: Request OTS attestation for the key-link event (NIP-03)
|
|
4. **Relay publisher**: Publish the key-link event to relays
|
|
5. **Verification UI**: Show the user what was created, verify the key-link event is valid
|
|
6. **No server-side secrets**: The web app is a static site — no backend that could intercept keys
|
|
|
|
### For Users Without Amber (or Without Seed Phrase in Amber)
|
|
|
|
The web app should also support:
|
|
- **NIP-07 browser extension signing** (nos2x, etc.) for secp256k1 signatures
|
|
- **Client-side seed phrase entry** (WASM, never transmitted) for users who want to derive PQ keys in-browser
|
|
- **New seed generation** for users who don't have a seed phrase yet (Component 4: migrating existing users with raw nsec)
|