From 93cd8b4bf406d2420e4b730e29a5847977e6f959 Mon Sep 17 00:00:00 2001 From: "Digibyte.X" Date: Fri, 2 Oct 2026 18:37:31 +0200 Subject: [PATCH] daemon: verify proof-of-work on every synced header; fork choice by work DigiByte is multi-algorithm, so this brings in six hash functions: SHA256d and Scrypt in JS, and Qubit, Skein, Groestl and Odocrypt from DigiByte Core's own C sources compiled to WebAssembly (packages/p2p/native, emscripten via docker). Each header is checked against its nBits target and the network powLimit before it can enter the chain; a peer serving an invalid or future-dated header is benched. Competing branches are accepted only when they carry more accumulated work than what they replace. npm run pow:test -w @dgb-wallet/p2p verifies real mainnet headers of all six algorithms and that a tampered header fails. --- docs/SECURITY-ROADMAP.md | 206 +- ops/push.sh | 2 +- packages/p2p/bin/dgb-daemon.ts | 132 +- packages/p2p/native/build.sh | 26 + packages/p2p/native/dgbpow.c | 73 + packages/p2p/native/dgbpow.wasm | Bin 0 -> 153904 bytes packages/p2p/native/odo_glue.cpp | 9 + packages/p2p/native/src/KeccakP-800-SnP.h | 41 + .../p2p/native/src/KeccakP-800-reference.cpp | 422 +++ packages/p2p/native/src/aes_helper.h | 393 +++ packages/p2p/native/src/brg_endian.h | 142 + packages/p2p/native/src/common.h | 110 + packages/p2p/native/src/cubehash.cpp | 723 ++++ .../native/src/displayIntermediateValues.h | 8 + packages/p2p/native/src/echo.cpp | 1032 ++++++ packages/p2p/native/src/groestl.cpp | 3119 +++++++++++++++++ packages/p2p/native/src/luffa.cpp | 1428 ++++++++ packages/p2p/native/src/odocrypt.cpp | 301 ++ packages/p2p/native/src/odocrypt.h | 96 + packages/p2p/native/src/scrypt.cpp | 256 ++ packages/p2p/native/src/scrypt.h | 47 + packages/p2p/native/src/sha256.cpp | 775 ++++ packages/p2p/native/src/sha256.h | 53 + packages/p2p/native/src/shavite.cpp | 1764 ++++++++++ packages/p2p/native/src/simd.cpp | 1799 ++++++++++ packages/p2p/native/src/skein.cpp | 1254 +++++++ packages/p2p/native/src/sph_cubehash.h | 292 ++ packages/p2p/native/src/sph_echo.h | 320 ++ packages/p2p/native/src/sph_groestl.h | 329 ++ packages/p2p/native/src/sph_luffa.h | 296 ++ packages/p2p/native/src/sph_shavite.h | 314 ++ packages/p2p/native/src/sph_simd.h | 309 ++ packages/p2p/native/src/sph_skein.h | 298 ++ packages/p2p/native/src/sph_types.h | 2009 +++++++++++ packages/p2p/package.json | 80 +- packages/p2p/scripts/pow-vectors.ts | 38 + packages/p2p/src/index.ts | 1 + packages/p2p/src/pow.ts | 139 + packages/p2p/test/pow-vectors.json | 1 + 39 files changed, 18469 insertions(+), 168 deletions(-) create mode 100644 packages/p2p/native/build.sh create mode 100644 packages/p2p/native/dgbpow.c create mode 100644 packages/p2p/native/dgbpow.wasm create mode 100644 packages/p2p/native/odo_glue.cpp create mode 100644 packages/p2p/native/src/KeccakP-800-SnP.h create mode 100644 packages/p2p/native/src/KeccakP-800-reference.cpp create mode 100644 packages/p2p/native/src/aes_helper.h create mode 100644 packages/p2p/native/src/brg_endian.h create mode 100644 packages/p2p/native/src/common.h create mode 100644 packages/p2p/native/src/cubehash.cpp create mode 100644 packages/p2p/native/src/displayIntermediateValues.h create mode 100644 packages/p2p/native/src/echo.cpp create mode 100644 packages/p2p/native/src/groestl.cpp create mode 100644 packages/p2p/native/src/luffa.cpp create mode 100644 packages/p2p/native/src/odocrypt.cpp create mode 100644 packages/p2p/native/src/odocrypt.h create mode 100644 packages/p2p/native/src/scrypt.cpp create mode 100644 packages/p2p/native/src/scrypt.h create mode 100644 packages/p2p/native/src/sha256.cpp create mode 100644 packages/p2p/native/src/sha256.h create mode 100644 packages/p2p/native/src/shavite.cpp create mode 100644 packages/p2p/native/src/simd.cpp create mode 100644 packages/p2p/native/src/skein.cpp create mode 100644 packages/p2p/native/src/sph_cubehash.h create mode 100644 packages/p2p/native/src/sph_echo.h create mode 100644 packages/p2p/native/src/sph_groestl.h create mode 100644 packages/p2p/native/src/sph_luffa.h create mode 100644 packages/p2p/native/src/sph_shavite.h create mode 100644 packages/p2p/native/src/sph_simd.h create mode 100644 packages/p2p/native/src/sph_skein.h create mode 100644 packages/p2p/native/src/sph_types.h create mode 100644 packages/p2p/scripts/pow-vectors.ts create mode 100644 packages/p2p/src/pow.ts create mode 100644 packages/p2p/test/pow-vectors.json diff --git a/docs/SECURITY-ROADMAP.md b/docs/SECURITY-ROADMAP.md index 67e7d2a..ba38253 100644 --- a/docs/SECURITY-ROADMAP.md +++ b/docs/SECURITY-ROADMAP.md @@ -1,95 +1,111 @@ -# DigiByte.X Wallet — Security Roadmap - -Derived from `D:\Dev\SilentCode\web_wallet_security_analysis.md` (the -general web-wallet threat model) and mapped onto what this wallet -actually does today. Each item says where we stand and what the next -concrete step is. Ordered by the analysis' own priority: CSP first, -then key-splitting, then hardware isolation. - -Last reviewed: 2026-09-09. - ---- - -## Where we stand against the threat model - -| Threat (analysis §1–2) | Status | Notes | -|---|---|---| -| Custodial key control | ✅ N/A | Non-custodial. Seed never leaves the browser; only signed tx bytes go out. | -| Server breach exposes keys | ✅ Mitigated | Nothing key-related on the server. Encrypted blobs live only in the user's `localStorage`. | -| Phishing / typo-squat | ⚠️ Partial | `digibyte.x` is a BNS name with IP + TLS fingerprint on-chain, so wallet-aware clients pin the server. Plain browsers reaching us through `navigate.st` trust that gateway's TLS. | -| XSS / injected script | ✅ Mitigated | Strict CSP live on `digibyte.x/web/` since 2026-09-06 (`script-src 'self'` + hash of the one inline script); asset tags carry SRI since 2026-09-09. | -| Malicious extensions | ⚠️ Inherent | Nothing in-page can stop an extension with page access. Mitigation is the multi-sig item below. | -| Local malware reading storage | ⚠️ Partial | Blobs are PBKDF2-210k + AES-GCM under the master password. Persistent PIN blob (100k rounds) weakens this for users who set a PIN — documented in `session-auth.ts`. | -| DNS spoofing | ✅ Mitigated for pinned clients | On-chain fingerprint pinning; see `ops/nginx-digibyte-x.conf` header comment. | - -## What the wallet already does (analysis §2 "Client-Side Architecture") - -- **Local cryptography.** BIP39/BIP32 via `@dgb-wallet/core`; WebCrypto PBKDF2 + AES-GCM in `packages/keystore` and `packages/web-ui/src/session-auth.ts`. -- **Encrypted local storage.** One master password per device; every wallet blob encrypted under it. Session auto-locks after 30 min idle. PIN is a shortcut with a 3-attempt budget; the master password restores it. -- **Local signing.** PSBT built and signed in `SendScreen.tsx`; keys are derived on demand and dropped with the component. -- **Verified broadcast.** `packages/p2p/src/broadcast.ts` treats a send as done only when an uninvolved peer announces the tx back (DGB Core drops policy failures silently). Fees sized to DGB's 100 sat/vB relay floor. -- **Address hygiene (opt-in).** Settings → Security → "Fresh addresses" rotates receive and change addresses to the first unused index. Off by default because "used" is only complete with Blockbook enabled. - ---- - -## Roadmap - -### 1. Strict Content Security Policy — MANDATORY (analysis §3) — ✅ APPLIED 2026-09-06 - -Add to the nginx `location /web/` block on the VPS (and keep `ops/nginx-digibyte-x.conf` in sync): - -```nginx -add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-MYCXjyaeuO4n6g9JktOO1yXmG9rBTuGJ5Wk4GojDwig=' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://api.coingecko.com; img-src 'self' data:; base-uri 'self'; frame-ancestors 'none'; form-action 'none'; object-src 'none'" always; -``` - -Notes: -- The `sha256-…` value is the hash of the inline ``-fixing script in the **built** `dist/index.html`. It changes whenever `packages/web-ui/index.html`'s inline script changes; recompute on each such change (a one-liner is in the deploy notes below) or move the script to a separate file under `assets/` to drop the hash entirely. -- `base-uri 'self'` (not `'none'`): the inline script injects a `` tag pointing at our own origin. -- `connect-src` needs CoinGecko only while the price feed is opt-in enabled; everything else (`../p2p/`, `../blockbook/`) is same-origin. -- `'unsafe-inline'` for styles is needed by a handful of inline `style=` attributes; removing them is a cleanup item, not a blocker. -- The `navigate.st` gateway serves the same HTML under its own headers; CSP there is the gateway's to set. - -Recompute the hash after a build: - -```bash -python -c "import re,hashlib,base64;h=open('packages/web-ui/dist/index.html',encoding='utf-8').read();s=re.findall(r'',h,re.S)[0];print('sha256-'+base64.b64encode(hashlib.sha256(s.encode()).digest()).decode())" -``` - -Applied and verified (zero violations through both digibyte.x and the navigate.st gateway). The repo mirror is `ops/nginx-digibyte-x.conf`; `ops/push.sh` warns when the live header's hash no longer matches the built inline script. - -### 2. Subresource integrity + reproducible bundle — ✅ SRI done 2026-09-09 - -- ✅ `integrity="sha384-…"` + `crossorigin` on the `',h,re.S)[0];print('sha256-'+base64.b64encode(hashlib.sha256(s.encode()).digest()).decode())" +``` + +Applied and verified (zero violations through both digibyte.x and the navigate.st gateway). The repo mirror is `ops/nginx-digibyte-x.conf`; `ops/push.sh` warns when the live header's hash no longer matches the built inline script. + +### 2. Subresource integrity + reproducible bundle — ✅ SRI done 2026-09-09 + +- ✅ `integrity="sha384-…"` + `crossorigin` on the `