Josix is Only Joking

使用 Unix 標準的密碼管理工具 pass (password-store) 管理密碼

March 30, 2021

pass 是什麼?

為了要維持好的安全性,密碼設定時需要有足夠的長度、字母數字隨機混合、定期更換密碼、不要使用固定的密碼。然而隨著使用的軟體服務、註冊的網站越來越多,人類的腦袋難以記住這些又長又複雜還要時常更換的密碼。因此我們需要一個工具來管理這些密碼,常見的工具包含 1PasswordKeePass 等,另外還有這篇文章要介紹的 pass,這是一個符合 Unix 哲學的密碼管理工具,其包含下列特色:

  • 所有的密碼會透過 GPG 加密後以檔案儲存在特定目錄下
  • 密碼儲存路徑及檔名命名自由,可以依照註冊網站或資源的名稱來命名方便查找
  • 因為是檔案,可以複製到不同的設備上,方便搬遷
  • 透過 CLI 操作,自動補全讓查找密碼容易、上手簡單(fish, zsh 也相容)
  • 增刪修改密碼時會透過 git 進行版本控制,分散式儲存
  • 多數裝置可以使用如 android、iOS 設備,基於 Chromium 的瀏覽器、Firefox 等都有擴充工具

pass 會將所有密碼儲存在 ~/.password-store 這個目錄下,並且有簡單的指令介面可以操作該目錄下的所有檔案,檢索密碼時可以透過 pass -c 自動將密碼複製到剪貼簿上並會在特定時間後自動刪除。

安裝 pass

在 MacOS 環境中,安裝 pass 只需要輸入指令 brew install pass 即可,Homebrew 會將相依的 gnupg 、tree 等工具一起安裝好。

其他環境的安裝方式可以參考官方文件

設定 passgnupg

由於 pass 儲存密碼的檔案會經過 gpg 加密過,因此需要先產生 GPG keypair,因為上一步已經安裝好 gnupg ,可以直接透過指令 gpg --full-generate-key 來產生 keypair,求方便可以選擇預設選項(密鑰種類為 RSA 用於加密及簽名、密鑰長度為 3072 bits 、密鑰不會過期)。

$gpg --full-gen-key
gpg (GnuPG) 2.2.26; Copyright (C) 2020 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.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
Requested keysize is 3072 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)
Key does not expire at all
Is this correct? (y/N) y

接者需要輸入使用者資訊如使用者姓名、信箱位置,最終需要設定 passphrase,passphrase 需設定強度高一些並且要記得該設定內容,未來僅會使用 passphrase 來取得儲存於 pass 的密碼,接者可以隨意的動作如打字、用滑鼠等,以生成隨機數:

Real name: testuser
Email address: testuser@example.com
Comment:
You selected this USER-ID:
    "testuser <testuser@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.
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 4033683BFDD66FA1 marked as ultimately trusted
gpg: revocation certificate stored as '/Users/wilson/.gnupg/openpgp-revocs.d/8CCE91BD36D05CE31210F1154033683BFDD66FA1.rev'
public and secret key created and signed.

pub   rsa3072 2021-03-31 [SC]
uid                      testuser <testuser@example.com>
sub   rsa3072 2021-03-31 [E]

其中包含資訊 keyid 4033683BFDD66FA1 為使用者 ID 經過 hash 後產生的字串,後續使用可以用此字串取代輸入使用者 ID。

可以使用 gpg --list-secret-keys --keyid-format LONG 列出已啟用的密鑰及其密鑰 ID,而我們會使用密鑰 ID (範例中為 4033683BFDD66FA1)作為 pass 建立 password store 時需要的參數。

/Users/wilson/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/4033683BFDD66FA1 2021-03-31 [SC]
uid                 [ultimate] testuser <testuser@example.com>
sub   rsa3072/4B11C286610BC41C 2021-03-31 [E]

使用 pass init <gpg-id> 建立 password store

接著透過 pass init <KEYID> 帶入剛剛產生的 Key ID,便可以建立 password store,會在 ~/.password-store 下看到 .gpg-id 檔案,其中內容即為設定的 GPG Key ID。

使用 pass git init 對密碼進行版本控制

若要使用 git 進行版本控制可以輸入 pass git init~/.password-store 目錄下會建立 git repository 並且在 .gitattributes 設定 gpg 副檔名的檔案會用 gpg 解密後再進行 git diff。

若要使用 remote repository 也可以輸入 pass git remote add <name> <url> 加入 remote repo,並可透過 pass git pushpass git pull 更新密碼。

建立 password store git repository 後,pass 會在每次操作自動產生 git commit 記錄每次進行的變更。

pass 基本操作

使用 pass generate <pass-name> 產生密碼

可以透過 pass generate <pass-name> 產生密碼,此指令會透過 /dev/urandom 隨機產生密碼到 <pass-name><pass-name> 是一個檔案路徑,如 pass generate website/facebook.com/user1pass 會自動建立目錄 ~/.password-store/website/facebook.com,並產生密碼文字檔案透過 gpg 加密後放入該目錄下,並也會輸出產生的密碼。

幾個常用的選項和參數如下:

  • 可以透過 pass generate <pass-name> <password length> 指定密碼長度
  • --no-symbols -n, 指定生成的密碼是不會有符號的只包含字母數字
  • --clip -cpass 將生成的密碼直接放入剪貼簿中,並且在 45 秒後自動刪除,並且不會輸出密碼至螢幕
