跳轉到內容

Ict-創新/LPI/110.3

來自華夏公益教科書

110.3 使用加密保護資料

[編輯 | 編輯原始碼]

考生應該能夠使用公鑰技術來保護資料和通訊


關鍵知識領域

  • 執行基本 OpenSSH-2 客戶端配置和使用
  • 瞭解 OpenSSH-2 伺服器主機金鑰的作用
  • 執行基本 GnuPG 配置和使用
  • 瞭解 SSH 埠隧道(包括 X11 隧道)

介紹 ssh

[編輯 | 編輯原始碼]

安全外殼 (SSH) 是早期遠端登入工具(如 telnet 和 rlogin)的流行替代品。SSH 比這些早期工具的最大優勢在於,客戶端和伺服器之間的所有通訊都是加密的,並且伺服器的身份得到了安全驗證。在 Linux 上使用的安全外殼的實現稱為 OpenSSH。

OpenSSH 伺服器 (sshd) 預設情況下在埠 22 上監聽。在某些 Linux 發行版上,伺服器預設安裝並執行;在其他發行版上,需要使用包管理工具安裝它。ssh 的客戶端部分(如 ssh、ssh-keygen、ssh-agent 和 ssh-add 命令)通常預設情況下已安裝。

SSH 使用公鑰/私鑰加密技術在建立連線時安全地驗證伺服器。此身份驗證握手還會執行共享金鑰的安全交換,該共享金鑰用於加密客戶端和伺服器之間所有後續通訊。下圖說明了對稱加密(使用共享金鑰)和非對稱加密(使用公鑰和私鑰對)之間的區別。

圖 110.3-1:對稱和非對稱加密

SSH 主機身份驗證

安裝 openssh 伺服器時,會為該機器生成一個公鑰/私鑰對。實際上,會生成兩個金鑰對:DSA 金鑰對和 RSA 金鑰對。(DSA 和 RSA 只是兩種非對稱加密技術的名稱。)私鑰儲存在 /etc/ssh/ssh_host_rsa_key 和 /etc/ssh/ssh_host_dsa_key 中;這些檔案只能由 root 讀取。公鑰儲存在 /etc/ssh/ssh_host_rsa_key.pub 和 /etc/ssh/ssh_host_dsa_key.pub 中。下圖總結了這些金鑰。


圖 110.3-2:公鑰和私鑰伺服器金鑰


這些金鑰用於安全地驗證伺服器機器的身份,並透過金鑰交換協議建立加密通道。伺服器的公鑰需要在任何需要連線的客戶端上可用。系統管理員可以將其複製到客戶端(到檔案 /etc/ssh/ssh_known_hosts 中)。您的發行版可能有一個名為 ssh-keyscan 的實用程式來幫助您執行此操作。或者,當 ssh 客戶端連線到伺服器時,伺服器將提供主機的公鑰。在此階段,系統將提示使用者類似以下內容


# ssh chris@192.168.81.1

無法建立主機“192.168.81.1 (192.168.81.1)”的身份驗證。

RSA 金鑰指紋為 a9:77:96:9f:13:24:59:90:92:f6:e2:da:f3:91:e5:06。

您確定要繼續連線嗎(yes/no)?yes

警告:已將“192.168.81.1”(RSA)永久新增到已知主機列表。

chris@192.168.81.1 的密碼


上次登入:2010 年 9 月 7 日星期二 21:00:02

$

一個注重安全的人可能選擇使用命令 ssh-keygen 在伺服器上生成的相同指紋驗證此金鑰指紋。例如


# ssh-keygen -l

輸入金鑰所在的(/root/.ssh/id_rsa)檔案:/etc/ssh/ssh_host_rsa_key.pub

2048 a9:77:96:9f:13:24:59:90:92:f6:e2:da:f3:91:e5:06 /etc/ssh/ssh_host_rsa_key.pub

但是,大多數使用者只是相信他們連線到的是正確的伺服器(而不是冒名頂替者),並且簡單地回答yes 以接受並繼續連線。此時,伺服器的公鑰將被新增到本地 ~/.ssh/known_hosts 檔案中。顯然,此檔案是“針對每個使用者的” - 它僅適用於登入的使用者。


一旦伺服器的公鑰被客戶端識別,便不會再次出現“您確定要繼續嗎”訊息。

使用者身份驗證

[編輯 | 編輯原始碼]

OpenSSH 支援多種機制來驗證使用者。預設情況下,在大多數 Linux 發行版上,ssh 被配置為支援簡單的基於密碼的身份驗證 - 系統會提示使用者輸入其在遠端伺服器上的帳戶密碼並登入。但是,請注意,此密碼會透過加密通道傳送到伺服器,不會被竊聽者竊取。

