Introduction
passc
is a small CLI tool for storing passwords with demanding encryption, without storing any secret keys on disk. It depends upon libsodium for cryptography and sqlite3 for storage.
Jump to the Usage section for installation & setup.
How it works
passc
derives a crypto_secretbox
key from a chosen master passphrase using crypto_pwhash
. This is used to encrypt passwords for one specific vault. This passphrase is never stored, and neither is the secret key; it is derived every time a password is encrypted/decrypted, which is an intensive process and prevents brute-forcing of the passphrase.
Each vault has a salt which is stored in the ~/.passc/salts
directory. This ensures every user derives a different secret key, even if they use the same passphrase. Salts are stored separate to the database to make them easy to back up.
Even though this passphrase and secret key aren't stored, the secret key is hashed (crypto_pwhash_str
) with a random salt upon creation and stored in the DB. This allows the passphrase to be verified to ensure all passwords in the same vault are encrypted with the same key.
This prevents a user adding a password to a vault with the incorrect passphrase, but does not stop an attacker deleting encrypted passwords manually from the SQLite DB. The salts and database should be backed up constantly.
Usage
You can use a pre-built binary or compile passc
from source. It is currently known to support Linux and macOS systems. Pre-built binaries are available from the Actions page; select the latest build and scroll to the bottom.
If you choose to compile it yourself, you must have SQLite3 installed on your system. Clone the repository and run cmake -B build && cmake --build build
. The resulting binary will be at build/passc
.
Creating a vault
A vault is a place with a unique passphrase used to store passwords. To create a new vault, run any subcommand; in this case we will run the ls
command.
$ passc ls
vault 'main' does not exist. creating...
KEY CREATION: A key will be derived from your given passphrase.
Ensure this is different to those used by other vaults.
OPSLIMIT (moderate):
MEMLIMIT (moderate):
Enter passphrase for vault:
It is highly recommended to skip past the OPSLIMIT and MEMLIMIT questions; these will default to
moderate
if you do not provide a value. Otherwise, it expects an integer. The default parameters require 256MiB of RAM and take about 2 seconds to derive a key with an M3 Pro chip. If you really require your passphrase to be harder to brute-force or have limited RAM, you can increase or decrease these values. See the libsodium docs for more information.
This will create a new vault, 'main', and ask you to specify a passphrase. It will list nothing as there are not yet any passwords in the vault.
To use a different vault name, use the -v
flag, like so:
$ passc -vMyVault <subcommand>
This flag can be used in all of the subcommands below, otherwise defaulting to 'main'. passc
uses GCC-style flags, so spaces are not allowed: -vVault
is correct.
Adding a password
Passwords are identified by their 'reference', like example.org
, and a password ID (PWID). This is generated automatically when you add a password.
Run the following command to add a password for github.com
in the 'main' vault:
$ passc add github.com
Enter passphrase for vault:
OK
Password for 'github.com':
1
There is now a password with reference github.com
and PWID 1
encrypted with the secret key for vault main
.
Getting a password
To retrieve and decrypt a password, use the get
subcommand, for example:
$ passc get github.com
1 | github.com
Enter passphrase for vault:
This will list the passwords in the vault with a reference that contains 'github.com'. If there is only one match, it will be selected. If not, you will be asked to specify which password using the PWID, for example:
$ passc get example
2 | example.org
3 | example.org
4 | example.com
Select password:
This will search the vault for passwords with a reference like example
. Enter the PWID, e.g. 2
, to select the first password for example.org
.
You will then be prompted for the passphrase, and the password will be decrypted.
Listing passwords in a vault
The PWIDs and references of all passwords in a vault can be listed without the passphrase. As shown earlier, you can use the ls
subcommand:
$ passc ls
1 | github.com
2 | example.org
3 | example.org
4 | google.com
This will list all passwords in the 'main' vault.
Deleting a password
The rm
subcommand is used to delete passwords. Note that this asks for a passphrase, but this can provide a false sense of security -- anyone can delete passwords from the database manually if they have access to it.
This command works similarly to the get
command:
$ passc rm github
1 | github.com
Deleting password with PWID 1. If you are unsure which password this is, use the 'get' subcommand to decrypt it before deletion.
Enter passphrase for vault:
This password will then be deleted.
Changing a vault's passphrase
You can rotate the secret key used for a vault with the rotate
command. This requires the current passphrase; it decrypts all passwords and re-encrypts them with a new key. The hash parameters can also be changed in this way.
For example, to change the passphrase of vault 'main':
$ passc rotate
KEY ROTATION: You will be prompted for new vault parameters, then you will be prompted for the current passphrase of vault 'main'. You can then specify a new passphrase for the vault, which will use the parameters specified initially.
OPSLIMIT (moderate):
MEMLIMIT (moderate):
Current --
Enter passphrase for vault:
OK
New --
Enter passphase for vault:
Vault key has been rotated. New keyhash: ...
It is recommended not to change the OPSLIMIT and MEMLIMIT parameters. See creating a vault for more info.
Security features
passc
tries to keep plaintext passwords and secret keys in memory for as little time as possible. Deriving the secret key uses crypto_pwhash_OPSLIMIT_MODERATE
and crypto_pwhash_MEMLIMIT_MODERATE
by default, which requires 256MiB of RAM and takes around 2 seconds on an M3 Pro chip. This can be increased upon creation of a passphrase. To hash the secret key (used for verification), INTERACTIVE
is used. This is much faster.
sodium_mlock
Sensitive data in memory is locked using sodium_mlock
. Some systems do not support this. Enabling verbose logging (-V
) will show whether it is supported. This helps avoid swapping sensitive memory to disk. See libsodium's secure memory docs for more information.
sodium_memzero
is always called regardless of whether sodium_mlock
fails, attempting to overwrite sensitive memory after use.
Key rotation
Keys can be rotated using the rotate
subcommand. This requests the current passphrase used for the vault, derives the vault's secret key, decrypts all passwords and re-encrypts them with a new passphrase. This can be used to change the hash parameters.
Incomplete features
- backup command (
VACUUM INTO
) - vault rename
- web interface