為 Git commit 添加簽名
...大约 3 分钟
1. PGP、OpenPGP、GnuPG 和 gpg
- PGP(Pretty Good Privacy):最初的商業軟件名
- OpenPGP: PGP 標準
- GnuPG(Gnu Privacy Guard):實現了 OpenPGP 的軟件
- gpg:GnuPG 的命令行工具
2. Git 設計的缺陷
Git commit 中的 author 中的user.name
和user.email
可以任意設置,沒有進行任何的校驗。
可以通過filer-branch
批量修改整個 Git 倉庫的歷史:
git commit -am "Destroy production"
git filter-branch --env-filter \
'if [ "$GIT_AUTHOR_EMAIL" = "[email protected]" ]; then
GIT_AUTHOR_EMAIL="[email protected]";
GIT_AUTHOR_NAME="Unsuspecting Victim";
GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all
git push -f
3. 為 Git commit 添加簽名
3.1 作用
- 防止惡意偽造 Git commit,參見震惊!竟然有人在 GitHub 上冒充我的身份!
GitHub 上帶有 Verified 標識,與眾不同
3.2 安裝 gpg
# windows
$ scoop install gpg
# linux 一般自帶
# 沒有的話使用對應的包管理器安裝即可
# arch
$ pacman -S gpg
$ gpg --version
gpg (GnuPG) 2.4.3
libgcrypt 1.10.2
Copyright (C) 2023 g10 Code GmbH
...
3.3 生成 gpg 密鑰對(公鑰和私鑰)
$ gpg --full-generate-key
- 密鑰種類:選擇默認的 RSA 即可
- 密鑰長度:選擇 GitHub 推薦的 4096 bits
- 密鑰過期時間:根據自己的需要選擇
- 輸入用戶名和郵箱
- 設置安全密碼,密碼一定要記住
3.4 查看密鑰
$ gpg --list-secret-keys --keyid-format=long
...
sec rsa4096/24CD550268849CA0 2020-08-29 [SC]
9433E1B6807DE7C15E20DC3B24CD550268849CA0
uid [ultimate] Spencer Woo (My GPG key) <[email protected]>
ssb rsa4096/EB754D2B2409E9FE 2020-08-29 [E]
其中的24CD550268849CA0
就是私鑰的 ID。
3.5 為 Git commit 添加簽名
# 配置 gpg 程序
$ git config --global gpg.program $(which gpg)
# 指定簽名用的密鑰
$ git config --global user.signingkey 24CD550268849CA0
# commit 時自動簽名
$ git config --global commit.gpgsign true
commit 一次,之後查看 git log
$ git log --show-signature
commit 1c4a03ba8a9629d02913406099d03a5ff1aa200d (HEAD -> test)
gpg: Signature made Wed Nov 22 02:39:51 2023 CST
gpg: using RSA key xxx
gpg: Good signature from "xxx" [ultimate]
3.6 導出公鑰並添加到 GitHub 賬戶中
# 獲取私鑰 ID
$ gpg --list-secret-keys --keyid-format=long
...
sec rsa4096/24CD550268849CA0 2020-08-29 [SC]
...
# 生成公鑰
$ gpg --armor --export 24CD550268849CA0
...
將輸出的內容粘貼至 Settings » SSH and GPG keys » New GPG key 。
4. 遷移 gpg key
有時需要在不同的開發環境中使用相同的 gpg 配置,此時就需要進行備份和遷移。
以 Windows 遷移到 ArchLinux 為例。
4.1 導出所需的 key
# 導出密鑰對到文件中
$ gpg --export-secret-keys -a <keyid> > private_key.asc
$ gpg --export -a <keyid> > public_key.asc
4.2 導出 trust db
gpg --export-ownertrust > file.txt
若忽略這一步,在另一環境中,gpg 將提示密鑰 userid 為 unknown 狀態。
4.3 導入 key 和 trust db
# 導入 trust
$ gpg --import-ownertrust < file.txt
# 導入密鑰
gpg --import private_key.asc
gpg --import public_key.asc
4.4 配置 Git
# 指定簽名用的密鑰
$ git config --global user.signingkey <keyid>
# commit 時自動簽名
$ git config --global commit.gpgsign true
若出現了 gpg failed to sign the data
在對應 shell 的 profile 文件中添加(以 zsh 為例):
# ~/.zprofile
export GPG_TTY=$(tty)
參考
Powered by Waline v2.15.2