From cfa0ecc2200887fcada9176481a1083af55e3006 Mon Sep 17 00:00:00 2001 From: Laan Tungir Date: Fri, 24 Jul 2026 09:09:51 -0400 Subject: [PATCH] =?UTF-8?q?G56-16:=20reconcile=20stale=20claims=20?= =?UTF-8?q?=E2=80=94=20README=20OTS=20trust=20model=20(API-assisted=20vs?= =?UTF-8?q?=20light-client),=20remove=20stale=20not-implemented=20items,?= =?UTF-8?q?=20soften=20nip=5Fproposal=20signer/OTS/pending-proof=20wording?= =?UTF-8?q?,=20add=20research-prototype=20banners=20to=20verify.html=20+?= =?UTF-8?q?=20all=20docs=20and=20research=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 ++++++++++++++++++++++---- audits/GPT5.6/remediation_progress.md | 15 ++++++++-- explanation.md | 5 ++++ laans_explanation.md | 5 +++- nip_proposal.md | 15 ++++++++-- package.json | 2 +- research/amber_integration_analysis.md | 4 +++ research/amber_integration_plan.md | 4 +++ research/existing_pq_proposals.md | 2 ++ research/nip_qr_two_account_flow.md | 4 +++ research/pq_js_packages_survey.md | 2 ++ why_what_how.md | 5 ++++ www/js/version.json | 6 ++-- www/verify.html | 14 +++++++-- 14 files changed, 104 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 2e453ce..faec2ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,12 @@ # Post-Quantum Nostr +> **⚠️ Research prototype.** This project is an experimental pre-quantum key-commitment and +> identity-link system. It does **not**, by itself, make a Nostr identity post-quantum secure: +> it links PQ keys to an existing identity and anchors that link in Bitcoin. Complete migration +> requires companion protocols (PQ event authentication, rotation, encryption, client adoption) +> that are not yet specified or implemented. Do not enter a valuable existing mnemonic into the +> web app. See the [implementation status](#implementation-status) section for what exists today. + A migration strategy for bringing post-quantum security to Nostr without breaking the social graph, without requiring consensus on a single post-quantum algorithm, and without forcing existing users to abandon their identities. ## Table of Contents @@ -374,7 +381,28 @@ The kind 9999 proof carrier *carries* the OTS proof; the kind 1 event *is* what' ### Current OTS Verification Status -The current implementation detects Bitcoin confirmation by searching the `.ots` proof bytes for the Bitcoin block-header attestation magic bytes, and delegates proof upgrading to a server-side helper. **Full client-side OTS verification** (parsing the proof, validating the Merkle path, checking the block header against the Bitcoin chain) is planned but not yet implemented. The vendored `javascript-opentimestamps` library in `resources/` provides the necessary primitives and will be integrated in a future release. +> **Research prototype — trust model.** The current OTS verification is **API-assisted**, not a +> full Bitcoin light-client verification. Treat results accordingly. + +The current implementation: + +- Parses the `.ots` proof and validates the Merkle path against a block header obtained from a + public Bitcoin explorer API (mempool.space). +- Detects Bitcoin confirmation by searching the proof bytes for the block-header attestation magic + bytes and confirming the attested block height via the same API. +- Delegates proof *upgrading* (asking calendars for a confirmed proof) to a server-side helper. + +**What is NOT done:** + +- **Full light-client verification** — validating the block header's proof-of-work, difficulty, and + chain linkage independently, without trusting an explorer API. The vendored + `javascript-opentimestamps` library in `resources/` provides primitives for this and will be + integrated in a future release. +- **Multi-explorer cross-checking** — comparing independent APIs and rejecting disagreement. + +Because the block header is trusted from a single API, a compromised or malicious explorer could +falsify a confirmation. The UI labels this as "API-checked," not "cryptographically verified on +Bitcoin." ### What Should Be OpenTimestamped @@ -762,12 +790,12 @@ The current implementation is a static web app (`www/`) that performs the full m | Component | Description | |---|---| -| Full client-side OTS verification | Parse the .ots proof, validate the Merkle path, check the block header against the Bitcoin chain (the vendored `javascript-opentimestamps` library in `resources/` provides the primitives) | -| OTS target-digest binding | Verify the OTS proof's target digest equals the event's `sha256` tag | +| Full light-client Bitcoin verification | Validate block headers, proof-of-work, difficulty, and chain linkage independently of an explorer API (the vendored `javascript-opentimestamps` library in `resources/` provides primitives). Current path trusts a single explorer API for the header. | +| Multi-explorer cross-checking | Compare independent Bitcoin APIs and reject disagreement | | Raw-nsec migration (Component 4) | Encrypt old nsec, publish kind 30078, 36-word phrase encoding | | Quantum-safe self-storage (Component 5) | OTP or symmetric-key encryption for kind 30078 data | -| Test suite | Known-answer tests for derivation, PQ sign/verify round-trips, event verification | -| 24-word mnemonic default | Currently defaults to 12 words; 24 recommended for production | +| PQ event authentication / rotation / revocation | Companion protocols for signing future events with PQ keys, rotating/revoking keys, PQ encryption | +| Independent implementation / test vectors | A second implementation reproducing canonical encoding, derivation, and selection | ### Dependencies @@ -778,7 +806,7 @@ The current implementation is a static web app (`www/`) that performs the full m - [`@scure/bip32`](https://github.com/paulmillr/scure-bip32) — BIP32 HD wallet derivation - [`@scure/base`](https://github.com/paulmillr/scure-base) — bech32 (npub) encoding - [OpenTimestamps](https://opentimestamps.org/) — calendar servers for timestamping -- [`javascript-opentimestamps`](resources/javascript-opentimestamps/) — vendored OTS library (present, not yet integrated for client-side verification) +- [`javascript-opentimestamps`](resources/javascript-opentimestamps/) — vendored OTS library (used as a fixture source; full light-client integration pending) - [nostr-login-lite](https://github.com/nostrband/nostr-login-lite) — NIP-07 / NIP-46 authentication --- diff --git a/audits/GPT5.6/remediation_progress.md b/audits/GPT5.6/remediation_progress.md index 9e4767c..8d8a165 100644 --- a/audits/GPT5.6/remediation_progress.md +++ b/audits/GPT5.6/remediation_progress.md @@ -10,9 +10,9 @@ |---|---:|---:|---:|---:| | Critical | 2 | 2 | 0 | 0 | | High | 6 | 1 | 0 | 5 | -| Medium | 8 | 1 | 0 | 7 | +| Medium | 8 | 2 | 0 | 6 | | Low / Info | 4 | 0 | 0 | 4 | -| **Total** | **20** | **4** | **0** | **16** | +| **Total** | **20** | **5** | **0** | **15** | ## Findings status @@ -33,7 +33,7 @@ | G56-13 | Medium | OTS parser lacks total input/operation budgets, unsafe 32-bit varuint | ❌ Not started | — | Add size/operation/branch limits, safe varuint parsing | | G56-14 | Medium | Dependency resolution not reproducible; lockfile ignored and inconsistent | ❌ Not started | — | Commit lockfile, use npm ci, add CI | | G56-15 | Medium | OpenTimestamps submodule not clonable; historical dependency risk | ❌ Not started | — | Fix .gitmodules or vendor immutable snapshot | -| G56-16 | Medium | Documentation and UI overclaim implementation status | ⚠️ Partially fixed | v0.0.14–v0.0.16 | Updated nip_proposal.md, README.md, explanation.md, why_what_how.md, laans_explanation.md for kind 9999. Remaining: broader status reconciliation | +| G56-16 | Medium | Documentation and UI overclaim implementation status | ✅ Fixed | v0.0.14–v0.0.18 | Kind 9999 docs (v0.0.14–v0.0.16); v0.0.17 fixed index.html claims + 24-word default; v0.0.18 reconciled README OTS trust model (API-assisted vs light-client), removed stale "not implemented" items (target-digest binding, test suite, 24-word default), softened nip_proposal.md ("No private key ever touches a server" → NIP-07/remote-signer caveat; pending-proof "establishes submission time" → "evidence of submission"; fixed "republished" → "new proof carrier published"), added research-prototype banners to verify.html + README + nip_proposal + explanation.md + laans_explanation.md + why_what_how.md + all 5 research/ docs | | G56-17 | Low | Block-height statement not validated | ❌ Not started | — | Validate against OTS height or remove from signed content | | G56-18 | Low | Relay URL policy permits insecure ws:// | ❌ Not started | — | Require wss:// in production | | G56-19 | Low | Missing event IDs accepted by library verifier | ❌ Not started | — | Require exact NIP-01 shape with 64-hex ID | @@ -84,10 +84,19 @@ - Updated README.md entropy table and nip_proposal.md mermaid diagram - Added 4 new tests (24-word default, 12-word option, invalid entropyBits rejection for both functions) +### v0.0.18 — G56-16 fix (status reconciliation) +- README.md: rewrote OTS verification status section to distinguish API-assisted verification (current, trusts explorer) from full light-client verification (not implemented); added research-prototype banner +- README.md: removed stale "not implemented" items (OTS target-digest binding, test suite, 24-word default); added accurate not-implemented items (light-client verification, multi-explorer cross-check, PQ event auth/rotation, independent implementation) +- nip_proposal.md: softened "No private key ever touches a server" → NIP-07/remote-signer caveat + API-assisted OTS trust model; pending-proof "establishes submission time" → "evidence of submission, not an independent timestamp"; fixed "republished" → "new proof carrier published with upgrade_of tag" +- verify.html: added research-prototype note; rewrote card description to list each verification check as a separate result line (PQ signatures individually, policy sufficiency, identity binding) +- Added research-prototype / design-only banners to explanation.md, laans_explanation.md, why_what_how.md, and all 5 research/ docs +- No new tests (documentation-only change) + ## Test count - **Before remediation:** 38 tests - **After G56-01:** 49 tests - **After G56-02+03:** 61 tests - **After G56-09:** 65 tests +- **After G56-16:** 65 tests (docs-only) - **All passing:** ✅ diff --git a/explanation.md b/explanation.md index 20fcef8..616a49b 100644 --- a/explanation.md +++ b/explanation.md @@ -1,5 +1,10 @@ # How the NIP-QR Event Is Constructed: Step by Step +> **⚠️ Research prototype.** This document describes an experimental pre-quantum key-commitment +> system. It links PQ keys to an existing Nostr identity and anchors that link in Bitcoin; it does +> not, by itself, make the identity post-quantum secure. Complete migration requires companion +> protocols not yet specified or implemented. + ## The Misconception The seed phrase is NOT used directly as the private key for PQ signing. The seed phrase is a source of entropy that is used to **derive** separate keys for each PQ algorithm via **BIP32 HD wallet derivation paths** — the same standard used by NIP-06 for secp256k1 keys. diff --git a/laans_explanation.md b/laans_explanation.md index 6043db2..1ddb674 100644 --- a/laans_explanation.md +++ b/laans_explanation.md @@ -1,8 +1,11 @@ # Laan's explanation +> **⚠️ Research prototype.** This is a short summary of an experimental pre-quantum key-commitment +> system. It does not, by itself, make a Nostr identity post-quantum secure. + A short summary of how the post-quantum Nostr migration works, matching the implementation. -1. **Create a new seed phrase.** This is your post-quantum (PQ) Nostr backup. It's a 12-word BIP39 mnemonic — pure entropy, not tied to any algorithm. +1. **Create a new seed phrase.** This is your post-quantum (PQ) Nostr backup. It's a BIP39 mnemonic (24 words by default; 12 words available for testing) — pure entropy, not tied to any algorithm. 2. **Derive 5 PQ keypairs from the seed.** Using BIP32 hierarchical deterministic derivation (the same standard as NIP-06), each PQ algorithm gets its own child key under the path `m/44'/1237'/0'/0/`: - child 1 → ML-DSA-44 diff --git a/nip_proposal.md b/nip_proposal.md index 7a79afa..0df6ec6 100644 --- a/nip_proposal.md +++ b/nip_proposal.md @@ -209,7 +209,7 @@ When a client finds multiple kind 9999 proof carriers for the same attesting ide ### OTS proof states -An OTS proof may be **pending** (not yet anchored in a Bitcoin block) or **confirmed** (anchored). A pending proof asserts that the digest has been submitted to calendar servers; a confirmed proof asserts a Bitcoin block commitment. Clients SHOULD treat a confirmed proof as authoritative. A pending proof is still useful: it establishes that the digest existed at submission time, and it can be upgraded to a confirmed proof later by re-querying the calendars. The wrapper is republished with the upgraded proof. +An OTS proof may be **pending** (not yet anchored in a Bitcoin block) or **confirmed** (anchored). A pending proof is evidence that the digest was submitted to calendar servers; it is **not** an independent timestamp and depends on calendar behavior. A confirmed proof asserts a Bitcoin block commitment. Clients SHOULD treat a confirmed proof as authoritative. A pending proof can be upgraded to a confirmed proof later by re-querying the calendars; when that happens, a **new** proof carrier event is published carrying the upgraded proof and referencing the original via an `upgrade_of` tag. The original event remains on relays permanently. ### Client-side verification @@ -294,4 +294,15 @@ This NIP builds on and is compatible with several existing community proposals: ## Reference implementation -A static, client-side-only web implementation exists at `https://laantungir.net/post-quantum/`. All cryptographic operations (BIP39, BIP32, PQ keygen/sign/verify, OTS submission and verification) happen in the browser. No private key ever touches a server. Source: [`www/js/pq-crypto.mjs`](www/js/pq-crypto.mjs:1) in this repository. +> **⚠️ Research prototype.** The implementation is experimental and is not a complete post-quantum +> migration. It links PQ keys to an existing identity and anchors that link in Bitcoin; it does not +> yet define PQ authentication for routine events, key rotation/revocation, or PQ encryption. + +A static, client-side-only web implementation exists at `https://laantungir.net/post-quantum/`. +Cryptographic operations (BIP39, BIP32, PQ keygen/sign/verify, OTS submission and Merkle-path +verification) happen in the browser. Private keys are handled in the browser or via a NIP-07 signer +extension, which may be a remote signer (NIP-46); in that case the signing key does not touch the +page origin. OTS proof *upgrading* uses a server-side helper, and Bitcoin block-header confirmation +relies on a public explorer API (mempool.space) — this is **API-assisted verification**, not a full +Bitcoin light-client verification. Source: [`www/js/pq-crypto.mjs`](www/js/pq-crypto.mjs:1) in this +repository. diff --git a/package.json b/package.json index cab7827..08d283e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "post_quantum_nostr", - "version": "0.0.17", + "version": "0.0.18", "description": "A migration strategy for bringing post-quantum security to Nostr without breaking the social graph, without requiring consensus on a single post-quantum algorithm, and without forcing existing users to abandon their identities.", "main": "index.js", "scripts": { diff --git a/research/amber_integration_analysis.md b/research/amber_integration_analysis.md index b634495..1079392 100644 --- a/research/amber_integration_analysis.md +++ b/research/amber_integration_analysis.md @@ -1,5 +1,9 @@ # 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: diff --git a/research/amber_integration_plan.md b/research/amber_integration_plan.md index d462760..eb3b54c 100644 --- a/research/amber_integration_plan.md +++ b/research/amber_integration_plan.md @@ -1,5 +1,9 @@ # Amber Integration Plan: End-User Experience +> **⚠️ Design-only research document.** This describes a planned user experience, not a shipped +> feature. The current system is a research prototype; it links PQ keys to an identity and anchors +> that link in Bitcoin, but does not by itself make the identity post-quantum secure. + ## Overview This document describes the complete end-to-end user experience for migrating a Nostr identity to post-quantum security using the PQ web app and Amber signer. There are **two paths** depending on how the user's account was created in Amber: diff --git a/research/existing_pq_proposals.md b/research/existing_pq_proposals.md index 5ceb783..20bd811 100644 --- a/research/existing_pq_proposals.md +++ b/research/existing_pq_proposals.md @@ -1,5 +1,7 @@ # Existing Post-Quantum Proposals in the Nostr Ecosystem +> **⚠️ Research document.** A survey of community discussion; not an implementation spec. + A survey of pull requests and issues in `nostr-protocol/nips` related to post-quantum cryptography, key migration, and key rotation — and how they compare to our plan in [`README.md`](../README.md). Research date: 2026-07-12 diff --git a/research/nip_qr_two_account_flow.md b/research/nip_qr_two_account_flow.md index 19ede59..ba46916 100644 --- a/research/nip_qr_two_account_flow.md +++ b/research/nip_qr_two_account_flow.md @@ -1,5 +1,9 @@ # NIP-QR: Two-Account Flow Architecture +> **⚠️ Design-only research document.** This describes the proposed architecture; the current +> implementation is a research prototype and does not by itself make Nostr identities +> post-quantum secure. + ## The Flow (as proposed) ``` diff --git a/research/pq_js_packages_survey.md b/research/pq_js_packages_survey.md index ec839ac..744ec00 100644 --- a/research/pq_js_packages_survey.md +++ b/research/pq_js_packages_survey.md @@ -1,5 +1,7 @@ # Post-Quantum Cryptography: JavaScript Package Survey +> **⚠️ Research document.** A library survey; not an implementation spec. + ## Executive Summary **We do NOT need to write our own implementations.** There are mature, well-maintained JavaScript packages for all NIST-standardized post-quantum algorithms. The standout recommendation is **[`@noble/post-quantum`](https://www.npmjs.com/package/@noble/post-quantum)** — a pure JavaScript implementation of all FIPS 203/204/205 algorithms, from the highly respected noble cryptography family (335 GitHub stars, MIT licensed, self-audited, actively maintained). diff --git a/why_what_how.md b/why_what_how.md index b1174a4..6dc6279 100644 --- a/why_what_how.md +++ b/why_what_how.md @@ -1,5 +1,10 @@ # Post-Quantum Nostr: Why, What, How +> **⚠️ Research prototype.** This document describes an experimental pre-quantum key-commitment +> and identity-link system. It does not, by itself, make a Nostr identity post-quantum secure; +> complete migration requires companion protocols (PQ event authentication, rotation, encryption, +> client adoption) that are not yet specified or implemented. + ## Why: The Problem ### Quantum computers will break Nostr's cryptography diff --git a/www/js/version.json b/www/js/version.json index ffb9e01..90ac770 100644 --- a/www/js/version.json +++ b/www/js/version.json @@ -1,5 +1,5 @@ { - "VERSION": "v0.0.17", - "VERSION_NUMBER": "0.0.17", - "BUILD_DATE": "2026-07-24T12:44:54.874Z" + "VERSION": "v0.0.18", + "VERSION_NUMBER": "0.0.18", + "BUILD_DATE": "2026-07-24T13:09:51.134Z" } diff --git a/www/verify.html b/www/verify.html index bef140f..d45da07 100644 --- a/www/verify.html +++ b/www/verify.html @@ -253,13 +253,21 @@
Verify NIP-QR Migration Event
+
+ Research prototype. Verification confirms key linkage and signature + validity; it does not mean the identity is post-quantum secure. Bitcoin OTS confirmation + is API-assisted (trusts a public explorer), not a full light-client verification. +
Verify post-quantum migration events (kind 9999) by querying relays for a user's pubkey, or by pasting event JSON directly. The kind 9999 event wraps a kind 1 announcement - (embedded in its content as JSON) and carries an OpenTimestamps proof. Verification checks: + (embedded in its content as JSON) and carries an OpenTimestamps proof. Verification checks, + reported as separate result lines: the kind 9999 secp256k1 signature, the embedded kind 1 event's secp256k1 signature, - the e tag (kind 1 event ID), the sha256 tag (full kind 1 event hash), all PQ signatures - (ML-DSA-44, ML-DSA-65, SLH-DSA-128s, Falcon-512, ML-KEM-768), and the OpenTimestamps proof. + the e tag (kind 1 event ID), the sha256 tag (full kind 1 event hash), each PQ signature + individually (ML-DSA-44, ML-DSA-65, SLH-DSA-128s, Falcon-512; ML-KEM-768 has no signature), + the PQ algorithm policy (all mandatory algorithms present and verified), identity binding + (outer/embedded/expected author match), and the OpenTimestamps proof.