Ict-创新/LPI/110.3
考生应该能够使用公钥技术来保护数据和通信
关键知识领域
- 执行基本 OpenSSH-2 客户端配置和使用
- 了解 OpenSSH-2 服务器主机密钥的作用
- 执行基本 GnuPG 配置和使用
- 了解 SSH 端口隧道(包括 X11 隧道)
安全外壳 (SSH) 是早期远程登录工具(如 telnet 和 rlogin)的流行替代品。SSH 比这些早期工具的最大优势在于,客户端和服务器之间的所有通信都是加密的,并且服务器的身份得到了安全验证。在 Linux 上使用的安全外壳的实现称为 OpenSSH。
OpenSSH 服务器 (sshd) 默认情况下在端口 22 上监听。在某些 Linux 发行版上,服务器默认安装并运行;在其他发行版上,需要使用包管理工具安装它。ssh 的客户端部分(如 ssh、ssh-keygen、ssh-agent 和 ssh-add 命令)通常默认情况下已安装。
SSH 使用公钥/私钥加密技术在建立连接时安全地验证服务器。此身份验证握手还会执行共享密钥的安全交换,该共享密钥用于加密客户端和服务器之间所有后续通信。下图说明了对称加密(使用共享密钥)和非对称加密(使用公钥和私钥对)之间的区别。
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 中。下图总结了这些密钥。
这些密钥用于安全地验证服务器机器的身份,并通过密钥交换协议建立加密通道。服务器的公钥需要在任何需要连接的客户端上可用。系统管理员可以将其复制到客户端(到文件 /etc/ssh/ssh_known_hosts 中)。您的发行版可能有一个名为 ssh-keyscan 的实用程序来帮助您执行此操作。或者,当 ssh 客户端连接到服务器时,服务器将提供主机的公钥。在此阶段,系统将提示用户类似以下内容
# ssh [email protected] 无法建立主机“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)永久添加到已知主机列表。
$ |
一个注重安全的人可能选择使用命令 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 [email protected] |
将生成 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 [email protected] 现在尝试登录到机器,使用“ssh '[email protected]'”,并在
中检查,以确保我们没有添加您不希望的额外密钥。 |
此脚本将在需要时在远程机器上创建 ~/.ssh 目录和 authorized_keys 文件,并正确设置其权限。如果 authorized_keys 文件已经存在,密钥将被附加到该文件。
下图总结了用户密钥的管理。
有了这个密钥,如果用户没有在他的私钥上设置密码短语,他就可以执行无密码的 ssh 登录到服务器。但是,如果他设置了密码短语,他将在此时被要求输入密码短语
$ ssh 192.168.81.1 输入密钥“/home/chris/.ssh/id_dsa”的密码短语
|
注意:文件的权限很重要。所有保存私钥的文件都应该是模式 600。~/.ssh 目录应该是模式 700。如果权限过松,ssh 将拒绝使用这些文件。
为了避免在 ssh 登录期间必须提供密码短语来解锁私钥的不便,可以使用程序 ssh-agent 来保存密码短语并在需要时自动提供密码短语。您只需将密码短语提供给代理一次,代理将在请求时将密钥提供给您拥有的其他进程。
以下对话将启动 ssh-agent 并将您的身份添加到它
$ eval $(ssh-agent) 代理 pid 22305
输入 /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 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 来通过加密通道安全地浏览。
作为端口转发的“特例”,ssh 可以安排将来自远程图形应用程序的 X 流量传回本地机器上的 X 服务器。这被称为 *X11 转发*。以下命令
$ ssh -X neptune xcalc |
在机器 neptune 上运行 xcalc 并安排它在本地机器的 X 服务器上显示。在幕后,sshd 充当代理 X 服务器并将所有 X 流量通过加密通道转发回客户端。此外,DISPLAY 环境变量被设置为将 xcalc 程序指向代理服务器。操作如下所示
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.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**
从真实姓名、注释和电子邮件地址中构建,格式如下 "Heinrich Heine (Der Dichter) <[email protected]>"
电子邮件地址:**[email protected]** 注释:**Demo User A** 您选择了此用户 ID "Alex Instructor <[email protected]>"
您需要一个密码来保护您的私钥。
其他操作(在键盘上键入、移动鼠标、使用 磁盘)是一个好主意;这给了随机数 生成器获得足够熵的更好机会。 .++++++++++++++++++++.++++++++++.+++++.+++++.+++++++++++++++.+++++.+++++++++++++++.+++++++++++++++.+++++++++++++++++++++++++..+++++++++++++++>..++++++++++>+++
操作系统有机会收集更多熵!(还需要 282 个字节) 我们需要生成大量的随机字节。在素数生成期间执行 其他操作(在键盘上键入、移动鼠标、使用 磁盘)是一个好主意;这给了随机数 生成器获得足够熵的更好机会。 ...+++++...+++++.+++++++++++++++++++++++++.+++++++++++++++...++++++++++...+++++...++++++++++++++++++++..+++++++++++++++++++++++++++++++++++.++++++++++++++++++++.+++++>..++++++++++>+++++......>+++++.......<+++++............>+++++..........+++++^^^^ gpg: /home/alex/.gnupg/trustdb.gpg: trustdb 已创建 gpg: 密钥 1B21BE5C 被标记为最终信任 公钥和私钥已创建并签署。
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 <[email protected]> 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) <[email protected]> sub 2048g/626C246D 2010-08-02 [过期时间:2010-08-30]
uid Beth Example (Demo User B) <[email protected]> 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) <[email protected]>" 2048 位 ELG 密钥,ID 07DFB736,创建于 2010-08-02(主密钥 ID F6CA4978)
"Beth Example (Demo User B) <[email protected]>" gpg: 签名于 2010 年 8 月 2 日星期一 03:25:00 BST 使用 DSA 密钥 ID B4DF979C 生成 gpg: 来自 "Alex Example (Demo User A) <[email protected]>" 的良好签名 |
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)加密发送者的纯文本,并将结果附加到消息中。接收者使用她的私钥解密会话密钥,然后使用它来解密消息正文。
这种方法有几个优点:首先,对称密码的计算速度要快得多,而且不需要那么长的密钥。此外,即使窃听者破解了会话密钥,他也无法读取任何后续消息。最后,由于非对称密码仅用于加密一个短的(且随机的)值,密码分析师几乎不可能破解它。
以下是使用的文件、术语和目标的部分列表
- 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/*