$pass generate test                                                       
[main ab6b2c2] Add generated password for test.
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test.gpg
The generated password for test is:
{t)1`1Sp-A;Qp|}5mI1>jYzf9

$pass generate -n test2                                                 
[main 86bee4a] Add generated password for test2.
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test2.gpg
The generated password for test2 is:
DJ1c1ovit51BYBKb97fLIxxFe

使用 pass insert <pass-name> 新增密碼

新增密碼可以透過指令 pass insert 達成,可以直接輸入想要設定的密碼到 pass-name 中, 也可以透過選項 --multiline 輸入 pass insert --multiline 在儲存的密碼中增加其他的欄位資料如 username, password, PIN, URLs 等,如下方舉例:

Yw|ZSNH!}z"6{ym9pI 
URL: *.amazon.com/*
Username: AmazonianChicken@example.com
Secret Question 1: What is your childhood best friend's most bizarre superhero fantasy? Oh god, Amazon, it's too awful to say...
Phone Support PIN #: 84719

在一些擴充工具中如 browserpass 會辨識其中欄位如 username, password 等帶入至瀏覽器表單自動填入,這些額外的欄位有助於這些工具使用。另外需注意的是多行的輸入模式需要讓第一行是密碼,原因是 pass 使用 --clip -c 參數時只會複製第一行(由於沒有明確的 schema 定義,並且預設每個檔案只會包含密碼)

$pass insert test3
Enter password for test3:
Retype password for test3:
[main aeba54a] Add given password for test3 to store.
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test3.gpg

使用 pass edit <pass-name> 修改密碼

pass 預設會使用 vi 編輯解密後的檔案,並且可以在環境變數中設定 $EDITOR 變數決定想要使用的編輯器。

使用 pass <pass-name>pass show <pass-name> 查看密碼內容

使用 pass <pass-name> 或是 pass show <pass-name> 可以直接得到密碼的內容,若想要直接輸出到剪貼簿可以加入 --clip -c 選項。

$pass test2
DJ1c1ovit51BYBKb97fLIxxFe

$pass -c test2
Copied test2 to clipboard. Will clear in 45 seconds.

使用 pass <subfolder>pass ls <subfolder> 查看已紀錄的密碼

使用 pass <subfolder> 或是 pass ls <subfolder> 可以得到當前設定的密碼檔案的層級狀態,如下:

$pass
Password Store
├── Business
│   ├── some-silly-business-site.com
│   └── another-business-site.net
├── Email
│   ├── donenfeld.com
│   └── zx2c4.com
└── France
    ├── bank
    ├── freebox
    └── mobilephone
    
$pass ls Email
Email
├── donenfeld.com
└── zx2c4.com

使用 pass rm <pass-name> 刪除密碼

使用 pass rm 便可以刪除建立的密碼,如下:

$pass rm test3
Are you sure you would like to delete test3? [y/N] y
/Users/wilson/.password-store/test3.gpg
[main 0d45ec0] Remove test3 from store.
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 test3.gpg

使用 browserpass 在瀏覽器上讀取本地密碼資料

pass 有許多相容的 clients 如 Windows、iOS、Android 等,可以參見這裏browserpass 是 chrome plugin,若要在 MacOS 環境上使用該 plugin 可以參考下方做法:

  1. 為了可以和 browserpass 溝通,首先需要先啟動 browserpass host,可以透過 brew 安裝非正式版:
    $ brew tap amar1729/formulae
    $ brew install browserpass
    $ PREFIX='/usr/local/opt/browserpass' make hosts-chrome-user -f /usr/local/opt/browserpass/lib/browserpass/Makefile
    make 時選擇自己的瀏覽器指令,完成後可以看到會產生一個 symlink,
    /Users/wilson/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.github.browserpass.native.json -> /usr/local/opt/browserpass/lib/browserpass/hosts/chromium/com.github.browserpass.native.json

    小記:由於我換成使用 sidekick,另一個基於 chromium 的瀏覽器,沒有找到 make 符合的子指令,但只要複製該 symlink 到 sidekick 下的相同目錄位置就可以執行了

  2. 安裝 plugin
  3. 為了讓 browserpass 可以和 gpg 溝通,首先需要修改/新增 ~/.gnupg/gpg-agent.conf 加入下列內容:
    # Enables gpg to find gpg-agent (deprecated since version 2.1)
    # use-standard-socket
    3 
    # Connects gpg-agent to the macOS keychain via pinentry-mac from GPGtools. 
    # This allows to trigger pinentry-mac GUI to enter our passphrase when needed 
    # and gpg key's passphrase to be stored in the login keychain, enabling automatic key signing.
    pinentry-program /usr/local/bin/pinentry-mac
    輸入 gpgconf --kill gpg-agnet 重啟 gpg-agent

成功後可以看到下方結果,在符合的網站頁面,browserpass 會跳 badge,選擇符合的 username 後若有定義明確的欄位,該值會被自動帶入至表單之中。

使用 Password StoreOpenKeychain 在 Android 手機上管理密碼

在 Android 上可以使用 Password Store,安裝好 App 後只需要將 remote repo 設定好即可以從遠端拉取 password-store 的密碼資料,另外由於會需要 gpg agent,因此會需要再安裝 OpenKeychain 並將私鑰夠過 gpg --export-secret-keys --armor Uid 輸出,再搬至手機上讓 OpenKeychain 引入使用。

Reference


Josix

Hi, I'm Josix, a software engineer. I love building tools and learning new things. In addition to coding, I enjoy hacking to improve my daily life. For example, I've built knowledge management systems, habit tracking systems, and financial management systems. I'm passionate about using my knowledge and experience to solve problems and make things more convenient, and I always enjoy doing it.

Josix Wang © 2022