Setting up pass on OS X

September 10, 2012

Over the weekend there was a post on Hacker News about Pass, the standard unix password manager now being on Homebrew. I hadn’t heard of pass before, so I did a bit of reading about it. From the announcement post:

Password management should be simple and follow Unix philosophy. With pass, each password lives inside of a gpg encrypted file whose filename is the title of the website or resource that requires the password. These encrypted files may be organized into meaningful folder hierarchies, copied from computer to computer, and, in general, manipulated using standard command line file management utilities.

Basically it is an open source, command line version of 1Password. When I saw it I was pretty excited, as I was thinking of doing something exactly like this the other week. So I tried it out. I checked the source on GitHub and there was a single bash script of a couple of hundred lines, so I was a bit suprised when I installed it:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ brew install pass

</span><span class=‘line’>==> Installing pass dependency: xz </span><span class=‘line’>==> Installing pass dependency: pwgen </span><span class=‘line’>==> Installing pass dependency: tree </span><span class=‘line’>==> Installing pass dependency: libgpg-error </span><span class=‘line’>==> Installing pass dependency: libgcrypt </span><span class=‘line’>(5 minutes later) </span><span class=‘line’>==> Installing pass dependency: libksba </span><span class=‘line’>==> Installing pass dependency: libassuan </span><span class=‘line’>==> Installing pass dependency: pkg-config </span><span class=‘line’>==> Installing pass dependency: pinentry </span><span class=‘line’>==> Installing pass dependency: pth </span><span class=‘line’>==> Installing pass dependency: gpg-agent </span><span class=‘line’>==> Installing pass dependency: dirmngr </span><span class=‘line’>==> Installing pass dependency: libusb </span><span class=‘line’>==> Installing pass dependency: libusb-compat </span><span class=‘line’>==> Installing pass dependency: gnupg2 </span><span class=‘line’>==> Installing pass </span><span class=‘line’>/usr/local/Cellar/pass/1.1.4: 6 files, 52K, built in 2 seconds</span>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Not exactly lightweight… But ok I thought and continued.

To set it up you need to run pass init and pass the ID of a GPG key. I didn’t have GPG setup (brew had only just installed it), but I assumed it would do all the magic for me.

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ pass init "Luca Password Key"

</span><span class=‘line’>Password store initialized for Luca Password Key.</span>

1
2

All good. So I tried generating a key:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ pass generate -c Facebook 16

</span><span class=‘line’>gpg: directory /Users/luca/.gnupg' created &lt;/span>&lt;span class='line'>gpg: new configuration file/Users/luca/.gnupg/gpg.conf’ created </span><span class=‘line’>gpg: WARNING: options in /Users/luca/.gnupg/gpg.conf' are not yet active during this run &lt;/span>&lt;span class='line'>gpg: keyring/Users/luca/.gnupg/secring.gpg’ created </span><span class=‘line’>gpg: keyring `/Users/luca/.gnupg/pubring.gpg’ created </span><span class=‘line’>gpg: Luca Password Key: skipped: No public key </span><span class=‘line’>gpg: [stdin]: encryption failed: No public key </span><span class=‘line’>Copied Facebook to clipboard. Will clear in 45 seconds.</span>

1
2
3
4
5
6
7
8
9

Hmm ok, maybe not. Not a very friendly error. I had a rough idea of what GPG does but I had never used it before. So how does gpg work?

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ gpg

</span><span class=‘line’>zsh: command not found: gpg</span>

1
2

Err? Back to the source, it turns out it runs a command gpg2.

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ gpg2

</span><span class=‘line’>gpg: Go ahead and type your message …</span>

1
2

Hmm. I’m guessing that’s not right. To Google!

I found a blog post, OpenPGP for complete beginners which explained it. It is rather indepth, but if you are interested it is worth a read. Here is what you need to set it up for pass.

First you need to generate a key:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ gpg2 --gen-key

</span><span class=‘line’>gpg (GnuPG) 2.0.19; Copyright © 2012 Free Software Foundation, Inc. </span><span class=‘line’>This is free software: you are free to change and redistribute it. </span><span class=‘line’>There is NO WARRANTY, to the extent permitted by law. </span><span class=‘line’> </span><span class=‘line’>Please select what kind of key you want: </span><span class=‘line’> (1) RSA and RSA (default) </span><span class=‘line’> (2) DSA and Elgamal </span><span class=‘line’> (3) DSA (sign only) </span><span class=‘line’> (4) RSA (sign only) </span><span class=‘line’>Your selection?</span>

1
2
3
4
5
6
7
8
9
10
11

As stated by the article, the defaults are fine, so just press enter. It then asks you for the key length.

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>RSA keys may be between 1024 and 4096 bits long.

</span><span class=‘line’>What keysize do you want? (2048)</span>

1
2

Rather than the default I opted for 4096. There is a warning in the article that it takes longer to generate and encrypt, but as I am only going to be encrypting passwords the trade off is worth it. It then asks how long the key should be valid for:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>Please specify how long the key should be valid.

</span><span class=‘line’> 0 = key does not expire </span><span class=‘line’> <n> = key expires in n days </span><span class=‘line’> <n>w = key expires in n weeks </span><span class=‘line’> <n>m = key expires in n months </span><span class=‘line’> <n>y = key expires in n years </span><span class=‘line’>Key is valid for? (0)</span>

1
2
3
4
5
6
7

For just encrypting passwords locally the default is fine, so just hit enter again. It’ll warn you that it will never expire, so type y to confirm and hit enter.

It’ll then ask you for your name and email. This isn’t really needed for local encryption, but heh, do what it says. At the end you’ll see a prompt to continue:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?&lt;/span></code></pre>
  </td>
</tr>

1

Type o and hit enter to confirm. You’ll then get a prompt for a pass phrase. This will be your master password for all other passwords, so ensure it is strong.

After this it needs a lot of entropy to generate a secure key. Go back to whatever you were doing before this, and check back in a few minutes. When it is done you’ll see something like this:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>gpg: checking the trustdb

</span><span class=‘line’>gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model </span><span class=‘line’>gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u </span><span class=‘line’>pub 4096R/11223344 2009-07-17 </span><span class=‘line’> Key fingerprint = <36-CHARACTER KEY FINGERPRINT> </span><span class=‘line’>uid Real Name (http://example.com/) <name@example.com> </span><span class=‘line’>sub 4096R/55667788 2009-07-17</span>

1
2
3
4
5
6
7

Success! Next back to pass. You need to pass it the key id to initialise it, in this case it is the 8 character ID after the pub section: 11223344

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ pass init 11223344

</span><span class=‘line’>Password store initialized for 11223344.</span>

1
2

If you then try generating a password again you shouldn’t get any errors:

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ pass generate -c Facebook 16

</span><span class=‘line’>Copied Facebook to clipboard. Will clear in 45 seconds.</span>

1
2

Paste it somewhere, then to double check it is working, ask for the password back. It’ll prompt you for the master passphrase you gave to gpg2 when generating your key.

  <td class='code'>
    <pre><code class=''>&lt;span class='line'>$ pass Facebook

</span><span class=‘line’> </span><span class=‘line’>You need a passphrase to unlock the secret key for </span><span class=‘line’>user: “Real Name (http://example.com/) <name@example.com>“ </span><span class=‘line’>4096-bit RSA key, ID 55667788, created 2009-07-17 (main key ID 11223344) </span><span class=‘line’> </span><span class=‘line’>Cahri;x2li-f3Zeo</span>

1
2
3
4
5
6
7

It should match, which means success!