除了口耳相傳或利用像 1Password 等密碼管理器(password manager)共享帳號、密碼之外,不知道大家是怎麼分享帳號、密碼或是極機密資訊的呢?
本文分享如何透過 gpg (GNU Privacy Guard) 產生公私鑰(public & private key)並對帳號、密碼等機密資訊進行加密,加密後的密文也僅有當初加密時指定的使用者才能解開,藉此增加分享機密資訊時資訊安全程度。
本文環境
- gpg 2.3.3
- macOS
$ brew install gpg
公私鑰加解密原理概要說明
簡單來說,本文用 gpg 達到安全的機密資訊共享的做法,是基於使用非對稱式加密(Asymmetric Encryption)技術。
如果不懂非對稱式加密(Asymmetric Encryption)技術的話,可以參考本章節的概略說明。
首先,非對稱式加密(Asymmetric Encryption)技術中,每個人都會持有一對金鑰,1 把稱為私鑰(private key),另 1 把稱為公鑰(public key) ,這 2 把金鑰的關係是——「用公鑰加密的密文,只能用私鑰解開,用私鑰加密的密文,只能用公鑰解開」,不過一般都是公鑰用以加密、私鑰用以解密。
總之,私鑰必須被安全地保護,不可外洩,如果私鑰外洩,基本上等同此加密已經遭到破解。
公鑰則如其名,可以被公開,任何人都可以用公鑰進行加密後得到密文,而該密文只有持有私鑰的人才能解開。
因此當 2 個人之間,例如下圖中的 A, B,想要建立安全、只有彼此能夠解密的通訊管道時,只需要交換彼此的公鑰:
當某 A 方想傳機密資訊給 B 方時,只要拿 B 方的公鑰進行加密,並將密文(ciphertext) 傳給 B 即可,傳輸過程就算密文遭到攔截,只要沒有 B 的私鑰,該密文也無法被破解。反之,若 B 想傳機密資訊給 A 時,也是拿 A 的公鑰進行加密後,再傳給 A。
建立自己的 GPG 公私鑰(public/private key pair)
如果想建立給自己個人使用的公私鑰,可以輸入以下指令:
$ gpg --full-generate-key
成功執行上述指令之後, gpg 指令會詢問幾項設定,一般按照預設值選即可:
設定都沒問題之後, gpg 會額外詢問是否設定 passphrase 用以保護私鑰,每次需要存取私鑰時,都需要輸入 passphrase 進行確認,避免他人未經允許就存取你的私鑰:
列出私鑰
公私鑰就建立好了之後,可以輸入以下指令列出私鑰:
$ gpg --list-secret-keys --keyid-format=long
上述指令成功之後,會列印出類似以下的文字畫面:
-----------------------------
sec ed25519/F430211DC901AB3F 2022-10-10 [SC]
ECBE16B6E601BE637448CB8FF430211DC901AB3F
uid [ultimate] [email protected]
ssb cv25519/2D8A2EF814046E91 2022-10-10 [E]
sec
代表 secret key
, 也就是主要私鑰(primary private key)的相關資訊。 [SC]
則代表這把私鑰可用於簽署(sign)以及製作憑證(certification)。
uid
代表 user id
, 對應先前輸入的 email 。 [ultimate]
則代表對這個 uid
的信任等級, ultimate
是最高層級的信任等級,通常只有自己個人使用的公私鑰是最高信任等級。
ssb
代表 secret subkey
, 這是 OpenPGP 支援的 subkey 功能。 [E]
則代表這把 secret subkey
用於進行加密。
列出公鑰
公鑰的部分,可以用以下指令列出:
$ gpg --list-keys --keyid-format=long
上述指令執行成功之後,會列出類似以下的畫面,與私鑰的資訊相似:
-----------------------------
pub ed25519/F430211DC901AB3F 2022-10-10 [SC]
ECBE16B6E601BE637448CB8FF430211DC901AB3F
uid [ultimate] [email protected]
sub cv25519/2D8A2EF814046E91 2022-10-10 [E]
pub
代表 public key
, 也就是主要公鑰(primary public key)的相關資訊。
匯出公鑰(public key)
建立個人使用的公私鑰之後,後續仍需要匯出公鑰並傳給其他人使用,如此一來,其他人才能夠使用你所發佈的公鑰加密,該密文是只有你的私鑰才能解開,藉此保證資訊傳輸的安全性:
$ gpg --export -a <uid> > public.key
範例:
$ gpg --export -a "[email protected]" > my_public.key
指定產生公私鑰的演算法
如果想在產生公私鑰時,事先指定產生公私鑰的演算法,可以使用以下指令:
$ gpg --default-new-key-algo <algo name> --generate-key
範例如下,下列指令使用 RSA-4096 演算法產生公私鑰:
$ gpg --default-new-key-algo rsa4096 --generate-key
更新 passphrase
如果想更新 passphrase, 可使用以下指令:
$ gpg --change-passphrase <uid>
例如:
$ gpg --change-passphrase [email protected]
刪除公私鑰
如果要刪除公私鑰,可以使用以下指令,不過這是一個相當危險的指令,如果你已經發布公鑰給其他人使用的話,就要特別小心,刪除公私鑰之後,代表你之後再也無法以原先的私鑰解密先前公鑰加密的內容,強烈建議先備份之後再進行刪除:
$ gpg --delete-secret-and-public-key <uid>
例如:
$ gpg --delete-secret-and-public-key [email protected]
如果要刪除某一把公鑰,可使用以下指令:
$ gpg --delete-keys <uid>
如果要刪除某一把私鑰,則使用以下指令:
$ gpg --delete-secret-keys <uid>
備份私鑰
備份私鑰的指令如下:
$ gpg -o private.gpg --export-options backup --export-secret-keys <uid>
例如:
$ gpg -o private.gpg --export-options backup --export-secret-keys [email protected]
復原 GPG key
備份的私鑰,用以下的指令進行還原:
$ gpg --import-options restore --import private.gpg
還原之後,需要輸入以下指令重新建立對該私鑰的信任等級:
$ gpg --edit-key <uid>
例如:
$ gpg --edit-key [email protected]
上述執行結果如下,可以發現 trust: unknown
,代表該私鑰信任等級未知:
Secret key is available.
gpg: checking the trustdb
gpg: no ultimately trusted keys found
sec ed25519/F430211DC901AB3F
created: 2022-10-10 expires: never usage: SC
trust: unknown validity: unknown
ssb cv25519/2D8A2EF814046E91
created: 2022-10-10 expires: never usage: E
[ unknown] (1). [email protected]
所以最後仍需要輸入指令 trust
,並輸入信任等級 5
提升其信任等級至 ultimate
才算完成:
信任某人
拿到別人發布給你的公鑰(public key)時,需要用以下指令匯入:
$ gpg --import <someone's public key file>
例如:
$ gpg --import ~/Downloads/public.key
同樣地,匯入完成之後,需要用以下指令提升其信任等級:
$ gpg --edit-key <someone's uid>
進入類似以下畫面後,輸入指令 trust
,並視情況輸入合適的信任等級:
加密訊息
有了對方的公鑰之後,就能夠用它進行加密,並傳給對方加密後的檔案。
例如以下檔案,記錄了機密帳密(檔名 password.txt):
username: jay123
password: youneverknow123
接下來,用以下指令進行加密:
$ gpg --encrypt --recipient <someone's email> <file>
例如:
$ gpg --encrypt --recipient [email protected] password.txt
加密成功之後,當前資料夾會多出一個檔案 password.txt.gpg
, 該檔案即是加密後的密文,只要傳給對方,讓對方以其私鑰(private key)解密即可。
截至目前為止加密後的檔案,只有對方的私鑰能解,如果想要彼此都能夠解開該密文,則可以多加一個參數 --recipient
把自己的 uid 也加進去,就能夠以各自的私鑰解開該密文,例如:
$ gpg --encrypt --recipient [email protected] --recipient [email protected] password.txt
如果要一次加密多個檔案,可以將 --encrypt
參數換為 --encrypt-files
, 例如以下指令一次加密 2 個檔案:
$ gpg --encrypt-files --recipient [email protected] password.txt password2.txt
最後,就只要把加密後的檔案傳給對方即可。
解密
收到密文之後,如要解密,則輸入以下指令即可:
$ gpg --decrypt <file>
例如:
$ gpg --decrypt password.txt.gpg
總結
實際上 gpg 的功能遠多過本文所提及的內容,其中還包含簽署(sign)、對稱式加密、與 Key server 互動等等。如有興趣,可以閱讀 man page 學習更多。
以上! Happy Encrypting!
References
https://gnupg.org/
https://wiki.debian.org/Subkeys