使用者也可以使用公鑰/私鑰對進行身份驗證,這與 SSH 伺服器在建立初始連線時對客戶端進行身份驗證的方式非常相似。要使此方法有效,使用者必須首先為自己生成一個金鑰對,然後他必須將金鑰對的公鑰複製到需要對其進行身份驗證的任何伺服器上。

使用 ssh-keygen 生成金鑰


$ ssh-keygen -t dsa

正在生成公鑰/私鑰 dsa 金鑰對。

輸入要儲存金鑰的檔案 (/home/chris/.ssh/id_dsa)

輸入密碼短語(不輸入密碼短語則為空)

再次輸入相同的密碼短語

您的身份已儲存到 /home/chris/.ssh/id_dsa 中。

您的公鑰已儲存到 /home/chris/.ssh/id_dsa.pub 中。

金鑰指紋為

14:af:92:52:d5:38:ba:82:88:11:44:ee:f8:b1:66:1a chris@m1530-rhel.example.com

將生成 DSA 金鑰。預設情況下,這些金鑰將儲存在 ~/.ssh/id_dsa 和 ~/.ssh/id_dsa.pub 中。如果生成 RSA 金鑰,它們將儲存在 ~/.ssh/id_rsa 和 ~/.ssh/id_rsa.pub 中。請注意,使用者可以選擇使用密碼短語保護私鑰。他可以選擇透過在此提示符處按“Enter”鍵來不使用密碼短語。


包含公鑰的檔案需要被複制到伺服器上(例如,使用 scp),並新增到伺服器上使用者主目錄中的檔案 ~/.ssh/authorized_keys 中,如下圖所示。您的發行版可能包含一個名為 ssh-copy-id 的實用指令碼,它可以自動執行此過程


$ ssh-copy-id -i .ssh/id_dsa.pub chris@192.168.81.1


chris@192.168.81.1 的密碼

現在嘗試登入到機器,使用“ssh 'chris@192.168.81.1'”,並在


.ssh/authorized_keys

中檢查,以確保我們沒有新增您不希望的額外金鑰。

此指令碼將在需要時在遠端機器上建立 ~/.ssh 目錄和 authorized_keys 檔案,並正確設定其許可權。如果 authorized_keys 檔案已經存在,金鑰將被附加到該檔案。


下圖總結了使用者金鑰的管理。


圖 110.3-3:SSH 使用者公鑰和私鑰


有了這個金鑰,如果使用者沒有在他的私鑰上設定密碼短語,他就可以執行無密碼的 ssh 登入到伺服器。但是,如果他設定了密碼短語,他將在此時被要求輸入密碼短語


$ ssh 192.168.81.1

輸入金鑰“/home/chris/.ssh/id_dsa”的密碼短語


上次登入:2010 年 9 月 28 日星期二 12:01:42 來自 m1530-rhel.local

注意:檔案的許可權很重要。所有儲存私鑰的檔案都應該是模式 600。~/.ssh 目錄應該是模式 700。如果許可權過鬆,ssh 將拒絕使用這些檔案。


為了避免在 ssh 登入期間必須提供密碼短語來解鎖私鑰的不便,可以使用程式 ssh-agent 來儲存密碼短語並在需要時自動提供密碼短語。您只需將密碼短語提供給代理一次,代理將在請求時將金鑰提供給您擁有的其他程序。


以下對話將啟動 ssh-agent 並將您的身份新增到它


$ eval $(ssh-agent)

代理 pid 22305


$ ssh-add

輸入 /home/chris/.ssh/id_dsa 的密碼短語

已新增身份:/home/chris/.ssh/id_dsa (/home/chris/.ssh/id_dsa)

現在,您應該能夠對任何擁有您的使用者公鑰副本的伺服器執行安全但無密碼的登入。


啟動 ssh-agent 時使用命令替換和 eval 命令的奇怪方法是因為 ssh-agent 在其標準輸出上報告了一些環境變數,該程序需要知道這些變數才能聯絡代理。這個“技巧”允許我們將這些變數傳播回 shell 中。請注意,舊的命令替換語法使用反引號,如下所示:eval `ssh-agent`


客戶端 ssh 命令

配置完成後,SSH 的終端使用者體驗非常簡單。下表顯示了一些示例命令。


表:示例 ssh 命令


