公鑰 (public key) 與私鑰 (private key) 是通過一種演算法得到的乙個金鑰對 (即乙個公鑰和乙個私鑰), 公鑰是金鑰對中公開的部分, 私鑰則是非公開的部分. 公鑰通常用於加密會話金鑰, 驗證數字簽名, 或加密可以用相應的私鑰解密的資料. 通過這種演算法得到的金鑰對能保證在世界範圍內是獨一的. 使用這個金鑰對的時候, 如果用其中乙個金鑰加密一段資料, 必須用另乙個金鑰解密. 比如用公鑰加密資料就必須用私鑰解密, 如果用私鑰加密也必須用公鑰解密, 否則解密將不會成功.
通過這篇文章也可以很好地理解公鑰與私鑰. 還可以理解, 公鑰是你家的位址, 私鑰是你家的鑰匙, 位址是公開的, 大家都可以知道, 但鑰匙最後一把, 只有你自己才能開啟方子.
公鑰和私鑰到底哪個才是用來加密和哪個用來解密?
一般來說, 既然是加密, 那肯定是不希望別人知道我的訊息, 所以只有我才能解密, 所以可得出公鑰負責加密, 私鑰負責解密; 同理, 既然是簽名, 那肯定是不希望有人冒充我發訊息, 只有我才能發布這個簽名, 所以可得出私鑰負責簽名, 公鑰負責驗證.
rsa 加密演算法是一種非對稱加密演算法, 在公開金鑰加密和電子商業中被廣泛使用. rsa是由羅納德·李維斯特 (ron rivest), 阿迪·薩莫爾 (adi shamir) 和倫納德·阿德曼 (leonard adleman) 在2023年一起提出的. 當時他們三人都在麻省理工學院工作. rsa 就是他們三人姓氏開頭字母拼在一起組成的.
對極大整數做因數分解的難度決定了 rsa 演算法的可靠性, 換言之, 對一極大整數做因數分解愈困難, rsa 演算法愈可靠. 假如有人找到一種快速因數分解的演算法的話, 那麼用 rsa 加密的資訊的可靠性就會極度下降. 但找到這樣的演算法的可能性是非常小的. 今天只有短的 rsa 鑰匙才可能被強力方式破解. 到當前為止, 世界上還沒有任何可靠的攻擊 rsa 演算法的方式. 只要其鑰匙的長度足夠長, 用rsa加密的資訊實際上是不能被破解的.
包含四個階段:
協議協商階段
服務端認證
客戶端驗證
資料傳輸
服務端監聽埠 22, 客戶端通過 tcp 三次握手與伺服器的 ssh 埠建立tcp連線.
伺服器通過建立好的連線向客戶端傳送乙個包含 ssh 版本資訊的報文, 格式為ssh-客戶端收到版本號資訊後, 如果伺服器使用的協議版本號低於自己的, 但是客戶端能夠相容這個低版本的 ssh 協議, 則就使用這個版本進行通訊. 否則, 客戶端會使用自己的版本號.
客戶端將自己決定使用的版本號發給伺服器, 伺服器判斷客戶端使用的版本號自己是否支援, 從而決定是否能夠繼續完成 ssh 連線, 可以則協商成功, 否則失敗斷開連線. 如果協商成功, 則進入金鑰和演算法協商階段.
協商成功後,服務端明文傳送:
客戶端收到後, 查詢該使用者的~/.ssh/下的known_hosts
是否存在對應服務端 ip 和機器名的 host key, 若不存在交由使用者判斷是否信任該服務端.
問題就在於如何對伺服器的 host key 進行認證?在 https 中可以通過 ca 來進行公證, 可是 ssh 的 host key 和 host private key 都是自己生成的, 沒法公證. 只能通過客戶端自己對 host key 進行確認. 通常在第一次登入的時候, 系統會出現下面提示資訊:
the authenticity of host 'ssh-server.example.com (12.18.429.21)' can't be established.
rsa key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
are you sure you want to continue connecting (yes/no)?
之所以用 fingerprint 代替 host key,主要是 host key過於長 ( rsa 演算法生成的公鑰有1024位), 很難直接比較. 所以, 對公鑰進行 hash 生成乙個 128 位的指紋, 這樣就方便比較了. 如果輸入yes
後, 會出現下面資訊:
warning: permanently added 'ssh-server.example.com,12.18.429.21' (rsa) to the list of known hosts.
password: (enter password)
該 host key 已被確認, 並被追加到檔案 known_hosts 中.
服務端的身份驗證成功之後, 雙方用服務端發來的引數和 diffie-hellman 演算法生成session key
.session key
是會話金鑰, 是隨機生成的對稱金鑰, 用於之後通訊時對訊息進行加密解密, 會話結束時被銷毀. 這個session key
的機制被稱作對稱加密 (symmetric encryption), 也就是兩端使用的相同的session key
來加密和解密資訊. 可以看出 ssh 資訊的加密解密時並不是用大家自己生成的 public/ private key, 而是用雙方都一致的session key
. 生成session key
的步驟大致如下:
客戶端和服務端使用溝通時的資訊, 協商加密演算法以及乙個雙方都知道的數字.
雙方各自生成只有自己才知道的 private 密碼, 並使用上一步中的數字進行加密, 再次生成密碼.
雙方交換再次加密後的密碼.
雙方在對方發來的密碼基礎上, 加上第二步自己的 private 密碼再次加密. 本次加密之後得到的結果就是在雙方處都相同的session key
.
從這個演算法中, 可以看出客戶端和服務端沒有直接傳輸自己在第二步生成的密碼, 而是通過加密互換再加密的方式來生成session key
, 從而保障了session key
無法被洩露.
雙方根據協商的加密演算法 (例如 md5, 這裡可能就是 md5 ) 將 host key, server key 和檢測位元組生成乙個 128 位 ( 16 位元組) 的 md5 值作為會話 id (session id). 這裡也有說伺服器生成 session id 發給客戶端的, 本質一樣.
客戶端驗證有多種驗證方式, 常用的包括密碼驗證和金鑰驗證. 服務端配置了金鑰驗證方式後 (預設是開啟) 優先使用金鑰方式登入.
客戶端使用session key
對 使用者名稱和密碼加密, 發給服務端, 服務端使用session key
解密後驗證是否合法. 有說, 客戶端使用上一步服務端傳送的server key/host key
對使用者和密碼加密, 然後發給服務端, 服務端使用私鑰解密, 這個描述不太正確, 感覺更容易被攻擊.
客戶端需要事先將自己的公鑰存放到服務端. 可用ssh-keygen
生成, 在/.ssh/id_rsa.pub
下.
然後通過以下命令, 將公鑰追加到要登陸使用者的家目錄中的/.ssh/authorized_keys
檔案中, 這裡 user 如果是 root, 則在/root/,ssh/authorized_keys
下, 如果是普通使用者, 則是/home/user/.ssh/authorized_keys
:
$ ssh-copy-id user@host
那麼在之後的連線中, 客戶端若生成了公鑰和私鑰, 則傳送公鑰認證 (public key) 請求, 傳送用session key
加密的包含公鑰的模作為識別符號 (keyid) 的資訊, 服務端接收到客戶端的連線請求後, 用session key
解密拿到公鑰的key id 從authorized_keys
檔案中找到匹配的對應該客戶端的公鑰, 若找不到則失敗, 客戶端則可繼續採取密碼登陸. 若找到, 服務端生成乙個 256 位 ( 32 位元組) 隨機數 r, 並用該公鑰加密, 最後使用session key
加密後傳送給客戶端.
客戶端收到後先用session key
和自己的私鑰解密, 得到隨機數r, 然後將隨機數和 session id 結合 (防止攻擊者重放攻擊, replay attack) 生成乙個 md5 值同時用session key
加密發給服務端. 服務端收到後, 也用同樣的認證方式 (隨機數 r 結合session id
) 生成 md5 值, 然後用 session key 解密客戶端發來的 md5 值, 對比是否一致完成驗證.
驗證成功後就是資料傳輸階段, 該階段使用session key
進行加密傳輸.
ssh 分為兩大步:
第一步是客戶端和服務端建立連線, 最終生成雙方都一致的 session key.
第二步使用 authorized key 進行登入, 登入過程使用 public/private key 驗證身份. 連線建立完成後, 在通訊過程中使用 session key 對資訊進行加密解密.
git 基於多種傳輸協議, 其中最常用的就是 https 和 ssh. 都是為了資料傳輸安全, 那麼設定 ssh 金鑰的目的是為了節省輸入使用者名稱密碼的過程, 同時保證傳輸安全. 並不是必須設定.
比如 github, 就可以通過將自己的公鑰配置到 github 端, 這樣傳輸的時候就不用每次都輸入密碼了.
使用 ssh-keygen 可以生成公鑰和私鑰, 具體可以參考這篇文章.
ssh 詳解
ssh認證登陸的過程與原理
每天都在用 ssh,你知道 ssh 的原理嗎?
ssh原理與運用(一):遠端登入
HTTP認證的底層技術簡析與揭秘
http認證的底層技術簡析與揭秘。http認證實現的基礎是web伺服器與瀏覽器之間能夠安全地交換類似使用者名稱和密碼這樣的使用者憑證,我們也可以把http認證當作是摘要驗證 digest authentication 這種預定義方法 標準在http協議中使用了編碼技術和md5加密雜湊。在這篇文章中,...
redhat環境下ssh不能自動認證登入的解決方法
一 摘要 許多開源專案,特別是分布式應用,如hadoop,mpi等都需要配置多個伺服器之間能自動登入。但是redhat enterprise 6.3,安裝後預設是沒有開啟ssh的自動認證功能。二 原因 產生該問題的原則是沒有開啟ssh的自動認證。三 解決方法如下 vim etc ssh sshd c...
ssh無密碼登入認證失敗 許可權問題
servera機器已經生產rsa金鑰 且已經將public key新增到serverb機器 root ssh authorized keys 但是ssh root 135.251.208.141機器時仍然需要輸入密碼,即無密碼認證失敗 分析與處理 用ssh v debug訪問,日誌如下,但是從日誌看...