基於安全及隱私因素,存取 Private 的 Github repository 不管是進行 clone, push, pull 時都需要驗證身分。 而 Public repository 在 clone 時是不用驗證的,直接 clone 就可以了,但 push 時就要驗證你是否為具有開發者身分了。
不管是早期使用 HTTP/HTTPS 輸入帳號密碼,或者使用 SSH 搭配公私鑰,都是通訊方式及帳戶驗證的手段罷了。 但 SSH 搭配公私鑰讓存取 Github 更安全(不用擔心密碼被破解)且更方便(設定好以後再也不用輸入密碼)。
HTTPS 搭配帳號密碼的方式沒什麼好說的,需要驗證時會要求你輸入帳號密碼。但,這個方式已經被 Github deprecated,我們應該使用更好的方式,以下就來介紹 SSH 搭配公私鑰的方法。
在 Github 或者 Gitlab 中,可以設定 SSH Key 的地方有 2 個,按用途分為 SSH Key 以及 Deploy Key。
當你使用 git 指令連到 Github 且輸入的是 SSH 格式,則 git 就會嘗試 SSH 安全遠端連線,若需要身分驗證,則會去取用你保存在 local 端的 private key。
Github 不允許使用者直接使用 SSH 操作 Github Host,而必須透過 git 指令,再由 git 指令去進行 SSH 操作。
SSH 的格式為 user@host
,對照 git clone
指令格式比如: git clone git@github.com:WSMao/hugo_blog.git
其中
git
github.com
:WSMao/hugo_blog.git
則是 Github 仿照 scp 格式冒號後面後面接檔案地址。SSH 指令指定
ssh
指令中明確指定連線參數,這些會 優先於 config 設定,如 ssh -i ~/.ssh/custom_key git@github.com
,其中 -i
選項指定金鑰。ssh
指令最少可以只輸入 host
即可,如 ssh github.com
(前提是 config 設定檔須提供細節)。~/.ssh/config
ssh
指令時就不用輸入那麼多細部參數。只要 ssh
指令找不到的參數設定都會到 config 裡找。~/.ssh/config
中有針對目標主機 (Host github.com
) 指定 IdentityFile
,則 SSH 會根據這個設定來選擇金鑰。config
可以設定不同 repository 使用不同的金鑰,例如:
Host github.com-hugo
HostName github.com
User git
IdentityFile ~/.ssh/hugo_key
Host github.com-private
HostName github.com
User git
IdentityFile ~/.ssh/private_key
SSH Agent
ssh-add
)載入金鑰(載入時已提供過密碼),則之後使用 private_key 就不用再輸入密碼。預設金鑰 (~/.ssh/id_rsa
、~/.ssh/id_ed25519
)
ssh
指令沒有提供,且 ~/.ssh/config
內也沒有指定 IdentityFile
,那 SSH 就會嘗試讀取預設的金鑰,如:
~/.ssh/id_rsa
(ssh-keygen 預設)~/.ssh/id_ed25519
(更推薦)基本上,除非你有很多個 private_key 或者特殊需求需要管理,不然不必使用 agent 或者 config 來設定,使用預設金鑰名稱即可。
相關 ssh-agent 指令如下:
eval $(ssh-agent)
: 啟動 ssh-agent
ssh-add <private_key>
: 加入 ssh key
ssh-add -l
: 列出已加入的 key
ssh-add -D
: 移除所有 key
這個檔案可以讓你自訂 SSH 連線方式,可用來簡化 SSH 指令、管理多個 SSH 金鑰。
ssh -i ~/.ssh/id_rsa chris@192.168.1.100 -p 2222
)。User
。ProxyJump
來穿透防火牆。可參考 如何針對不同的-repo-指定不同的-ssh-key
以 Github 帳號擁有者來說,他的身分理當允許存取所有 repositories ,只需要為他的電腦,設置一組 SSH key 並將 public key 加入 Github 即可,往後在這台電腦上進行任何對 Github 的操作,都會自動完成身分驗證,無須輸入帳號密碼。
若有另外一台電腦,也是再產生一組 SSH Key 加入 Github 即可,而且我想,或許兩台電腦使用相同的 private key 也是可以的,這樣只需要一組 SSH Key 了。
注意,不管是用在 SSH Key 或者 Deploy Key 都不可以重複,否則加入 Key 時會出現:
Key is already in use
的錯誤訊息。
ssh-keygen
參數 | 說明 | 範例 |
---|---|---|
-t <key_type> |
指定 金鑰類型,ed25519 是一種較新的橢圓曲線演算法,比 rsa (預設)更安全、更快,且金鑰較短。 |
-t ed25519 |
-C <comment> |
設定金鑰的 註解 (comment),通常用來標記用途,例如 GitHub 會建議填入 Email 來區分不同設備的金鑰。 | -C "your_email@example.com" |
-b <bits> |
金鑰長度(只適用於 rsa ,ed25519 沒有這個選項) |
-b 4096 (預設 3072) |
-f <file> |
指定金鑰存放位置(預設存於 ~/.ssh/id_ed25519 ) |
-f ~/.ssh/my_github_key |
-N <passphrase> |
設定金鑰密碼(空字串 "" 代表無密碼) |
-N "mypassword" |
-y |
從私鑰產生對應的公鑰 | ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub |
-q |
安靜模式(不顯示輸出) | -q |
範例,於終端機則一輸入:
ssh-keygen
,沒給參數則會引導一步步輸入ssh-keygen -t ed25519 -C "my_email@example.com"
,指定用 ed25519 算法產生晶鑰,並加入 comment 訊息。輸入後就會產生一對 Keys,帶有尾墜.pub 的是 public_key,沒有尾墜的是 private_key。
cat id_rsa.pub
讀出 public_key,並複製輸出結果。ssh -T git@github.com
: 可用來測試連線,-T
代表禁用虛擬終端分配,因為 GitHub SSH 伺服器不提供 shell 存取,使用 -T
不會開啟遠端終端機,只是測試身份驗證是否成功。
如果驗證身分成功,你會看到 Hi WSMao! You've successfully authenticated, but GitHub does not provide shell access.
補充:若你使用 deploy key 存取 github.com 時,則會提到特定 repository 名稱 Hi WSMao/hugo_blog! You've successfully authenticated, but GitHub does not provide shell access.
看 git clone git@github.com:WSMao/hugo_blog.git
是否 clone 成功就知道 SSH Key 設定是否生效。若出現失敗訊息 Please make sure you have the correct access rights and the repository exists.
可能就是 SSH Key 沒有設定好。
GitHub 禁止的是 Git 操作時使用密碼驗證(此密碼就是登入 Github 之密碼)。在網頁登入 GitHub 時仍然是使用密碼,但透過 HTTPS 的 Git 操作不能再用密碼。
儘管 GitHub 在 2021 年 停用了使用帳號密碼的方式進行 Git 操作,但是仍然可以使用 HTTPS + Personal Access Token(PAT)來驗證並進行 git clone 等操作。 如果你使用 HTTPS 並看到提示要求輸入密碼,那麼密碼應該是 Personal Access Token,而非 GitHub 帳號密碼。
Personal Access Token (PAT) 是 GitHub 提供的一種更安全、更靈活的身份驗證方式,可以用來替代密碼,並可設置具體權限和範圍。
SSH 和 HTTPS 都有公私鑰加密,但它們的重點不同,SSH 更強調 身份驗證 和 加密通信,而 HTTPS 則專注於 加密資料傳輸 和 伺服器身份認證。
主要差別是:
對於 Github 應用來說,主要是要進行 client 端的身分驗證,這正是 SSH 本就擅長的部份。HTTPS 雖然也保障資料傳輸是安全加密的,但進行 client 身分認證的部分,還是得透過使用者輸入帳號密碼,即使現在改用 PAT 認證,還是沒有永遠不用輸入密碼的 SSH Key 機制來的安全。
你可以透過 ~/.ssh/config
設定不同 repo 使用不同的 Key。
注意: 這裡主要是要探討若需要管理多把 keys 時, config 檔案可以如何設定。日常 Github 使用上,不太會有這個需求,因為只需要設定好 1 組 SSH key 即可。
(1) 產生多組 SSH Key
ssh-keygen -t ed25519 -C "your-email@example.com" -f ~/.ssh/github_repo1
ssh-keygen -t ed25519 -C "your-email@example.com" -f ~/.ssh/github_repo2
這會產生:
~/.ssh/github_repo1
(私鑰)~/.ssh/github_repo1.pub
(公鑰)~/.ssh/github_repo2
(私鑰)~/.ssh/github_repo2.pub
(公鑰)(2) 分別把 .pub
上傳到 GitHub
github_repo1.pub
和 github_repo2.pub
加到 SSH Keys(3) 設定 ~/.ssh/config
Host github-repo1
HostName github.com
User git
IdentityFile ~/.ssh/github_repo1
Host github-repo2
HostName github.com
User git
IdentityFile ~/.ssh/github_repo2
這樣,你可以用 github-repo1
或 github-repo2
來指定不同的 SSH Key。
(4) 使用 git clone
git clone git@github-repo1:WSMao/repo1.git
git clone git@github-repo2:WSMao/repo2.git
這樣就可以讓不同的 repo 使用不同的 SSH Key。