Repository navigation
piv: store certificates compressed when they don't fit (CLI + GUI) - #154
Conversation
|
I'd like to note: the ~3kB-ish are YubiKey 5 specific |
|
Thanks, agreed. #154 doesn't assume any size: keyroost never pre-checks a limit. It writes the certificate uncompressed and only compresses it if the card itself refuses it as too large, so a card with a smaller limit is handled the same way. The ~3 KB figure only appears as a YubiKey 5 example in the docs. On the spec: SP 800-73-4 lists 1856 bytes as a recommended certificate length and says certificates can exceed it. A card whose storage is full gets its own "no room left" error rather than a retry. |
94d3d57 to
3460135
Compare
Writing a compressed certificate needs the object's CertInfo byte to say so. encode_certificate now takes a CertInfo (Uncompressed = 0x00, Gzip = 0x01, the two values SP 800-73-4 Part 1 Appendix A defines) instead of hard-coding 0x00. The byte layer still has no compressor: the caller passes the gzip member as the payload. Known-answer tests pin both forms, short and long 0x70 lengths, and the round trip through cert_object_parts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Storing a certificate compressed needs one RFC 1952 member to put in the object. gzip_member sits next to the reader and reuses its CRC-32: a fixed header (no optional fields, MTIME 0, so the same certificate always gives the same bytes), a level-9 DEFLATE body from the miniz_oxide dependency the reader already uses, and the CRC-32 / ISIZE trailer. Tests pin the header and trailer, round-trip through the CRC-checking reader, check determinism, and check a repetitive 6 KB input shrinks well below 3 KB. A member written this way was also confirmed readable by CPython's gzip module and by gzip -t. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Some certificates are larger than a card will take in one object. The PIV standard's answer is the gzip form (CertInfo 0x01), so import_certificate now takes a CertCompression: Auto (the default) stores the certificate uncompressed and, only when the card refuses it as too large, stores it compressed once instead; Always compresses; Never does not. There is no per-device size table: the card's own length refusal is the only signal. The call returns a CertImport saying what was stored, so the CLI and GUI can tell the user when Auto compressed and why. Every compressed write is read back and must return the exact DER that was written, else PivCertReadbackMismatch. A too-large refusal now says whether compression was tried: without it, that storing the certificate compressed may make it fit; with it, both sizes and that it does not fit even compressed. The PUT DATA / chaining body moves unchanged into put_cert_object so both encodings share it, and self_signed_certificate passes the choice on and returns the CertImport with the DER. Slot status gains cert_compressed for a certificate stored gzip-compressed that inflates cleanly (cert_len stays the DER length). The CLI and GUI pass Never for now, keeping today's behaviour until they expose the choice. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
…sign
The CLI now uses the transport's compression choice instead of pinning it
off. With neither flag a certificate is stored uncompressed and, only if
the card refuses it as too large, compressed; --compress always
compresses and --no-compress never does (the two conflict). The help says
what the flags do, that the compressed form is the PIV standard's gzip,
and that some software may not read compressed certificates.
A compressed import adds "(stored compressed: N bytes on the card)" to
the success line. When the automatic choice compressed, a note says it did
not fit uncompressed and that support in the Windows and macOS built-in
PIV support has not been verified. A too-large refusal under
--no-compress also names the flags that would let it fit. piv status
marks a compressed certificate ("stored compressed"), and its --json slot
gains cert_compressed, present only when true. import-cert and self-sign
have no --json output today, so none was added for them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
…dialogs The GUI gets the same choice the CLI has. The Import certificate and Self-signed certificate dialogs gain a Compression dropdown: Automatic (only if too large), the default and reset per dialog; Always; Never. The help under it matches the CLI's: compressed is the PIV standard's gzip form, some software may not read it, and Automatic compresses only when the card refuses the certificate as too large. The notice and the dialog's success detail mirror the CLI output: the stored size when compressed, and the same note when Automatic had to compress (it did not fit uncompressed; support in the Windows and macOS built-in PIV support has not been verified). A too-large refusal with Never set points at the dropdown. The selected slot's state line reads "certificate present (ECC P-256, compressed)" for a compressed certificate; that line's wording moves into a small tested function. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
The Learn page now says what a compressed PIV certificate is (the standard's gzip form, flagged in the object's CertInfo byte), when keyroost writes one (automatically only when the card refuses the certificate as too large, or on request with --compress, never with --no-compress), that the card's refusal is the only size signal and every compressed write is read back, and where the same choice is in the desktop app. A note lists the readers confirmed to handle compressed certificates and states that support in the Windows and macOS built-in PIV support has not been verified. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
…sion notes A tester on Windows 11 (#152) found that Windows' built-in PIV smart-card driver read a certificate keyroost stored compressed. The CLI/GUI note, the Learn page and the changelog now say so; macOS's built-in PIV support stays marked as not verified. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Folds the narrow-window/high-zoom overlap item into it, with the AppImageHub screenshot as the concrete case. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
The AppStream <screenshots> block was a commented-out placeholder pointing at an image that never existed. Enable it with the device-view screenshot the Learn site already hosts (WebP is allowed by AppStream). Software centers reading the Flatpak and AppImage metadata, and AppImage catalogs, can show it from the next release. Fresh screenshots are part of the v0.12.0 design pass (TODO.md). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
The metainfo is the app's store page in software centers and AppImage catalogs, and travels inside the Flatpak and AppImage. Add it to the semantic audit inventory, plus a checklist item: appstreamcli validate, screenshot URLs load and show the current UI, and the summary, description and links match the release. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
One item for all pictures of the app: the Learn site's screenshots and social card, the README (none today), and the metainfo store-page screenshots, retaken from the release build when the GUI changes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
After the rebase onto #128, the Compression label sat outside the label column #128 gives the management-key and PIN rows. Size it to the same column (96px for Import certificate, the measured width for Self-signed). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU
083fc2e to
df8d885
Compare
keyroost can now store a PIV certificate gzip-compressed: the PIV standard's form (CertInfo
0x01, NIST SP 800-73-4 Part 1 Appendix A). This lets certificates too large for a slot fit; the limit is about 3 KB on a YubiKey 5.Behaviour
--compress/--no-compressonpiv import-certandpiv self-signforce it either way.piv statusshows "stored compressed" in text, andcert_compressedin--json. The GUI slot line shows "compressed".docs/piv.htmlgains a "Compressed certificates" section.Implementation
keyroost-piv) gets aCertInfochoice inencode_certificate. It stays compressor-free.CertCompression/CertImportonimport_certificateandself_signed_certificate.Verified on a YubiKey 5.7 (slot 9D)
--no-compress--compressself-sign --compresswith a new keypiv testpassesWindows and macOS: in a community test on Windows 11 (#152), Windows' built-in PIV smart-card driver read a certificate keyroost stored compressed; the YubiKey Minidriver did too. macOS's built-in PIV support has not been verified, and the notes and Learn page say so. Automatic mode only compresses a certificate the card would otherwise refuse, so it cannot break an import that works today.
Checks: fmt, clippy
-D warnings, workspace tests,cargo doc -D warnings, changelog check, docs audit (including the new CLI flags indocs/piv.html).🤖 Generated with Claude Code
https://claude.ai/code/session_01Skvxkb6eMzytjPDmL6mPYU