--- title: 使用 SSH 金鑰與 GitHub 連線 date: 2020-12-23 21:50 is_modified: false disqus: cynthiahackmd categories: - "資訊科技 › 環境設定與指令" tags: - "資訊科技 › 環境設定與指令" - Git - GitHub - SSH - "Published" --- # 使用 SSH 金鑰與 GitHub 連線 ###### tags: | `資訊科技 › 環境設定與指令` | `Git` `GitHub` `SSH` | `Published` {%hackmd @CynthiaChuang/Github-Page-Theme %} <br> 好久沒發網誌,一發網誌立刻收到 GitHub 的通知,說它們即將在明年廢除 https 上 code 的方式,也就是輸入帳密的方式。只好鼻子摸摸來改成使用 SSH 金鑰了。 <!--more--> > **[GitHub] Deprecation Notice** > Basic authentication using a password to Git is deprecated and will soon no longer work. Visit https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information around suggested workarounds and removal dates. ## 配置 GitHub 金鑰 之前在使用 [SSH Key-based 登入](/@CynthiaChuang/Configuring-SSH-Key-Based-Authentication-on-a-Linux/)時,有稍微提過 SSH 認證與設置的步驟,在這邊的流程也不例外: 1. 產生金鑰對。 2. 將產生的 Pub key 放到遠端倉庫,也就是我們的 GitHub。 <p class="illustration"> <img src="https://i.imgur.com/XkG1sE2.png" alt="SSH 連線運作方式"> SSH 連線運作方式(圖片來源: <a href="https://sebastien.saunier.me/blog/2015/05/10/github-public-key-authentication.html">Sébastien Saunier</a>) </p> ### 產生金鑰對 我習慣所有的金鑰對收集起放在 `~/.ssh` 這個目錄下。若該目錄不存在,就自己建一個,並設定正確的權限: ```bash= $ mkdir ~/.ssh $ chmod 700 ~/.ssh ``` <br> 然後使用 `ssh-keygen` 這個指令產生金鑰,依照[教學文件](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)的提示,我們選擇 **ED25519** 作為金鑰的加密演算法,並使用電子郵件作為標籤,創建一個新的 SSH 金鑰。 ```bash= $ ssh-keygen -t ed25519 -C "your_email@example.com" Generating public/private ed25519 key pair. ``` 不過,`ED25519` 是後來推出的加密演算法,可能會發生舊系統無法生成的狀況。因此若系統不支援,可以改用 `rsa`,並指定金鑰長度為 `4096`: ```bash= $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com" ``` <br> 這邊稍微補充下,在 `ssh-keygen` 中常用參數如下: - `-t`:指定金鑰的加密演算法,預設使用 `SSH2d` 的 `rsa`。 - `-f`:指定金鑰的檔名,預設檔名會隨演算法而變動,例如使用 `rsa` 加密時,其檔名預設為 `id_rsa`(私鑰`id_rsa`,公鑰`id_rsa.pub`)。這階段沒改沒關係,等等還會在詢問。 - `-P`:提供舊密碼,空表示不需要密碼(-P ‘’) - `-N`:提供新密碼,空表示不需要密碼(-N ‘’) - `-b`:指定金鑰長度(bits)。 - `-C`:提供一個新標籤。 <br> 在產生金鑰的過程中,會詢問 3 個問題,如果沒有特殊需求可以全部使用預設值(按 Enter)就好: ```bash= Enter file in which to save the key (/home/username/.ssh/id_ed25519): /home/username/.ssh/github_key Enter passphrase (empty for no passphrase): Enter same passphrase again: ``` <br> 1. **Enter file in which to save the key** 第 1 個問題是問你金鑰儲存的位置與檔名,預設檔名是前面所提到 `id_ed25519`。不過,這命名無法表明金鑰的用途,所以習慣上我會更改檔名,例如 `github_key`。 2. **Enter passphrase** / **Enter same passphrase again** 第 2 跟 3 個問題則是詢問是否指定金鑰保護密碼,若有設定密碼的話,之後使用每次使用時,這把金鑰時就要輸入密碼,因此請務必牢記,不然這把金鑰就廢了 XDDD 如果之後想修改金鑰密碼的話,可以透過 `ssh-keygen` 來設定。 <br> 完成上述設定後,會看到 fingerprint 與 randomart ,就代表產生成功了 ```bash= Your identification has been saved in /home/username/.ssh/github_key. Your public key has been saved in /home/username/.ssh/github_key.pub. The key fingerprint is: ...... your_email@example.com The key’s randomart image is: +---[ED25519 256]----+ | | | | ... | | | | +----[SHA256]-----+ ``` ### 設定金鑰代理 這個步驟是給有設定金鑰密碼的人,如果你有設定密碼,但又不想每次使用金鑰就要輸入一次,你可以考慮設定金鑰代理: ```bash= $ eval "$(ssh-agent -s)" $ ssh-add ~/.ssh/github_key ``` 如果你沒有設定密碼,或是像我一樣不想起一個 agent 在背景跑,寧願每次輸入密碼的,可以跳過這個步驟。 ### 新增公鑰到你的遠端倉庫 產生的金鑰有兩把,一把是**公鑰(Public Key)**、一把是**私鑰(Private Key)**。 1. **公鑰**:這把是對外公開的金鑰,也就是我們要上傳的金鑰。 2. **私鑰**:這把則是放在自己電腦的金鑰,它等同於你的密碼。 <br> 知道要上傳的是那把鑰匙後,就可以依照下列方式進行設定 1. **檢視並複製生成的公鑰**: ```bash= $ cat ~/.ssh/github_key.pub ssh-ed25519 ........ your_email@example.com ``` <br> 2. **新增金鑰**: 接下來登陸你的 GitHub 帳號,點選你的頭像 → `Settings` 。 <p class="illustration"> <img src="https://i.imgur.com/jJ6XpEQ.png?1" alt="Settingsl"> </p> 左欄點選 `SSH and GPG keys` → `New SSH key`。 <p class="illustration"> <img src="https://i.imgur.com/rjIhVFM.png" alt="Settingsl"> </p> 最後把剛剛複製下來的公鑰,貼在下方,並為這把金鑰取個方便管理的名字。 <p class="illustration"> <img src="https://i.imgur.com/pmGdEeE.png" alt="Settingsl"> </p> 3. **連線測試** 完成金鑰上傳後,驗證下這組金鑰是不是正常工作,如果一切正常,應該會看到下面的訊息: ```bash= $ ssh -T git@github.com Hi XXX! You’ve successfully authenticated, but GitHub does not provide shell access. ``` <br> 不過,很不幸的我看到是這樣: ```bash= $ ssh -T git@github.com Permission denied (publickey). ``` 看起來被拒絕了。因為沒有足夠的資訊可供參考,所以我加上的 `-v`,試圖獲取多的資訊: ```bash= $ ssh -vT git@github.com debug1: Trying private key: /home/Cynthia_Chuang/.ssh/id_rsa debug1: Trying private key: /home/Cynthia_Chuang/.ssh/id_dsa debug1: Trying private key: /home/Cynthia_Chuang/.ssh/id_ecdsa debug1: Trying private key: /home/Cynthia_Chuang/.ssh/id_ed25519 debug1: No more authentication methods to try. ``` <br> 發現它在連線測試的時候,使用的預設的檔名,但我剛剛在建立金鑰時,更改了金鑰的名稱,難怪找不到,這時必須在配置一個 `config` 檔: ```bash= $ vim ~/.ssh/config ``` 在檔案中加上下列內容,其中 IdentityFile 是我們剛剛建立的金鑰: ``` Host github.com HostName github.com User CynthiaChuang IdentityFile ~/.ssh/github_key ``` 保存後重新測試連線,Bingo! ```bash= $ ssh -T git@github.com Hi CynthiaChuang! You've successfully authenticated, but GitHub does not provide shell access. ``` ## 更改連線協議 完成金鑰的產生與配置後,必須更改連線的協議,否則即便配置 SSH,還是會走 https 的傳輸協定。 ```bash= $ git remote -v origin https://github.com/user_name/project.git (fetch) origin https://github.com/user_name/project.git (push) ``` 說是更改連線協議,不過這其實就是**更換遠端伺服器倉庫網址**,Github 對於不同的協定走的是不同的伺服器倉庫網址。因此網址會從 https 改成 git 開頭: ```diff= - https://github.com/user_name/project.git + git@github.com:user_name/project.git ``` 完整的指令如下: ```bash= $ git remote set-url origin git@github.com:user_name/project.git ``` 是也可以[修改 config 檔案來達成該換遠端伺服器倉庫](/@CynthiaChuang/Git-Remote-Set-Url),不過個人偏愛指令的設定方式。 <br> 完成後,可以試著上傳 commit,並查看金鑰的使用狀況,應該會發現金鑰有了使用紀錄: <p class="illustration"> <img src="https://i.imgur.com/T0MzThW.png" alt="The Learning Model"> </p> ## 在 Window 使用 SSH 金鑰 基本上所有動作跟在 Linux 一樣,唯一的差異就是在 SSH 金鑰存放的位置是在 `c:/Users/user_name/.ssh`。 ## 參考資料 1. [Generating a new SSH key and adding it to the ssh-agent](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) 。檢自 GitHub Docs (2020-12-22)。 2. [Adding a new SSH key to your GitHub accountt](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account) 。檢自 GitHub Docs (2020-12-22)。 3. [Switching remote URLs from HTTPS to SSH](https://docs.github.com/en/free-pro-team@latest/github/using-git/changing-a-remotes-url#switching-remote-urls-from-https-to-ssh) 。檢自 GitHub Docs (2020-12-22)。 4. (2018-05-29)。[ssh-keygen常用參數詳解](https://www.itread01.com/content/1527598583.html) 。檢自 IT 閱讀 (2020-12-22)。 5. Mike Mazur (2009-08-06)。[ssh - How do I change my private key passphrase?](https://serverfault.com/questions/50775/how-do-i-change-my-private-key-passphrase) 。檢自 Server Fault (2020-12-22)。 6. 冰海 (2018-01-14)。[github提示Permission denied (publickey),如何才能解决? - 冰海的回答](https://www.zhihu.com/question/21402411/answer/295576230)。檢自 知乎 (2020-12-22)。 ## 更新紀錄 :::spoiler 最後更新日期:2020-12-23 - 2020-12-23 發布 - 2020-12-23 完稿 - 2020-12-22 起稿 ::: <br><br> > **本文作者**: 辛西亞.Cynthia > **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/Generating-a-Ssh-Key-and-Adding-It-to-the-Github/) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/Generating-a-Ssh-Key-and-Adding-It-to-the-Github) > **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!