前言
不管是在GitHub或是GitLab網站上,都會看到每個commit資訊,這些commit資訊會顯示「unverified」的時候,像是下列的圖示:
為什麼Commit會顯示「Unverified」呢?原因是該Commit並沒有建立GPG sign簽章而導致該Commit顯示未經過認證,有認證過的Commit有什麼好處?可以讓人有個保證,有簽章過的Commit較為安全,未簽章過的會讓人覺得有偽造的嫌疑。在本文章中,會以GitHub為例,演示該如何針對一個使用者進行設定GPG commit,以及產生GPG金鑰的方法與相關的步驟。
前置條件
首先,要有GPG的指令可以使用,在Windows底下可以安裝Git for Windows進行使;用Linux相關的作業系統則已經有gpg的指令可以使用了。下列是有關於Windows上安裝Git for Windows與Linux作業系統上檢查gpg指令的方法:
# 在Windows上(Git for Windows) peter@ideapad-peterli MINGW64 ~/Downloads $ gpg --version gpg (GnuPG) 2.2.41-unknown libgcrypt 1.9.4-unknown Copyright (C) 2022 g10 Code GmbH License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Home: /c/Users/peter/.gnupg Supported algorithms: Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256 Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224 Compression: Uncompressed, ZIP, ZLIB, BZIP2 # 在Linux作業系統上,以Ubuntu發行版本為例 peter@ideapad-peterli:~$ gpg --version gpg (GnuPG) 2.2.4 libgcrypt 1.8.1 Copyright (C) 2017 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Home: /home/peter/.gnupg Supported algorithms: Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256 Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224 Compression: Uncompressed, ZIP, ZLIB, BZIP2
產生GPG金鑰
接下來可以使用下列的指令進行產生GPG金鑰以及相關輸出執行後的訊息,產生的時候會將公鑰與私鑰一併進行產生:
gpg --full-generate-key gpg (GnuPG) 2.2.4; Copyright (C) 2017 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. gpg: keybox '/home/peter/.gnupg/pubring.kbx' created 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) Your selection? 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 GnuPG needs to construct a user ID to identify your key. Real name: peter279k Email address: peter279k@gmail.com Comment: You selected this USER-ID: "peter279k <peter279k@gmail.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: /home/peter/.gnupg/trustdb.gpg: trustdb created gpg: key 180E78DA37B1ABDE marked as ultimately trusted gpg: directory '/home/peter/.gnupg/openpgp-revocs.d' created gpg: revocation certificate stored as '/home/peter/.gnupg/openpgp-revocs.d/4569E017DF5889475A5959A6180E78DA37B1ABDE.rev' public and secret key created and signed. pub rsa3072 2023-11-12 [SC] 4569E017DF5889475A5959A6180E78DA37B1ABDE uid peter279k <peter279k@gmail.com> sub rsa3072 2023-11-12 [E]
從上述的執行指令訊息,有幾個重點如下:
- 選用什麼演算法來產生公私鑰,這邊可以使用預設RSA演算法來進行產生。
- 產生RSA金鑰長度要多少bits?預設是3072,也可以使用預設值是可以的。
- 「Key is valid for? (0)」產生的金鑰不會過期。
- 接下來會問你是否正確,就輸入「y」來進行下一步。
- 接下來分別輸入「Real name」、「Email address」以及「Comment」,Comment可以是空白。
- 接下來會問是否設定正確?確定正確訊息之後,則可以輸入「O」來進行下一步。
- 接著會跳出下列的訊息對話框,提示需要輸入金鑰的passphrase來進行保護,相關圖片如下:
- 上述的步驟會重複兩次,這邊會建議不設定passphrase是因為,假設儲存在電腦上是安全的,且有可能有忘記passphrase的風險,因此這邊以空白為主,並按下「enter」鍵。
產生完成之後,會顯示相關的訊息出來,以及說明公私鑰儲存在哪裡以及公鑰之內容。
接下來,為了要讓Git指令在使用git commit指令時可以去使用GPG金鑰進行簽章,則需要使用下列的指令來進行設定:
git config --global commit.gpgSign true git config --global user.signingKey signed_key
從上述執行的指令可以知道,第一行代表的是設定GPG簽章為true,第二行是設定簽章的金鑰是哪一個。
「signed_key」要替換成自己產生的key,輸出自己的Key方式如下:
$ gpg --list-secret-keys --keyid-format=long gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u /home/peter/.gnupg/pubring.kbx ------------------------------ sec rsa3072/180E78DA37B1ABDE 2023-11-12 [SC] 4569E017DF5889475A5959A6180E78DA37B1ABDE uid [ultimate] peter279k <peter279k@gmail.com> ssb rsa3072/9619458E50C86AD1 2023-11-12 [E]
從上述的輸出訊息可以知道,「4569E017DF5889475A5959A6180E78DA37B1ABDE」就是私鑰。
於是執行「git config –global user.signingKey 4569E017DF5889475A5959A6180E78DA37B1ABDE」指令進行設定。
接著要讓GitHub知道這是簽章過的Commit,因此需要將上面產生的GPG公鑰上傳到我們GitHub帳號中,可以透過下列的指令來輸出公鑰的資訊:
gpg --output public.pgp --armor --export peter279k@gmail.com
從上述的指令可以知道,指定上面產生GPG的那個信箱,並把輸出的公鑰資訊儲存到「public.pgp」檔案中,「–armor」參數是產生ASCII格式的公鑰輸出訊息。
我們用cat指令就可以把上述的檔案進行輸出:
$ cat public.pgp -----BEGIN PGP PUBLIC KEY BLOCK----- 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 lQwJ6FPQa+D5VSc= =VkgQ -----END PGP PUBLIC KEY BLOCK-----
輸出的這一段就可以貼到GitHub帳號設定裡面,記得進到帳戶設定選擇「SSH and GPG Keys」並按下「New GPG Keys」,接著就可以設定該公鑰名稱以及公鑰內容了,相關的截圖如下:
在新增之後,會需要對帳號進行二次確認, 對帳號輸入密碼之後,該GPG金鑰就會設定進去了。
設定好之後,在設定GPG金鑰的那台機器上就可以產生出Verified的有經過GPG簽章過的Commit了。
故障排除
若是在git commit的指令時候,出現下列的訊息:
gpg: skipped "peter279k <peter279k@gmail.com>": No secret key gpg: signing failed: No secret key error: gpg failed to sign the data fatal: failed to write commit object
則是代表說「git config –global user.signingKey」指令沒有設定成功,則需要進行正確的設定。
並確定該GPG公鑰有上傳到指定的GitHub帳號中。
若是執行指令的環境無法有互動模式的話,則可以使用無互動的方式去執行gpg的指令,相關的指令執行方式如下:
<pre>#!/bin//bash gpg --full-generate-key --batch <(echo "Key-Type: 1"; \ echo "Key-Length: 4096"; \ echo "Subkey-Type: 1"; \ echo "Subkey-Length: 4096"; \ echo "Expire-Date: 0"; \ echo "Name-Real: peter279k"; \ echo "Name-Email: peter279k@gmail.com"; \ echo "%no-protection"; )</pre>
備註
上述的GPG公鑰與私鑰將不會真的拿來設定與使用,在這篇文章完成之後,該GPG金鑰就會從產生的機器上刪除,並透過下列的指令進行刪除:
$ gpg --delete-secret-keys peter279k@gmail.com $ gpg --delete-keys peter279k@gmail.com
從上述指令得知,就是分別刪除指定信箱的GPG私鑰與公鑰,有順序之分,需要先刪除GPG私鑰再刪除公鑰。
參考資料
- https://gist.github.com/paolocarrasco/18ca8fe6e63490ae1be23e84a7039374
- https://unix.stackexchange.com/questions/481939/how-to-export-a-gpg-private-key-and-public-key-to-a-file
- https://gist.github.com/woods/8970150
- https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits