mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-06 21:02:04 +00:00
parity: PGP key derivation, byte-for-byte with PGPy
The last unported derivation, and the one the plan flagged as highest risk. It turned out to be fully reproducible: the key material is deterministic, EdDSA signatures are deterministic (RFC 8032), and the packet layout is fixed -- so the armored blocks match exactly, with no OpenPGP dependency. core/derive/pgp.ts emits the packets directly: new-format headers, the secret-key packet (unencrypted MPI plus 16-bit checksum), the user-id packet, and the self-certification signature with PGPy's exact subpacket set and order, wrapped in ASCII armor with a CRC-24 footer. Verified against PGPy across two seeds, three indices and three user-id shapes -- armored private key, armored public key, and fingerprint. RSA is deliberately unsupported: PyCryptodome's seeded prime search is not reproducible, so the TS port refuses the key type rather than silently deriving a different key. Two things worth recording from the build: the v4 fingerprint reproduces from first principles (SHA-1 over the public-key packet), which is what made byte-parity look feasible before committing to it; and the only mismatch in the first run was packet framing -- PGPy uses new-format headers where I had emitted old-format. CLI: `entry add pgp`, reveal (armored private key), `entry pgp-public`. Cross-impl phases A/B now cover a pgp entry in both directions, completing coverage of every creatable entry kind. 193 core + 47 CLI tests green; 30/30 cross-implementation checks green. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
1 parent
5dcd779a6f
commit
c2d7306bb7
12 files changed
+457
-13
No files matched your search
@@ -17,7 +17,7 @@ P0 gate is green, Python remains the normative reference
|
||||
| Cross-implementation profile interop | green |
|
||||
| Sync protocol parity | green |
|
||||
| Agent security model | green (TS ahead of Python) |
|
||||
| Feature parity for daily use | partial |
|
||||
| Feature parity for daily use | partial (all derivations green) |
|
||||
| Packaging + release | not started |
|
||||
| Migration + rollback story | not started |
|
||||
|
||||
@@ -47,14 +47,15 @@ P0 gate is green, Python remains the normative reference
|
||||
and the TS CLI restores it with secrets intact. **Green.**
|
||||
|
||||
5. **Feature parity for real daily use.** **Partial.** Remaining:
|
||||
- PGP key material (entries round-trip; derivation not ported — highest
|
||||
parity risk, PGPy serialization)
|
||||
- document import/export commands
|
||||
- `semantic` and `api` command groups (deliberately deferred; decide
|
||||
whether they block cutover or ship post-cutover)
|
||||
- PGP RSA keys: unsupported by design (not byte-reproducible). Decide
|
||||
whether existing RSA entries block cutover; ed25519 is at parity.
|
||||
|
||||
Done since this list was written: SSH key derivation (PEM byte-for-byte)
|
||||
and schema migrations 0→4, so legacy Python profiles now open in TS.
|
||||
Done since this list was written: SSH and PGP key derivation (both
|
||||
byte-for-byte) and schema migrations 0→4, so legacy Python profiles now
|
||||
open in TS.
|
||||
|
||||
6. **Packaging and distribution exist.** Not started. Needs: an installable
|
||||
artifact (npm bin, single-file build, or both), checksums and signatures
|
||||
|
||||
@@ -31,7 +31,7 @@ until a later milestone.
|
||||
| Password KDF (Argon2id) | P0 | green | `password_kdf.json` | `@noble/hashes` argon2id (pure JS, audited family); default (t=2, m=64MiB, p=8) and light params verified. |
|
||||
| KDF metadata parsing | P0 | green | `kdf_metadata.json`, `legacy_payloads.json` | KdfConfig schema with Python-default fallbacks. |
|
||||
| SSH key derivation | P1 | green | `ssh_keys.json` | Ed25519 from BIP-85 app 32; PKCS#8 and SubjectPublicKeyInfo PEM match Python `cryptography` byte-for-byte (fixed DER prefixes, no ASN.1 dependency). CLI: `entry add ssh`, reveal (private PEM), `entry ssh-public` (PEM or OpenSSH line — the OpenSSH format is a TS-only convenience Python does not emit). Cross-impl phases A/B include an ssh entry. |
|
||||
| PGP key derivation | P1/P2 | todo | — | Highest parity risk (PGPy serialization); import/roundtrip first. |
|
||||
| PGP key derivation | P1/P2 | green | `pgp_keys.json` | Ed25519/EdDSA from BIP-85 app 32, creation time pinned to 2000-01-01Z. OpenPGP packets are emitted directly (no OpenPGP dependency): new-format headers, secret-key/user-id/self-signature packets, ASCII armor with CRC-24. Armored private and public blocks match PGPy byte-for-byte across two seeds, three indices and three user-id shapes. **RSA is deliberately unsupported** — PyCryptodome's seeded prime search is not reproducible, so TS refuses rather than emitting a different key. CLI: `entry add pgp`, reveal, `entry pgp-public`. |
|
||||
| Nostr snapshot chunk/manifest model | P0 | green | `nostr_snapshot.json` | Kinds 30070/30071/30072; gzip chunking, chunk-hash verify, reassembly of Python-produced chunks, manifest JSON parse, manifest id HMAC (key_index chain). Compressed bytes are deliberately not byte-pinned (deflate encoders differ); cross-decompression verified both ways. |
|
||||
| Relay transport + sync flows | P0 | green | — (live mock relay) | RelayPool over platform WebSocket (multi-relay publish/fetch, dedupe, signature verification on ingest); publish/fetch snapshot with chunk-hash verify, delta publish/replay. End-to-end tested against an in-process NIP-01 relay incl. corrupted-chunk rejection, and at the CLI level: sync -> destroy local vault -> restore. jsdom skips transport tests (real-browser run: Milestone 6 CI). |
|
||||
| Deterministic conflict merge | P0 | green | `sync_merge.json` | Full `merge_index_payloads` port: ts precedence, canonical-hash tie-breaks (Python-compatible ensure_ascii canonical JSON), equal-ts field union incl. the `custom_fields: null` quirk, tombstone lifecycle, retention cap, `_sync_meta`. |
|
||||
@@ -51,7 +51,7 @@ until a later milestone.
|
||||
|
||||
| Environment | Status |
|
||||
|---|---|
|
||||
| Node 22 (vitest) | green — 173/173 core + 44 CLI |
|
||||
| Node 22 (vitest) | green — 193/193 core + 44 CLI |
|
||||
| jsdom browser-like env | green — 148/148 core (3 transport tests Node-only) |
|
||||
| Real Chromium/Firefox (vitest browser mode) | todo — lands with Milestone 6 web app CI |
|
||||
|
||||
@@ -83,7 +83,7 @@ the same values:
|
||||
|
||||
Entry coverage in phases A/B: password (plain and policy-constrained), TOTP
|
||||
(deterministic and imported), key_value, document, seed, managed_account,
|
||||
nostr, ssh.
|
||||
nostr, ssh, pgp — every creatable kind.
|
||||
|
||||
## Known intentional divergences
|
||||
|
||||
|
||||
Reference in new issue
Block a user