DEV Community

Arseny Zinchenko
Arseny Zinchenko

Posted on • Originally published at rtfm.co.ua on

Linux: GPG-keys, Pass – passwords manager, and passwords import from a KeePass database

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:

$ sudo apt install pass

For macOS can be installed with Homebrew:

$ brew install pass

The pass itself is just a bash-script:

$ head /usr/bin/pass
# !/usr/bin/env bash
Copyright (C) 2012 - 2018 Jason A. Donenfeld <Jason@zx2c4.com>. 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"

GPG keys management

Creating GPG key

The pass require a GPG-key to encrypt and decrypt files so let’s create it first:

$ 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: example@example.com
Comment:

You selected this USER-ID:
"example <example@example.com>"

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.
...

Then a window will appear asking to set up a password for your GPG-key:

Enter the desired password and finish the key generation:

...
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 <example@example.com>
sub   rsa2048 2019-04-25 [E]

Check public keys in your storage:

$ 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 <linux@dropbox.com>

pub   rsa2048 2011-04-26 [SC]
FCF986EA15E6E293A5644F10B4322F04D67658D8
uid           [ unknown] FFmpeg release signing key <ffmpeg-devel@ffmpeg.org>
sub   rsa2048 2011-04-26 [E]

pub   rsa4096 2018-04-02 [SC]
ABBAD1CB484F53024CF5868B69332F9203F21F5C
uid           [ unknown] Andrew Richards (cancel) <cancel@cancel.fm>
sub   rsa2048 2019-01-28 [S]
sub   rsa4096 2018-04-02 [E]

pub   rsa2048 2019-04-25 [SC]
DEB0D4AD41CC2612B1944D448D22D6610B2F6067
uid           [ultimate] setevoy (my main) <reg@domain.kiev.ua>
sub   rsa2048 2019-04-25 [E]

pub   rsa2048 2019-04-25 [SC]
E130BB49AAA234F2BE2A7F96714F9CBFDA191430
uid           [ultimate] example <example@example.com>
sub   rsa2048 2019-04-25 [E]

And your private keys:

$ gpg --list-secret-keys
/home/setevoy/.gnupg/pubring.kbx
--------------------------------
sec   rsa2048 2019-04-25 [SC]
DEB0D4AD41CC2612B1944D448D22D6610B2F6067
uid           [ultimate] setevoy (my main) <reg@domain.kiev.ua>
ssb   rsa2048 2019-04-25 [E]

Deleting key

To delete a key first need to delete its private part, and after then – its public part.

Remove the private key:

$ 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 <example@example.com>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

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:

$ 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 <example@example.com>

Delete this key from the keyring? (y/N) y

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):

$ 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

Or by exporting private keys to a dedicated storage:

$ gpg --export-secret-keys > ~/Dropbox/Backups/gpg-setevoy-arch-work-secret-backup.gpg

During the export operation – a password will be asked:

Later you can restore keys using the --import option.

Remove an existing key:

$ gpg --delete-secret-key setevoy

And restore it from the backup:


$ gpg --import ~/Dropbox/Backups/gpg-setevoy-arch-work-secret-backup.gpg
gpg: key 8D22D6610B2F6067: "setevoy (my main) <reg@domain.kiev.ua>" 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

Check now:

$ gpg --list-secret-keys
/home/setevoy/.gnupg/pubring.kbx

--------------------------------

sec   rsa2048 2019-04-25 [SC]
DEB0D4AD41CC2612B1944D448D22D6610B2F6067
uid           [ultimate] setevoy (my main) <reg@domain.kiev.ua>
ssb   rsa2048 2019-04-25 [E]

The pass

A database initialization

Initialize new storage using an ID (name) or an email used during GPG-key creation:

$ pass init setevoy

Password store initialized for setevoy

pass will create an identity file ~/.password-store/.gpg-id:

$ cat .password-store/.gpg-id
setevoy

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:

$ git config --global user.email reg@domain.kiev.ua
git config --global user.name "setevoy"

And create local git-repository in your existing pass‘s storage:

$ 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

Now you can check history as in a common Git:

$ cd .password-store/
git log
commit d8f791453fd1e8be7cf6126cde7f32df3bd351cc (HEAD -> master)
Author: setevoy <reg@domain.kiev.ua>
Date:   Thu Apr 25 11:08:19 2019 +0300
Configure git repository for gpg file diff.
commit d49c886510221f31268f22cd74d0859965bafb7b
Author: setevoy <reg@domain.kiev.ua>
Date:   Thu Apr 25 11:08:19 2019 +0300

Add current contents of the password store.

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 git@github.com:setevoy2/pass-example.git:

Go to your local directory:

$ cd ~/.password-store/

Update its repository settings – add remote:

$ git remote add origin git@github.com:setevoy2/pass-example.git

Check it:

$ 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 = git@github.com:setevoy2/pass-example.git
fetch = +refs/heads/*:refs/remotes/origin/*

And push to the Github:

$ git push origin master
To github.com:setevoy2/pass-example.git
* [new branch]      master -> master

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:

$ 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

Retrieve secrets

Now the storage’s structure is like next:

$ pass
Password Store
└── rtfm.co.ua
 └── admin
  └── setevoy

To retrieve a password – specify a path to its file and enter your GPG-key password:

$ pass rtfm.co.ua/admin/setevoy
p@ssw0rd

It can be copied to the clipboard using the -c option:

$ pass -c rtfm.co.ua/admin/setevoy
Copied rtfm.co.ua/admin/setevoy to clipboard. Will clear in 45 seconds.

And git history now:

$ git log
commit 7ae47c9535eabddc64c89df39c7db720a2cd5244 (HEAD -> master)
Author: setevoy <reg@domain.kiev.ua>
Date:   Thu Apr 25 11:12:16 2019 +0300
Add given password for rtfm.co.ua/admin/setevoy to store.
...

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:

$ 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

Check:

$ pass show rtfm.co.ua/admin/setevoy
p@ssw0rd
Username: setevoy
URL: rtfm.co.ua

Looking for records and passwords

For search pass has two options – find, and grep.

find will do fast search by a directories/files names:

$ pass find setevoy
Search Terms: setevoy
├── rtfm.co.ua
 └── admin
  └── setevoy

And grep will search over all files text:

$ pass grep rtfm.
rtfm.co.ua/admin/setevoy:
URL: rtfm.co.ua
...

Removing passwords

Call the pass with the rm option:

$ 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

To delete a directory – use rm -r:

$ 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'
...

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:

$ yaourt -S pass-import

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:

$ 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
...

Check the pass‘s database now:

$ pass
Password Store
├── Main
│   ├── AWS
│   │   ├── AWS root user
│   │   └── AWS setevoy
│   ├── Cards
│   │   ├── Aval Credit
│   │   ├── OtherCards
│   │   │   ├── Masha
│   │   │   ├── Stromenko etabak
...

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:

$ sudo pacman -S qtpass

Run it:

Done.

Similar posts

Top comments (9)

Collapse
 
perrocontodo profile image
David Catanho

Hi. Great post! I've been using pass for a while, as I don't trust my passwords to a third party. I can recommend an Android app that works great with it: play.google.com/store/apps/details...

Collapse
 
tarialfaro profile image
Tari R. Alfaro

Interesting article. What benefits does Pass have over KeePassXC?

Collapse
 
setevoy profile image
Arseny Zinchenko • Edited

Well, actually... Actually - I'd prefer to use KeePassXC as it has better UI.
From the other hand - pass has simple for using CLI (but KeePassXC has keepassxc-cli as well, I just never used it).

Both use the same database mechanism - as a file(s) on a local disk.
Just - KeePass keeps everything in one file while pass keeps all data in a separated dirs/files, so there is less chance it will break everything at the same time.

Also - you can use separated GPG keys to encrypt various pass's files (but again in KeePass(XC) you just can keep different databases with different passwords/keys).

And the built-in Git ability in the pass looks really good (but still - I'm using KeePass with its DB in a Dropbox, so...).

I'd say it's more a matter of taste.
Maybe - pass is more an "oldschool" fashion while KeePassXC is a more modern tool? :-)

P.S. Ah, and there is even WebUI for the pass - github.com/BenoitZugmeyer/pass-web, but it's in Node.js and I didn't trust such a thing, even if run it behind a firewall with HTTPS.

P.P.S keepassxc-cli really simple as well:

$ keepassxc-cli --help
Usage: keepassxc-cli [options] command
KeePassXC command line interface.

Available commands:
add            Add a new entry to a database.
clip           Copy an entry's password to the clipboard.
create         Create a new database.
diceware       Generate a new random diceware passphrase.
edit           Edit an entry.
estimate       Estimate the entropy of a password.
extract        Extract and print the content of a database.
generate       Generate a new random password.
locate         Find entries quickly.
ls             List database entries.
merge          Merge two databases.
rm             Remove an entry from the database.
show           Show an entry's information.
Enter fullscreen mode Exit fullscreen mode
Collapse
 
brixy profile image
Brixy

Thank you very much for your great article.

There is also gopass.

gopass is a rewrite of the pass password manager in Go with the aim of making it cross-platform and adding additional features.

It is actively being developed, you can install it without having Go on your machine, and it is 100% compatible with pass.

Collapse
 
tarialfaro profile image
Tari R. Alfaro • Edited

Yep. I honestly think we as developers and privacy enthusiasts should be moving away from PGP to better tools that implement better UI/UX and newer algorithms. Not to forget, PGP is hard to use. Long live Libsodium!!!

But I agree. KeePassXC has a pretty UI. I think there are many great things about it.

However there are only a couple reasons one might want to not use it.

  • It's slightly harder to use than other password managers, and can be confusing to non-tech savvy people.
  • It's hard to delegate certain accounts to other people.
  • Possibly more likely to be corrupted and unrecoverable. (Just use a stable application and Operating System and everything should be fine)

But other than that, I see no problem with it.

I found a article explaining why they moved from KeePassXC to pass. It was because they liked using the terminal, and apparently they like doing EVERYTHING in a browser and terminal. I guess it isn't really announced that KeePassXC has a CLI tool. At least I didn't notice anything like that on their homepage.

I think KeePassXC is the best desktop password manager.

On a note, I like to sync my database with Syncthing, which you should definitely check out if you are paranoid about having your database in the "cloud".

I will take KeePassXC over any other password manager any day. Even if I have to manually copy accounts over to another database so someone else can use it. The benefits for me are just too great with KeePassXC.

For people using KeePassXC, I recommend that if they have very important credentials on there, like banking stuff, make sure it is a 6-12 random word passphrase. And print a copy of it and store it somewhere safe. That way if the database gets corrupt you can still easily type it in manually.


Edit

KeePassXC is really nice, because you can set it to automatically minimized the window and select the browser's text field and press Ctrl+C and boom, in 0.25 seconds you copy and pasted your password. It's actually really fast and convenient. Which means I am not being driven insane to take 5 seconds to just paste it, no need for browser integrations. FYI, of your password you generated is longer than 75+ characters, DON'T do auto-type. It can be a little glitchy and it takes forever.

Also, does the auto-type feature prevent clipboard/key-loggers from getting the password?

Thread Thread
 
tarialfaro profile image
Tari R. Alfaro

A really good idea would be to create a easy to use Libsodium CLI and GUI, kinda like PGP but based on Libsodium.

Thread Thread
 
setevoy profile image
Arseny Zinchenko • Edited

Wow... Thanks for the Syncthing! It looks great.
I have two computers at home (PC and laptop) and using a bash-script with rsync to synchronize their /home/setevoy directories, but looks like Syncthing can do it much better. Will investigate it on Saturday.

Just not sure yet if it will be good to sync home folders with gigabytes of data.

And looking at this topic - maybe sync home dirs in such a way will be not the best idea)

Thread Thread
 
tarialfaro profile image
Tari R. Alfaro

Yeah, Syncthing is pretty cool. I recommend you back up it before messing around. Not trying to imply that it is not stable.

I will warn you not to sync certain folders/files, there MIGHT be folder/file permission issues, which might screw things up. I do not think it is directly related to Syncthing.

Anyways, yeah. I have not synced large amounts of data. I synced a 32mb veracrypt volume and it seemed fine.

At the very least it is great with small amounts of data, e.g: password database.

let me know how it goes, especially how much it can sync.