命令 功能
$ ssh neptune 使用本地使用者帳戶名登入到機器 neptune
$ ssh brian@neptune 以使用者 brian 身份登入到機器 neptune
$ ssh neptune date 在 neptune 上執行單個命令
$ scp foo neptune 將本地檔案 foo 複製到 neptune 上的主目錄中
$ scp foo neptune:/tmp/foo 將本地檔案 foo 複製到 neptune 上的指定路徑名
$ scp neptune:/tmp/foo . 將 neptune 上的 /tmp/foo 複製到本地機器上的主目錄中

埠轉發

[編輯 | 編輯原始碼]

ssh 具有一個名為遠端埠轉發的有用功能,它允許遠端 ssh 伺服器監聽任何指定的埠上的連線,並將流量透過加密的 ssh 隧道轉發到本地機器上的指定埠。在下圖的上半部分中,機器 mercury 上的使用者運行了以下命令

$ ssh -R 4023:mercury:23 venus

然後在機器 earth 上,使用者執行 telnet,連線到 venus 上的埠 4023。埠轉發意味著流量是安全的,並且伺服器上只需要開啟埠 22 以供連線。在實踐中,“venus”和“earth”通常是同一臺機器。

本地埠轉發與此類似,但它是客戶端轉發流量,而不是伺服器。在下圖的下半部分中,mercury 上的使用者運行了以下命令

$ ssh -L 8080:earth:80 venus

(再說一次,'venus'和'earth'通常是同一臺機器。) 然後,我們可以透過將瀏覽器指向 localhost:8080 來透過加密通道安全地瀏覽。

圖 110.3-4:本地和遠端埠轉發


作為埠轉發的“特例”,ssh 可以安排將來自遠端圖形應用程式的 X 流量傳回本地機器上的 X 伺服器。這被稱為 *X11 轉發*。以下命令


$ ssh -X neptune xcalc

在機器 neptune 上執行 xcalc 並安排它在本地機器的 X 伺服器上顯示。在幕後,sshd 充當代理 X 伺服器並將所有 X 流量透過加密通道轉發回客戶端。此外,DISPLAY 環境變數被設定為將 xcalc 程式指向代理伺服器。操作如下所示

圖 110.3-5:使用 ssh 進行 X-11 轉發

GPG(Gnu Privacy Guard)是原始 PGP 軟體的重寫版本。它使用對稱和非對稱加密的組合來提供兩個參與方之間的安全通訊。GPG 還提供金鑰管理工具。


GPG 的核心是一個名為 gpg 的命令列工具,它處理簽署、加密和解密訊息的基本任務,並處理金鑰管理。(許多電子郵件程式都有外掛來加密、簽署和解密使用此命令列工具在幕後執行的電子郵件。)為了說明它的用途,假設 Alex 想與 Beth 安全地進行通訊。


首先,Alex 使用命令 gpg-gen-key 生成他的公鑰/私鑰對


$ gpg --gen-key

gpg (GnuPG) 1.4.5; 版權所有 (C) 2006 自由軟體基金會,Inc。

此程式沒有任何保證。

這是一個自由軟體,您可以在某些條件下重新分發它

有關詳細資訊,請參見檔案 COPYING。


gpg: 目錄 `/home/alex/.gnupg' 已建立

gpg: 新配置的檔案 `/home/alex/.gnupg/gpg.conf' 已建立

gpg: 警告:`/home/alex/.gnupg/gpg.conf' 中的選項在本執行期間尚不可用

gpg: 金鑰環 `/home/alex/.gnupg/secring.gpg' 已建立

