G56-16: reconcile stale claims — README OTS trust model (API-assisted vs light-client), remove stale not-implemented items, soften nip_proposal signer/OTS/pending-proof wording, add research-prototype banners to verify.html + all docs and research files
This commit is contained in:
@@ -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
|
||||
|
||||
---
|
||||
|
||||
@@ -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:** ✅
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
+13
-2
@@ -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.
|
||||
|
||||
+1
-1
@@ -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": {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-3
@@ -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"
|
||||
}
|
||||
|
||||
+11
-3
@@ -253,13 +253,21 @@
|
||||
|
||||
<div class="pq-card">
|
||||
<div class="pq-card-title">Verify NIP-QR Migration Event</div>
|
||||
<div class="pq-info-text" style="color: var(--accent-color); font-size: 13px;">
|
||||
<strong>Research prototype.</strong> 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.
|
||||
</div>
|
||||
<div class="pq-info-text">
|
||||
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.
|
||||
</div>
|
||||
<div class="pq-info-text">
|
||||
<a href="./" class="pq-link">Back to migration page</a>
|
||||
|
||||
Reference in New Issue
Block a user