Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
11e4e99
Improve Keycard benchmark verification and test
3rdIteration Jun 15, 2026
c731cbe
Tolerate non-canonical DER and use digit keyboard
3rdIteration Jun 15, 2026
dd7225a
Add keyboard text and kwargs to FakePrompt
3rdIteration Jun 15, 2026
b2ddbf2
Initialize passphrase keyboard from initial state
3rdIteration Jun 15, 2026
97bdd5d
Fix PIN entry keyboards to start on digits for Keycard/Specter-DIY
3rdIteration Jun 15, 2026
a9a054a
Bump PGPy to latest commit (7cdad00)
3rdIteration Jun 16, 2026
e247b7e
Return SignResult and add signing timeout retry
3rdIteration Jun 16, 2026
a8dedbd
Handle stale keycard pref for SeedKeeper flows
3rdIteration Jun 16, 2026
bfa829b
Fix test mock: accept backend_preference kwarg in mock_init_satochip
3rdIteration Jun 17, 2026
8fe2e5d
BIP85 GPG: Split ECC into app 828366' with remapped key_types and add…
3rdIteration Jun 17, 2026
b1c4451
Split microSD views into separate module, fix missing-import bugs, ad…
3rdIteration Jun 30, 2026
943fbc0
Swap pygame→pygame-ce for Python 3.14+, loosen pins, add 3.13/3.14 to…
3rdIteration Jun 30, 2026
9664009
Fix ZeroDivisionError in scan_screens.py FPS calculation on Windows
3rdIteration Jun 30, 2026
1a07d94
Exclude Windows + Python 3.14 from CI desktop matrix
3rdIteration Jun 30, 2026
33d818a
Add hardware-in-the-loop E2E smartcard test suite
3rdIteration Jul 1, 2026
fd30d16
fix: normalize line endings to LF with .gitattributes
3rdIteration Jul 1, 2026
8708658
Add smart card AID detection utility script
3rdIteration Jul 1, 2026
4b47916
Fix CI test failures: guard smartcard mock in base.py, catch BaseExce…
3rdIteration Jul 1, 2026
4ed0fc2
Fix CodeQL substring sanitization alert: use exact URL match
3rdIteration Jul 1, 2026
554afec
Add specter-card dep and fix cleanup exception handling
3rdIteration Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
7 changes: 6 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.12"]
python-version: ["3.12", "3.13", "3.14"]
exclude:
# Windows + Python 3.14: no pre-built cp314 wheels for embit,
# cffi, pyscard; building from source causes segfaults.
- os: windows-latest
python-version: "3.14"
defaults:
run:
shell: bash
Expand Down
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,19 @@ When moving or renaming an underscore-prefixed function:
- Use the same patterns as existing tests: `object.__new__(ViewClass)` to create view instances without triggering `__init__`, then monkeypatch dependencies.
- For views that reference symbols from split modules, ensure those symbols are accessible through `tools_views` (see star import caveat above).

### Navigation test maintenance