gpg: 金鑰環 `/home/alex/.gnupg/pubring.gpg' 已建立

請選擇您想要的金鑰型別

(1) DSA 和 Elgamal(預設)

(2) DSA(僅簽署)

(5) RSA(僅簽署)

您的選擇? **1**

DSA 金鑰對將擁有 1024 位。

ELG-E 金鑰的長度可能在 1024 位到 4096 位之間。

您想要什麼金鑰大小? (2048) **2048**

請求的金鑰大小為 2048 位

請指定金鑰的有效期。

0 = 金鑰永不過期

<n> = 金鑰在 n 天后過期

<n>w = 金鑰在 n 周後過期

<n>m = 金鑰在 n 個月後過期

<n>y = 金鑰在 n 年後過期

金鑰的有效期為? (0) **1y**

金鑰在 2011 年 9 月 28 日星期三下午 01:29:24 BST 過期

是否正確? (y/N) **y**


您需要一個使用者 ID 來識別您的金鑰;軟體將使用者 ID

從真實姓名、註釋和電子郵件地址中構建,格式如下

"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"


真實姓名:**Alex Example**

電子郵件地址:**alex@example.com**

註釋:**Demo User A**

您選擇了此使用者 ID

"Alex Instructor <alex@example.com>"


更改 (N)ame、(C)omment、(E)mail 或 (O)kay/(Q)uit? o

您需要一個密碼來保護您的私鑰。


我們需要生成大量的隨機位元組。在素數生成期間執行

其他操作(在鍵盤上鍵入、移動滑鼠、使用

磁碟)是一個好主意;這給了隨機數

生成器獲得足夠熵的更好機會。

.++++++++++++++++++++.++++++++++.+++++.+++++.+++++++++++++++.+++++.+++++++++++++++.+++++++++++++++.+++++++++++++++++++++++++..+++++++++++++++>..++++++++++>+++


可用的隨機位元組不夠。請執行其他操作,以便

作業系統有機會收集更多熵!(還需要 282 個位元組)

我們需要生成大量的隨機位元組。在素數生成期間執行

其他操作(在鍵盤上鍵入、移動滑鼠、使用

磁碟)是一個好主意;這給了隨機數

生成器獲得足夠熵的更好機會。

...+++++...+++++.+++++++++++++++++++++++++.+++++++++++++++...++++++++++...+++++...++++++++++++++++++++..+++++++++++++++++++++++++++++++++++.++++++++++++++++++++.+++++>..++++++++++>+++++......>+++++.......<+++++............>+++++..........+++++^^^^

gpg: /home/alex/.gnupg/trustdb.gpg: trustdb 已建立

gpg: 金鑰 1B21BE5C 被標記為最終信任

公鑰和私鑰已建立並簽署。


gpg: 正在檢查 trustdb

gpg: 需要 3 個邊緣信任,需要 1 個完整信任,PGP 信任模型

gpg: 深度:0 有效:1 已簽署:0 信任:0-,0q,0n,0m,0f,1u

gpg: 下次 trustdb 檢查將在 2011-09-28 進行

pub 1024D/1B21BE5C 2010-09-28 [過期時間:2011-09-28]

金鑰指紋 = 9FD4 775C 8867 2E53 9C0A 28C3 C633 2E64 1B21 BE5C

uid Alex Instructor <alex@example.com>

sub 2048g/F0938AF1 2010-09-28 [過期時間:2011-09-28]

在這裡,我們選擇了 DSA 和 Elgamal 金鑰以及 2048 位的 DSA 金鑰大小。我們提供了一個密碼來保護我們的私鑰。我們提供了一個姓名、電子郵件地址和註釋,這些資訊用於構建一個“使用者 ID”,以人性化的方式標識這是誰的金鑰。


公鑰和私鑰被放置在 .gnupg 目錄中的檔案中


$ **ls -l .gnupg**

共 32

-rw------- 1 alex alex 9207 9 月 28 日 13:28 gpg.conf

-rw------- 1 alex alex 1178 9 月 28 日 13:35 pubring.gpg

-rw------- 1 alex alex 1178 9 月 28 日 13:35 pubring.gpg~

-rw------- 1 alex alex 600 9 月 28 日 13:35 random_seed

-rw------- 1 alex alex 1327 9 月 28 日 13:35 secring.gpg

-rw------- 1 alex alex 1280 9 月 28 日 13:35 trustdb.gpg

然後 Alex 將他的公鑰匯出到一個 ASCII 檔案,如下所示


$ gpg --export --armor -o alex.pub Alex

“武裝”金鑰只是意味著以 ASCII 格式表示它,例如可以打印出來或作為電子郵件的文字進行傳輸。命令的最後一個引數('Alex')是金鑰使用者 ID 的一部分,足以識別金鑰。他最終得到的檔案 alex.pub 是他計劃交給 Beth 的檔案。


Beth 經歷了相同的過程,生成自己的金鑰對和自己的密碼,並將公鑰匯出到一個名為 beth.pub 的檔案中,準備交給 Alex。


Alex 和 Beth 現在交換了他們的 GPG 公鑰。Alex 將 Beth 的檔案複製到他的計算機上,並將其匯入到他的 GPG 金鑰環中,如下所示


$ gpg --import beth.pub

Beth 也類似地將 Alex 的公鑰匯入到她的金鑰環中。


此時,如果 Alex 列出他的金鑰,他將看到他自己的金鑰的公鑰部分以及他從 Beth 匯入的金鑰


$ gpg --list-keys

/home/alex/.gnupg/pubring.gpg

-----------------------------

pub 2048D/B4DF979C 2010-08-02 [過期時間:2010-08-30]

uid Alex Example (Demo User A) <alex@example.com>

sub 2048g/626C246D 2010-08-02 [過期時間:2010-08-30]


pub 2048D/F6CA4978 2010-08-02 [過期時間:2010-08-30]

uid Beth Example (Demo User B) <beth@example.com>

sub 2048g/07DFB736 2010-08-02 [過期時間:2010-08-30]



在 Alex 可以使用 Beth 的公鑰向她傳送機密訊息之前,他還有一件事需要做。他需要簽署 Beth 的金鑰,以表明他相信它確實是她的金鑰


$ gpg --sign-key Beth

Alex 現在可以使用 Beth 的公鑰向她傳送加密訊息


$ gpg --encrypt --armor --recipient Beth secret.txt

在此命令中,Beth 是金鑰 ID 的任何部分,足以唯一地識別此金鑰。此時,Alex 有一個名為 secret.txt.asc 的加密檔案,他可以將其傳送給 Beth。他知道只有 Beth 可以閱讀它,因為只有她知道 Alex 用它加密訊息的公鑰對應的私鑰。


Beth 可以這樣解密此檔案


$ gpg --decrypt -o poetry.txt secret.txt.asc


您需要一個密碼來解鎖使用者的私鑰

user: "Beth Example (Demo User B) <beth@example.com>"

2048 位 ELG 金鑰,ID 07DFB736,創建於 2010-08-02(主金鑰 ID F6CA4978)


gpg: 使用 2048 位 ELG 金鑰加密,ID 07DFB736,創建於 2010-08-02

"Beth Example (Demo User B) <beth@example.com>"

gpg: 簽名於 2010 年 8 月 2 日星期一 03:25:00 BST 使用 DSA 金鑰 ID B4DF979C 生成

gpg: 來自 "Alex Example (Demo User A) <alex@example.com>" 的良好籤名

Alex 的金鑰對也很重要。他已使用他的私鑰簽署(宣告他信任)Beth 的公鑰。當然,他的公鑰將用於加密 Beth 回覆給 Alex 的訊息。

數字簽名

[編輯 | 編輯原始碼]

Alex 透過建立訊息的雜湊值並用他的私鑰對其進行加密來簽署他的訊息。收到後,Beth 可以解密雜湊值(使用 Alex 的公鑰),計算她自己的訊息雜湊值,並將兩者進行比較。如果它們匹配,Beth 就有高度的信心,即該訊息來自 Alex 並且自簽署後該訊息未被修改。請注意,數字簽名不提供機密性,即它們不會加密訊息。gpg 將複雜性隱藏在簡單的命令選項(--sign)後面。Alex 可以同時加密和簽署訊息


$ gpg --encrypt --sign --armor --recipient Beth secret.txt

然後,當 Beth 解密它時,簽名將自動被檢查。(在前面的示例的結尾,請注意報告了使用哪個公鑰對訊息進行了加密,使用哪個私鑰對其進行了簽署,以及簽名是否與訊息匹配。


GPG 還使用“信任網”支援自己的公鑰基礎設施,但這超出了我們目前的範圍。


PGP 的工作原理


PGP 使用對稱和非對稱加密的混合。選擇一個隨機的會話金鑰(僅用於此訊息),並用接收者的公鑰對其進行加密。結果作為訊息的一部分發送。然後使用會話金鑰使用對稱密碼(預設情況下為 IDEA)加密傳送者的純文字,並將結果附加到訊息中。接收者使用她的私鑰解密會話金鑰,然後使用它來解密訊息正文。


這種方法有幾個優點:首先,對稱密碼的計算速度要快得多,而且不需要那麼長的金鑰。此外,即使竊聽者破解了會話金鑰,他也無法讀取任何後續訊息。最後,由於非對稱密碼僅用於加密一個短的(且隨機的)值,密碼分析師幾乎不可能破解它。


圖 110.3-6:PGP 工作原理



以下是使用的檔案、術語和目標的部分列表

  • ssh
  • ssh-keygen
  • ssh-agent
  • ssh-add
  • ~/.ssh/id_rsa 和 id_rsa.pub
  • ~/.ssh/id_dsa 和 id_dsa.pub
  • /etc/ssh/ssh_host_rsa_key
  • ssh_host_rsa_key.pub
  • /etc/ssh/ssh_host_dsa_key
  • ssh_host_dsa_key.pub
  • ~/.ssh/authorized_keys
  • /etc/ssh_known_hosts
  • gpg
  • ~/.gnupg/*
華夏公益教科書