sefy 0.17.0

An inconspicuous encrypted store for notes, credentials and files
sefy-0.17.0 is not a library.

An encrypted store for notes, credentials and files that does not announce itself: one file with no header, no extension it must keep, and no name that gives it away.

Every way of storing secrets announces itself. A .kdbx file says "password database". age and gpg write a header. VeraCrypt wants a container and a mount. Whoever looks at your disk, your backup drive or your cloud folder can tell exactly where the interesting file is.

sefy is a secret store whose file looks like nothing. Notes, logins, cards, ssh keys and files live in an encrypted SQLite database sealed into a single blob with no magic bytes, no header and no extension convention. Call it notes.bak, leave it among your other backups, and there is nothing to notice.

$ head -c 32 notes.bak | xxd
00000000: 65b0 1375 a933 361d 89e2 9338 1b8d cb76  e..u.36....8...v
00000010: 0749 7515 ad12 dd40 1c3e 3e93 9282 4b5a  .Iu....@.>>...KZ

Threat model, honestly

  • Protects against: a passing glance, a curious file listing, a cloud-side scanner looking for known formats, anyone who does not already know the file is a vault.
  • Does not protect against: forensic analysis - a high-entropy headerless file is recognizable as some container to an examiner - or anyone who can compel you to give up the password.

sefy is inconspicuous, not deniable, and it will not pretend otherwise.

A day with it

Point sefy at a file. There is no default location: a vault at a predictable path would undo the whole point.

$ export SEFY_VAULT=~/backups/notes.bak

$ sefy init
Master password:
created /home/you/backups/notes.bak

Put things in - notes, logins, cards, ssh keys, and files kept byte for byte:

$ sefy add note "bank card" --text "PIN 4815" --tag money
added "bank card" as 1

$ sefy add login mail --login someone@example.com --url https://mail.example.com --tag mail
Password for this item:
added "mail" as 2

$ sefy add file ~/.ssh/id_ed25519 --tag keys
added "id_ed25519" as 3

Bare sefy opens a picker over everything in the vault:

$ sefy
? Item >
> bank card   note   [money]
  mail        login  [mail]
  id_ed25519  file   [keys]

Take a secret out. It goes to the clipboard and is taken back off after 45 seconds - and only if the secret is still what is sitting there, so anything you copied meanwhile is left alone.

$ sefy get mail
copied password of "mail" to the clipboard; clearing in 45s
clipboard cleared

A new account needs a new password, and sefy gen makes one and keeps it in the same breath - stored as a login, then put on the clipboard for the sign-up form:

$ sefy gen --save forum --login someone@example.com --url https://forum.example.com
added "forum" as 4
generated 20 characters: 130 bits of entropy, strength 4/4
copied it to the clipboard; clearing in 45s

Items are addressed by title, id or text to search for, and sefy lists what the words could mean rather than guessing. sefy open loads the site with the password on the clipboard, sefy fill passes login, password and one-time code one Enter at a time, sefy sync carries the vault through a transport, and sefy status says what you hold without saying what is in it.

Every command, with its flags: the reference.

What you get

  • A file that looks like nothing. No magic bytes, no header, no extension convention - salt and nonce fresh on every save, so two saves of identical content share no prefix.
  • Notes, logins, cards, ssh keys, Wi-Fi networks, API tokens, bank accounts and files in one vault, tagged and searchable, with files kept byte for byte.
  • Passwords made where they are kept. sefy gen draws random characters, pronounceable ones or a diceware passphrase (English or Russian lists built in), reports its exact entropy beside an offline zxcvbn score, and can save the result as a login in the same command.
  • Two-factor sign-in built in. sefy otp turns the key a site shows into the one-time code, and sefy fill hands over login, password and code one Enter at a time.
  • Tokens for scripts without a .env file. sefy run -e TOKEN=github -- ./deploy.sh puts the secret in the environment of that one command - not in a file, the shell history or a process listing.
  • Transports, not lock-in. sefy sync carries the vault through a sefy-plugin-* executable - github and sftp ship today - and folds what comes back in without a credential ever passing through the transport.
  • Every value keeps its past. An edit keeps what it replaced; sefy history shows how each version differs without printing a secret, and sefy restore brings one back - whole, or one field.
  • Merge instead of overwrite. Where two copies both changed an item, the newer is current and the other waits in its history rather than being dropped on a timestamp.
  • Sync without surprises. --dry-run names every item a sync would touch before it touches one, SEFY_AUTO_SYNC=on syncs after every change, a merge keeps the vault as it was beside it first, and sefy doctor checks the vault, the transport and the clipboard on this machine.
  • An audit that stays home. sefy audit names weak, reused and year-old passwords, the card or token kept twice, and every record past or near its expires date - worked out offline, without showing a value.
  • A vault that is never a trap. import reads KeePass, Bitwarden and browser exports, history included; export writes sefy JSON, KeePass XML or CSV - in the clear only after you say so explicitly.
  • An end, when one is needed. sefy wipe overwrites the vault, the copies beside it and any unfinished save with random bytes and deletes them, once you type the vault's name back - there is no --yes.

Install

One-line installers. Windows (PowerShell):

irm https://raw.githubusercontent.com/lacodda/sefy/main/tools/install.ps1 | iex

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/lacodda/sefy/main/tools/install.sh | sh

On Windows use the PowerShell line above: install.sh carries the macOS and Linux builds only, and run from Git Bash it stops with a pointer back here.

cargo - cargo install sefy, plus cargo install sefy-plugin-github or sefy-plugin-sftp for a transport

npm - npm install -g sefy-cli

Binary releases - grab the archive for your platform from Releases (Windows x86_64, Linux x86_64, macOS arm64), unpack and put sefy on your PATH.

Both installers take the newest release by default; set SEFY_VERSION to a tag to pin one, and SEFY_INSTALL_DIR to choose where the binary lands. They also place any transport the archive carries into sefy's plugins directory, so sefy plugin list finds it without a second step.

Shell completions: sefy completions bash (also zsh, fish, powershell, elvish).

Documentation

Full command reference, concepts and guides: lacodda.github.io/sefy - including how the vault works and the plugin reference for transports.

Status

v0.17.0, in daily use. The vault file format is stable at version 1 and the plugin protocol at version 1 since 0.3.0; the database schema inside the ciphertext moves between releases, and older builds keep reading a vault safely even when they cannot see everything in it - see versions and compatibility. A desktop app over the same core is being built and is not released yet. What landed in each version: CHANGELOG.

Contributing

Building the workspace, repository layout and commit conventions: CONTRIBUTING.md.

License

MIT (c) Kirill Lakhtachev