Skip to content

Request for feedback: Proposal Implementation for PIN feature #297

@antotocar34

Description

@antotocar34

Hello there, I would like to implement a PIN feature. I would like to write here the motivation, implementation details and potential problems / design choices to make. As well as get some feedback and discussion going.

Motivation

Since you can use rbw as an ssh-agent, it’s very convenient to use it for SSH keys. However, typing my long master password every time I push a local repository is inconvenient.
I’d like to let users configure a short (but still secure) PIN for convenience and security 1
We could even leverage the age plugin ecosystem so that the vault can be unlocked using a hardware key or macOS Touch ID via an age plugin.

Design

dek - master symmetric key which decrypts the contents of your vault. Held in memory by the rbw-agent
local_secret - 32-byte secret persisted via a backend
backend - either encrypt local_secret to disk with age (and bound to device via a plugin) or simply in the os keyring.
PIN - arbitrary length user inputted string
kek - key derived from PIN and local_secret with kdf (argon2id)
wrapped_dek - dek wrapped with the kek
pin_state - [wrapped_dek+nonce, salt+argon2params for derivingkek, backend] serialized to disk

The cli api will expose three commands
rbw pin set

  • Generates and stores local_secret via backend.
  • Prompts user for a PIN (with confirmation).
  • Wraps dekwrapped_dek and writes pin_state.

rbw pin status

  • Shows whether pin_state exists, and which backend is used (age / keyring).

rbw pin clear

  • Deletes pin_state and local_secret.

At rbw unlock, we simply check that a pin_state exists in the actions::unlock_state function, ask for pin, decrypt and store the decrypted dek to the agent's state.

Considerations

  • I do not think an expiry time / limited tries is worth implementing given that these are all defeated by rolling back pin_state.
  • An attacker who can run arbitrary commands could brute force a short pin very quickly, assuming the backend (e.g keyring) is unlocked. Doesn't apply to hardware key style age plugins.
  • If the user rotates their keys and syncs the local database, the pin becomes invalid. A potential solution would be to keep a hash of the dek in pin_state and clear the pin if the rotated hash doesn't match.
  • If the user stores the local secret with age-plugin-yubikey, we can allow them to use an empty pin for maximum convenience.
  • insert obvious security flaw I have missed here

Footnotes

  1. A short pin / touchid on mac would make it painless to have a very short/instant locking time on the rbw-agent, keeping the dek in memory for as short a time as possible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions