feat(vault): live TOTP codes from login ciphers#22
Merged
Conversation
A login's stored totp field (otpauth:// URI or bare base32 secret) now yields the current RFC 6238 code instead of the raw secret. - vault-core: new `totp` module — HOTP + RFC 4226 dynamic truncation, hand-rolled base32 decode, otpauth:// parsing; SHA1 default + SHA256/SHA512. One new dep: sha1 (RustCrypto). Error::Totp variant. - vault-agent: get_item(Field::Totp) generates the code from the decrypted secret (the secret stays in the agent; only the code crosses the socket); None still yields NoSuchField. The Copy path inherits it. - vault-tui: `t` copies the current code (beside c/u/o). - vault-cli: FieldArg::Totp already maps; `vault get … --field totp` now prints the live code. Tests: RFC 6238 SHA1 vector + base32 + otpauth parse (vault-core); an agent test that Field::Totp returns a 6-digit code (not the secret). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A Bitwarden login can store a TOTP secret (the
totpfield — anotpauth://URI or a bare base32 secret). Vault already stored/edited it, but reading it
returned the raw secret. Now it returns the live RFC 6238 code:
vault get github --field totp # -> 123456 (rolls over every 30 s)In the TUI,
tcopies the current code for the selected item.How
vault-core::totp(new module): HOTP + RFC 4226 dynamic truncation,hand-rolled RFC 4648 base32 decode,
otpauth://totp/…parsing (honoringalgorithm/digits/period), SHA1 default + SHA256/SHA512. One new dep:sha1(RustCrypto, MIT/Apache — same family as the existingsha2/hmac).New
Error::Totpvariant.vault-agent:get_item(Field::Totp)generates the code from thedecrypted secret — the secret stays in the agent; only the short code
crosses the socket.
Nonestill yieldsNoSuchField. TheCopypathinherits it (so TUI
tworks).vault-tui:t→copy_field(Field::Totp, "TOTP code")besidec/u/o.vault-cli:FieldArg::Totpalready mapped — no code change, the value isnow the live code.
Scope
Standard authenticator secrets only (SHA1/256/512).
otpauth://hotp, Steam, andother non-standard types are rejected; a live ticking readout in the TUI detail
pane and exposing the raw secret are tracked follow-ups.
Tests
vault-core: the RFC 6238 SHA1 vector (T=59→94287082), base32 decode ofthe seed (+ case/space tolerance, error cases), and otpauth-URI vs bare-secret
parsing + digit clamping — all pure/fast.
vault-agent:get_item(Field::Totp)over a known base32 secret returns a6-digit numeric string (and not the raw secret); a missing field →
NoSuchField.Local CI-exact gates all green:
fmt, fresh isolatedclippy -D warnings,cargo test --workspace --all-targetsunderRUSTFLAGS=-D warnings,cargo deny check(newsha1dep — licenses ok), both headless builds.🤖 Generated with Claude Code