pass
– a password manager for Linux/UNIX.
Stores data in tree-based directories/files structure and encrypts files with a GPG-key.
In Arch Linux present by default, in Debian can be installed using apt
from default repositories:
[simterm]
$ sudo apt install pass
[/simterm]
For macOS can be installed with Homebrew:
[simterm]
$ brew install pass
[/simterm]
The pass
itself is just a bash-script:
[simterm]
$ head /usr/bin/pass #!/usr/bin/env bash # Copyright (C) 2012 - 2018 Jason A. Donenfeld <[email protected]>. All Rights Reserved. # This file is licensed under the GPLv2+. Please see COPYING for more information. umask "${PASSWORD_STORE_UMASK:-077}" set -o pipefail GPG_OPTS=( $PASSWORD_STORE_GPG_OPTS "--quiet" "--yes" "--compress-algo=none" "--no-encrypt-to" ) GPG="gpg"
[/simterm]
Contents
GPG keys management
Creating GPG key
The pass
require a GPG-key to encrypt and decrypt files so let’s create it first:
[simterm]
$ gpg --full-gen-key ... Please select what kind of key you want: (1) RSA and RSA (default) // leave default RSA and RSA (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) // leave default 2048 Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) // leave default 0 - valide forever Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: example Email address: [email protected] Comment: You selected this USER-ID: "example <[email protected]>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. ...
[/simterm]
Then a window will appear asking to set up a password for your GPG-key:
Enter the desired password and finish the key generation:
[simterm]
... We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: key 714F9CBFDA191430 marked as ultimately trusted gpg: revocation certificate stored as '/home/setevoy/.gnupg/openpgp-revocs.d/E130BB49AAA234F2BE2A7F96714F9CBFDA191430.rev' public and secret key created and signed. pub rsa2048 2019-04-25 [SC] E130BB49AAA234F2BE2A7F96714F9CBFDA191430 uid example <[email protected]> sub rsa2048 2019-04-25 [E]
[/simterm]
Check public keys in your storage:
[simterm]
$ gpg --list-keys gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u /home/setevoy/.gnupg/pubring.kbx -------------------------------- pub rsa2048 2010-02-11 [SC] 1C61A2656FB57B7E4DE0F4C1FC918B335044912E uid [ unknown] Dropbox Automatic Signing Key <[email protected]> pub rsa2048 2011-04-26 [SC] FCF986EA15E6E293A5644F10B4322F04D67658D8 uid [ unknown] FFmpeg release signing key <[email protected]> sub rsa2048 2011-04-26 [E] pub rsa4096 2018-04-02 [SC] ABBAD1CB484F53024CF5868B69332F9203F21F5C uid [ unknown] Andrew Richards (cancel) <[email protected]> sub rsa2048 2019-01-28 [S] sub rsa4096 2018-04-02 [E] pub rsa2048 2019-04-25 [SC] DEB0D4AD41CC2612B1944D448D22D6610B2F6067 uid [ultimate] setevoy (my main) <[email protected]> sub rsa2048 2019-04-25 [E] pub rsa2048 2019-04-25 [SC] E130BB49AAA234F2BE2A7F96714F9CBFDA191430 uid [ultimate] example <[email protected]> sub rsa2048 2019-04-25 [E]
[/simterm]
And your private keys:
[simterm]
$ gpg --list-secret-keys /home/setevoy/.gnupg/pubring.kbx -------------------------------- sec rsa2048 2019-04-25 [SC] DEB0D4AD41CC2612B1944D448D22D6610B2F6067 uid [ultimate] setevoy (my main) <[email protected]> ssb rsa2048 2019-04-25 [E]
[/simterm]
Deleting key
To delete a key first need to delete its private part, and after then – its public part.
Remove the private key:
[simterm]
$ gpg --delete-secret-key E130BB49AAA234F2BE2A7F96714F9CBFDA191430 gpg (GnuPG) 2.2.15; Copyright (C) 2019 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. sec rsa2048/714F9CBFDA191430 2019-04-25 example <[email protected]> Delete this key from the keyring? (y/N) y This is a secret key! - really delete? (y/N) y
[/simterm]
As an argument to the --delete-secret-key
option a key’s fingerprint or ID (name) can be passed, here it is the “example“.
Now the public key can be removed using the --delete-key
option:
[simterm]
$ gpg --delete-key E130BB49AAA234F2BE2A7F96714F9CBFDA191430 gpg (GnuPG) 2.2.15; Copyright (C) 2019 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. pub rsa2048/714F9CBFDA191430 2019-04-25 example <[email protected]> Delete this key from the keyring? (y/N) y
[/simterm]
Backuping GPG-keys
As this key(s) will be used to decrypt data – we don’t want to lose it.
You can create a backup just by copying the whole ~/.gnupg
directory (in case if GnuPG package is used):
[simterm]
$ ll .gnupg/ total 52 drwx------ 2 setevoy setevoy 4096 Jan 22 12:44 crls.d drwx------ 2 setevoy setevoy 4096 Apr 25 10:04 openpgp-revocs.d drwx------ 2 setevoy setevoy 4096 Apr 25 10:11 private-keys-v1.d -rw-r--r-- 1 setevoy setevoy 13732 Apr 25 10:14 pubring.kbx -rw-r--r-- 1 setevoy setevoy 12317 Apr 25 09:58 pubring.kbx~ -rw-r----- 1 setevoy setevoy 676 Apr 25 09:54 sshcontrol -rw------- 1 setevoy setevoy 1440 Apr 25 10:14 trustdb.gpg
[/simterm]
Or by exporting private keys to a dedicated storage:
[simterm]
$ gpg --export-secret-keys > ~/Dropbox/Backups/gpg-setevoy-arch-work-secret-backup.gpg
[/simterm]
During the export operation – a password will be asked:
Later you can restore keys using the --import
option.
Remove an existing key:
[simterm]
$ gpg --delete-secret-key setevoy
[/simterm]
And restore it from the backup:
$ gpg --import ~/Dropbox/Backups/gpg-setevoy-arch-work-secret-backup.gpg gpg: key 8D22D6610B2F6067: "setevoy (my main) <[email protected]>" not changed gpg: key 8D22D6610B2F6067: secret key imported gpg: Total number processed: 1 gpg: unchanged: 1 gpg: secret keys read: 1 gpg: secret keys imported: 1
[/simterm]
Check now:
[simterm]
$ gpg --list-secret-keys /home/setevoy/.gnupg/pubring.kbx -------------------------------- sec rsa2048 2019-04-25 [SC] DEB0D4AD41CC2612B1944D448D22D6610B2F6067 uid [ultimate] setevoy (my main) <[email protected]> ssb rsa2048 2019-04-25 [E]
[/simterm]
pass
A database initialization
Initialize new storage using an ID (name) or an email used during GPG-key creation:
[simterm]
$ pass init setevoy Password store initialized for setevoy
[/simterm]
pass
will create an identity file ~/.password-store/.gpg-id
:
[simterm]
$ cat .password-store/.gpg-id setevoy
[/simterm]
pass
Git and Github
Besides a usual local storage pass
can keep it as a git-repository with all changes history.
If you didn’t make global Git settings – add them now:
[simterm]
$ git config --global user.email [email protected] $ git config --global user.name "setevoy"
[/simterm]
And create local git-repository in your existing pass
‘s storage:
[simterm]
$ pass git init Initialized empty Git repository in /home/setevoy/.password-store/.git/ [master (root-commit) 7e19ab0] Add current contents of password store. 1 file changed, 1 insertion(+) create mode 100644 .gpg-id [master 19aaf2c] Configure git repository for gpg file diff. 1 file changed, 1 insertion(+) create mode 100644 .gitattributes
[/simterm]
Now you can check history as in a common Git:
[simterm]
$ cd .password-store/ $ git log commit d8f791453fd1e8be7cf6126cde7f32df3bd351cc (HEAD -> master) Author: setevoy <[email protected]> Date: Thu Apr 25 11:08:19 2019 +0300 Configure git repository for gpg file diff. commit d49c886510221f31268f22cd74d0859965bafb7b Author: setevoy <[email protected]> Date: Thu Apr 25 11:08:19 2019 +0300 Add current contents of password store.
[/simterm]
Then you can create a private repository in Github or Bitbucket and import your pass
‘s database there to synchronize it between multitype computers.
Although the idea to keep all your passwords in an even private repository, even in a GPG-encrypted file maybe not too good.
Another solution could be to create own git-server and use it.
Still, just for example – let’s create a private Github repository:
Copy its address, here it is the [email protected]:setevoy2/pass-example.git:
Go to your local directory:
[simterm]
$ cd ~/.password-store/
[/simterm]
Update its repository settings – add remote
:
[simterm]
$ git remote add origin [email protected]:setevoy2/pass-example.git
[/simterm]
Check it:
[simterm]
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [diff "gpg"] binary = true textconv = gpg2 -d --quiet --yes --compress-algo=none --no-encrypt-to --batch --use-agent [remote "origin"] url = [email protected]:setevoy2/pass-example.git fetch = +refs/heads/*:refs/remotes/origin/*
[/simterm]
And push to the Github:
[simterm]
$ git push origin master ... To github.com:setevoy2/pass-example.git * [new branch] master -> master
[/simterm]
Check:
Adding passwords
To add a new password use insert
with a path to dirs/file:
For example, a password for the RTFM could be added like this:
[simterm]
$ pass insert rtfm.co.ua/admin/setevoy mkdir: created directory '/home/setevoy/.password-store/rtfm.co.ua' mkdir: created directory '/home/setevoy/.password-store/rtfm.co.ua/admin' Enter password for rtfm.co.ua/admin/setevoy: Retype password for rtfm.co.ua/admin/setevoy: [master 7ae47c9] Add given password for rtfm.co.ua/admin/setevoy to store. 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rtfm.co.ua/admin/setevoy.gpg
[/simterm]
Retrieve secrets
Now the storage’s structure is like next:
[simterm]
$ pass Password Store └── rtfm.co.ua └── admin └── setevoy
[/simterm]
To retrieve a password – specify a pass to its file and enter your GPG-key password:
[simterm]
$ pass rtfm.co.ua/admin/setevoy p@ssw0rd
It can be copied to the clipboard using the -c
option:
[simterm]
$ pass -c rtfm.co.ua/admin/setevoy Copied rtfm.co.ua/admin/setevoy to clipboard. Will clear in 45 seconds.
[/simterm]
And git
history now:
[simterm]
$ git log commit 7ae47c9535eabddc64c89df39c7db720a2cd5244 (HEAD -> master) Author: setevoy <[email protected]> Date: Thu Apr 25 11:12:16 2019 +0300 Add given password for rtfm.co.ua/admin/setevoy to store. ...
[/simterm]
Multiline records
Instead of adding just a password you can specify some additional fields.
To add multitype lines to your password’s file use-m
. Set a password itself in the first line: -c
will use it to copy a password to the buffer:
[simterm]
$ pass insert -m rtfm.co.ua/admin/setevoy An entry already exists for rtfm.co.ua/admin/setevoy. Overwrite it? [y/N] y Enter contents of rtfm.co.ua/admin/setevoy and press Ctrl+D when finished: p@ssw0rd Username: setevoy URL: rtfm.co.ua [master fc43a4c] Add given password for rtfm.co.ua/admin/setevoy to store. 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rtfm.co.ua/admin/setevoy.gpg
[/simterm]
Check:
[simterm]
$ pass show rtfm.co.ua/admin/setevoy p@ssw0rd Username: setevoy URL: rtfm.co.ua
[/simterm]
Looking for records and passwords
For search pass
has two options – find
, and grep
.
find
will do fast search by a directories/files names:
[simterm]
$ pass find setevoy Search Terms: setevoy ├── rtfm.co.ua └── admin └── setevoy
[/simterm]
And grep
will search over all files text:
[simterm]
$ pass grep rtfm. rtfm.co.ua/admin/setevoy: URL: rtfm.co.ua ...
Removing passwords
Call the pass
with the rm
option:
[simterm]
$ pass rm rtfm.co.ua/admin/setevoy Are you sure you would like to delete rtfm.co.ua/admin/setevoy? [y/N] y removed '/home/setevoy/.password-store/rtfm.co.ua/admin/setevoy.gpg' [master 7a23ede] Remove rtfm.co.ua/admin/setevoy from store. 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 rtfm.co.ua/admin/setevoy.gpg
[/simterm]
To delete a directory – use rm -r
:
[simterm]
$ pass rm -r Main Are you sure you would like to delete Main? [y/N] y removed '/home/setevoy/.password-store/Main/Work/blabla.com.gpg' ...
[/simterm]
Import from a KeePass database
Actually, I’m using pass
as a backup storage.
In general, I’m using KeePass (KeePassXC), its database is stored in a Dropbox account and synchronize KeePass’s instances between multiple computers.
In case if this database will break somewhen – I want to have its backup, so let’s import it to the pass
.
Here the pass-import
utility can be used which can import data from various managers and a KeePass’s XML-file.
it can be installed on Arch Linux from AUR:
[simterm]
$ yaourt -S pass-import
[/simterm]
Now create a database’s copy (using KeePass – KeePassXC can’t import to XML):
And run an import to the pass
‘s storage passing a source type (here – keepass) and a path to the file:
[simterm]
$ pass import keepass ~/Backups/KeePassBKP/KeePass-Main-25-04-2019-bkp.xml (*) Importing passwords from keepass . File: /home/setevoy/Backups/KeePassBKP/KeePass-Main-25-04-2019-bkp.xml . Number of password imported: 294 . Passwords imported: Main/AWS/AWS root user Main/AWS/AWS setevoy Main/Cards/Aval Credit ...
[/simterm]
Check the pass
‘s database now:
[simterm]
$ pass Password Store ├── Main │ ├── AWS │ │ ├── AWS root user │ │ └── AWS setevoy │ ├── Cards │ │ ├── Aval Credit │ │ ├── OtherCards │ │ │ ├── Masha │ │ │ ├── Stromenko etabak ...
[/simterm]
QtPass
The terminal is awesome but can be better to work using some UI.
For the pass
there is the QtPass utility.
In Arch Linux can be installed from the common repository:
[simterm]
$ sudo pacman -S qtpass
[/simterm]
Run it:
Done.