Skip to content

new#1

Open
bmatusiak wants to merge 9 commits into
bm-ok:masterfrom
0c-coder:master
Open

new#1
bmatusiak wants to merge 9 commits into
bm-ok:masterfrom
0c-coder:master

Conversation

@bmatusiak

Copy link
Copy Markdown

No description provided.

T and others added 9 commits March 17, 2026 15:34
…ssphrase

Port three features from the OnlyKey-App (JavaScript) to python-onlykey:

1. loadkey - Parse OpenPGP armored private keys (RSA 1024-4096, Ed25519,
   NIST P-256, secp256k1, Curve25519), extract key material (p/q for RSA,
   scalar s for ECC), and load onto the OnlyKey device. Supports auto-slot
   assignment (slot 99) matching the OnlyKey App behavior where signing and
   decryption subkeys are assigned to slots automatically.

2. restore - Parse OnlyKey backup files (base64-encoded with SHA256 hash
   verification), and send restore data to the device in 57-byte chunks
   using the OKRESTORE (0xF1) protocol message. Verifies backup file
   integrity before sending.

3. backuppassphrase - Set the backup encryption passphrase by computing
   its SHA256 hash and storing as a backup decryption key on slot 131
   with type 161 (backup + decryption flags).

All three features are available as both CLI commands (onlykey-cli loadkey,
onlykey-cli restore, onlykey-cli backuppassphrase) and interactive mode
commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port the firmware update feature from the OnlyKey-App to python-onlykey:

- Add OKFWUPDATE (0xF4) message type to Message enum
- Parse signed firmware files (-----BEGIN SIGNED FIRMWARE----- format)
- Transition device from config mode to bootloader via initial dummy packet
- Send firmware blocks in 57-byte chunks with per-chunk acknowledgment
- Wait for NEXT BLOCK between blocks and SUCCESSFULLY LOADED FW on completion
- Handle device reconnection after bootloader reboot
- Add loadfirmware CLI command with safety confirmation prompt
- Works in both command-line and interactive modes

Usage: onlykey-cli loadfirmware <firmware_file>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire onlykey/pqc.py into the CLI: "onlykey-cli setpqc RSA1 <160-byte hex|file>"
loads a composite IETF OpenPGP-PQC seed blob (OKSETPRIV 0x67) into slot 1-4.
Also fix load_composite_key framing: send_message rejects bytes, use bytearray.
- age_plugin: user ECC slots 101-116 (not 133/134), key-type byte, OKSETPRIV
  0xFF keygen, multi-packet decaps, slot validation + hardware-free tests
- client.py: prefer hidraw backend (trustcrypto#89) [surgical — composite PQC work preserved]
- setup.py: enable long_description (markdown), bump 1.2.10 -> 1.2.11; MANIFEST.in
…loadpqc

- onlykey/openpgp_bridge/{bridge.js,openpgp.js}: Node bridge over the modified
  OpenPGP.js (same engine as the web app). Parses composite PQC PGP keys
  (ML-DSA-65 + ML-KEM-768 -> 160-byte OnlyKey blob) AND classic RSA (p/q) / ECC
  (scalar + curve) keys that GnuPG/PGPy can't handle for PQC.
- onlykey/pgp_bridge.py: python subprocess wrapper (needs Node.js).
- client.py: loadkey/loadprivate now parse via the bridge; PGPy fully removed.
- cli.py: new 'loadpqc <keyfile> [RSA1-4] [passphrase]' -> parse -> setpqc.
- setup.py: ship openpgp_bridge/*.js. Removed the PGPy submodule.
Verified: gen->parse round-trip reproduces the 160B blob; RSA/ECC extraction.
Host-side ML-KEM half of the derived X-Wing path (device keeps sk_X; host does
ML-KEM via kyber-py). mlkem_keypair_from_seed / build_recipient /
split_decapsulate. RPID pinned to onlyagent.app so the CLI derives the SAME key
as the web app. kyber-py verified byte-compatible with the web app's @noble.
tests/test_derived_xwing.py: split decaps == standard encaps (4/4).
encode_identity/decode_identity for derived (label) identities so the plugin can
distinguish derived vs slot identities and support both models. 5/5 tests pass.
age-plugin-onlykey now supports BOTH stored (slot) and derived (label) keys.
Derived keys use split custody: OnlyKey returns its X25519 half + an ML-KEM
seed over HID (slot RESERVED_KEY_WEB_DERIVATION, keytype XWING, RPID pinned to
onlyagent.app); the host finishes the ML-KEM half (derived_xwing.py). Same
OnlyKey + same label => same key as the web app, so a file encrypted with age
in the agent decrypts in the web app on the same device.

- onlykey_hid: derive_recipient()/derive_decaps() + derived_label_tag()
- cli: --derived --label mode for generate/recipient/identity; unwrap_callback
  handles derived identities alongside slot identities
- __init__: RESERVED_KEY_WEB_DERIVATION=128

Derived decaps input framing (tag||ct_X = 64B > one report) still to be
validated on hardware. Tests: tests/test_derived_xwing.py 5/5.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants