Decode an OpenSSH SHA256:<base64> fingerprint string into its raw
hash bytes. OpenSSH emits unpadded base64 with potentially non-zero
trailing bits (synthetic fingerprints from demo fixtures sometimes
fall in this bucket), so we configure a lenient engine that accepts
both padded and unpadded input. Returns None when the SHA256:
prefix is missing or the body is not decodable.
Generate the Drunken Bishop visit grid from a fingerprint. Mirrors the
key_fingerprint_randomart walk in OpenSSH sshkey.c: starting at
the grid centre, the bishop steps diagonally based on 2-bit pairs read
LSB-first from each fingerprint byte. Each visited cell increments its
counter (capped so unique cells stay distinguishable), and the start
and end positions are tagged with S and E markers.
Indices into keys whose name or comment contains query
(case-insensitive substring). Returns all indices when the query is
empty or None, so callers can render the unfiltered list using the
same code path. Pure function so the search handler can call it
repeatedly per keystroke without touching the App.
Translate a UI-space selection index into an app.keys.list index,
honoring an active search filter. Returns None when the selection
is out of range for the current filter. Centralised here so every
call site (copy, push, detail-pane render) maps selection back to
app.keys.list through one code path; a divergent implementation in any
of them would silently point at the wrong key.
Resolve the SSH directory to scan for keys. Honours a thread-local
override set by tests; falls back to ~/.ssh in production. Returns
None when the home directory cannot be determined and no override
is set, so callers can short-circuit cleanly.