`tests/test_flows_menu_navigation.py` (**56 tests**) walks every UI menu path to catch lazy-import errors and platform-crashes. **Whenever a menu tree (a View's button_data list) is changed, a new View is added, or a View's imports are modified, update this test file** to cover the new/changed path.

Key rules:
- **Every settings-gated or conditionally-shown menu item must have a test** that verifies it is reachable (setting enabled) and/or hidden (setting disabled).
- **Every `run()` method that references an external module or class must be exercised** by at least one navigation test that reaches that `run()`. Missing-import bugs (`NameError`) are only caught when the View is actually entered.
- Tests verify **both** forward navigation (correct destination) and backward navigation (BACK returns to the right parent via `BackStackView` or direct `Destination`).
- Deep sub-menus (e.g. Password Generator → Diceware-BIP39 → 64 bits → Dice) should be tested when they contain views with external dependencies or platform-specific code.
- Use `before_run` callbacks (like `_patch_microsd_child`, `_patch_scan_view_decoder`) to patch hardware deps so child Views can be entered without crashing in CI.

When adding a new View that uses lazy imports, always add the corresponding `FlowStep` to an existing or new test method — even a simple "navigate to the View and stop" test is sufficient to catch `NameError` regressions.

## Unicode and locale-safe string handling

SeedSigner must produce identical results regardless of the host locale or input method. Follow these rules when processing user-supplied or externally-sourced strings:
Expand Down
138 changes: 138 additions & 0 deletions docs/bip85_gpg_version_history.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# BIP85 GPG Version History

SeedSigner implements [BIP85](https://github.com/bitcoin/bips/blob/master/bip-0085.mediawiki)
for deterministic GPG key derivation. The derivation scheme has evolved through
several versions as the spec and available hardware matured.

## Overview

| Version | Period | Tags | Key change |
|---------|--------|------|------------|
| v0 | Aug 31 – Sep 14, 2025 | *(development only, no release)* | Initial implementation; all keys use app 828365 |
| v1 | Sep 15, 2025 – Mar 8, 2026 | `SS0.8.6+Satochip+Earthdiver-B4` … `SeSi-0.8.6+ShSi-B8` | Separate BIP85 app per curve |
| v2 | Mar 9, 2026 – Jun 2026 | `SeSi-0.8.6+ShSi-B9`, `SeSi-0.8.6+ShSi-B10` | Unified app 828365 with `key_type` codes |
| v3 | Jun 2026+ (planned) | *(B11-TestingFixes branch, unreleased)* | Split RSA (828365) and ECC (828366) apps |

## Detailed per-version description

### v0 (development — unreleased)

First working implementation. Every curve used the same BIP85 app number and
a simple `[param, index]` path.

- **App**: `828365'` for all key types
- **Path format**: `m/83696968'/828365'/{param}'/{index}'`
- **Param**: `{key_bits}` for RSA (e.g. 2048), `259` for Curve25519, `256` for ECDSA curves
- **Curves**: RSA 2048/3072/4096, Curve25519, secp256k1, NIST P-256
- **Tags**: None — development-only. The compatible upstream
[bipsea](https://github.com/3rdIteration/bipsea) test vectors were never
generated for this version.

### v1 (tagged releases B4 through B8)

Each curve got its own BIP85 app number. ECC was restricted to 256-bit.

- **Apps**:

| Curve | App |
|-------|-----|
| RSA | `828365'` |
| Curve25519 | `828366'` |
| secp256k1 | `828367'` |
| NIST P-256 | `828368'` |
| Brainpool P-256 | `828369'` |

- **Path format**: `m/83696968'/{app}'/256'/{index}'` (ECC); `m/83696968'/828365'/{bits}'/{index}'` (RSA)
- **Key type codes**: Not used — the curve was encoded in the app number
- **Curves**: RSA, Curve25519, secp256k1, NIST P-256, Brainpool P-256
- **Tags**: `SS0.8.6+Satochip+Earthdiver-B4` through `SeSi-0.8.6+ShSi-B8`

### v2 (tagged releases B9, B10)

Unified all curves under a single app number with a `key_type` discriminator.
Added P-384, P-521, Brainpool P-384, Brainpool P-512.

- **App**: `828365'` for all key types
- **Path format**: `m/83696968'/828365'/{key_type}'/{key_bits}'/{index}'[/{sub_index}']`
- **Key type codes**:

| Code | Curve |
|------|-------|
| 0 | RSA |
| 1 | Curve25519 |
| 2 | secp256k1 |
| 3 | NIST P-256 / P-384 / P-521 |
| 4 | Brainpool P-256 / P-384 / P-512 |

- **Curves**: RSA, Curve25519, secp256k1, NIST (P-256/P-384/P-521), Brainpool (P-256/P-384/P-512)
- **Tags**: `SeSi-0.8.6+ShSi-B9`, `SeSi-0.8.6+ShSi-B10`

### v3 (B11-TestingFixes branch — unreleased)

**Breaking change for ECC keys only.** RSA key derivation is identical to v2.

Splits RSA and ECC into separate apps and remaps ECC `key_type` codes so the
least-used curve (Brainpool) occupies code 0, reducing migration friction.

- **Apps**:

| Family | App |
|--------|-----|
| RSA | `828365'` (unchanged from v2) |
| ECC | `828366'` (new) |

- **Path format**:
- RSA: `m/83696968'/828365'/0'/{bits}'/{index}'[/{sub_index}']`
- ECC: `m/83696968'/828366'/{key_type}'/{key_bits}'/{index}'[/{sub_index}']`
- **ECC key type codes** (remapped):

| Code | Curve |
|------|-------|
| 0 | Brainpool P-256 / P-384 / P-512 |
| 1 | Curve25519 |
| 2 | secp256k1 |
| 3 | NIST P-256 / P-384 / P-521 |

- **RSA key type code**: 0 (unchanged from v2)
- **Curves**: Same as v2

## Summary table

```
v0 (dev) v1 (B4-B8) v2 (B9-B10) v3 (B11)
────────────────────────────────────────────────────────────────
App 828365' 828365'-828369' 828365' 828365' (RSA)
828366' (ECC)

Path [param, idx] [256, idx] (ECC) [kt, bits, idx] [kt, bits, idx]
[bits, idx] (RSA)

ECC kt N/A N/A 1=C25519 1=C25519
2=secp256k1 2=secp256k1
3=NIST 3=NIST
4=Brainpool 0=Brainpool

RSA kt N/A N/A 0 0

P-384/ ✗ ✗ ✓ ✓
P-521

Brainpool ✗ P-256 only ✓ ✓
```

## Notes

- **v0 was never released** — no tagged release or public build contains it.
The compatible bipsea test vectors were generated starting from v1.
- **v2 → v3 is a breaking change for ECC keys** — the app number changed
from `828365'` to `828366'` and key_type codes were remapped. RSA keys
are unaffected.
- **Upstream SeedSigner (v0.8.7)** does **not** contain any GPG support.
All versions described above are on the
[3rdIteration](https://github.com/3rdIteration/SeedSigner) fork.

## See also

- [`docs/gpg_tools.md`](gpg_tools.md) — user-facing GPG feature documentation
- [`tools/bip85_pgp.py`](../tools/bip85_pgp.py) — standalone CLI tool
- [bipsea test vectors](https://github.com/3rdIteration/bipsea/blob/main/test_vectors.md)
Loading
Loading