為 Git commit 添加簽名

Kesa...大约 3 分钟Git

1. PGP、OpenPGP、GnuPG 和 gpg

  • PGP(Pretty Good Privacy):最初的商業軟件名
  • OpenPGP: PGP 標準
  • GnuPG(Gnu Privacy Guard):實現了 OpenPGP 的軟件
  • gpg:GnuPG 的命令行工具

2. Git 設計的缺陷

Git commit 中的 author 中的user.nameuser.email可以任意設置,沒有進行任何的校驗。

可以通過filer-branch批量修改整個 Git 倉庫的歷史:

git commit -am "Destroy production"
git filter-branch --env-filter \
  'if [ "$GIT_AUTHOR_EMAIL" = "iamthe@evilguy.com" ]; then
     GIT_AUTHOR_EMAIL="unsuspecting@victim.com";
     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 作用

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) <my@email.com>
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 keyopen in new window

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)

參考

  1. https://en.wikipedia.org/wiki/Pretty_Good_Privacyopen in new window
  2. 用更现代的方法使用PGPopen in new window
  3. 震惊!竟然有人在 GitHub 上冒充我的身份! open in new window
  4. 迁移 GPG 密钥open in new window
  5. How to migrate GPG trust database from one machine to another?open in new window
  6. Managing commit signature verificationopen in new window
上次编辑于:
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.2