ssh-keygen命令使用指南:生成与管理SSH密钥 – wiki基地


SSH-Keygen 命令使用指南:生成与管理SSH密钥

在现代网络通信中,尤其是在服务器管理、代码版本控制(如Git)以及各种自动化部署场景下,SSH(Secure Shell)协议扮演着至关重要的角色。它提供了一种加密的方式来安全地在网络中传输数据和执行命令。而SSH密钥,作为SSH协议中一种比传统密码登录更安全、更便捷的认证方式,其重要性不言而喻。

ssh-keygen 命令是OpenSSH套件中的一个核心工具,专门用于生成、管理和转换SSH密钥对。理解并熟练使用 ssh-keygen,是每一个需要进行安全远程连接的技术人员必备的技能。本文将带您深入了解 ssh-keygen 命令的各项功能和使用方法,从最基本的密钥生成到高级的密钥管理技巧。

第一章:理解SSH密钥和ssh-keygen的作用

在开始使用 ssh-keygen 之前,有必要先理解SSH密钥的工作原理。SSH密钥对是基于非对称加密算法生成的,包含两个部分:

  1. 私钥 (Private Key):这是您拥有的密钥,必须严格保密。它用于对数据进行解密或签名。私钥文件通常位于 ~/.ssh/ 目录下,例如 id_rsa。私钥的权限设置至关重要,通常应设置为只有拥有者可读写(chmod 600),确保其他用户无法访问。
  2. 公钥 (Public Key):这是与私钥配对生成的密钥,可以公开分享给您希望允许通过SSH连接到您的服务或服务器的对方。公钥用于对数据进行加密或验证签名。公钥文件通常与私钥同名,但带有 .pub 后缀,例如 id_rsa.pub。您需要将您的公钥放置到您想登录的远程服务器的特定位置(通常是用户家目录下的 ~/.ssh/authorized_keys 文件中)。

当您尝试使用SSH密钥登录远程服务器时,流程大致如下:

  1. SSH客户端告诉服务器您希望使用密钥进行认证,并发送您的公钥ID。
  2. 服务器查找与该ID对应的公钥,并使用该公钥生成一个随机数,然后用该随机数和您协商好的会话密钥对一个挑战消息进行加密,发送给客户端。
  3. 客户端收到加密的挑战消息后,使用对应的私钥进行解密,得到原始的挑战消息。
  4. 客户端使用原始挑战消息计算出一个响应,并用私钥对其进行签名,然后将签名发送给服务器。
  5. 服务器使用先前找到的公钥验证客户端发送的签名。如果签名有效,证明客户端确实拥有与公钥配对的私钥,服务器则允许认证成功,建立安全连接。

整个过程中,私钥从未离开您的本地计算机,从而极大地提高了安全性。

ssh-keygen 命令的核心作用就是执行上述流程的第一步:生成私钥和公钥对。此外,它还能帮助您管理这些密钥,例如修改私钥的密码(passphrase)、查看密钥指纹、更改密钥注释等。

第二章:基本密钥生成流程

使用 ssh-keygen 生成密钥对是最常见和基础的操作。最简单的命令形式如下:

bash
ssh-keygen

执行这个命令后,ssh-keygen 会以交互式的方式引导您完成密钥生成过程。以下是可能的输出和提示:

Generating public/private rsa key pair.
Enter file in which to save the key (/home/your_user/.ssh/id_rsa):

提示 1: 密钥文件保存路径

这是第一个提示,询问您希望将生成的密钥对保存在哪里。

  • 括号中 (/home/your_user/.ssh/id_rsa) 是默认的保存路径和文件名。通常情况下,直接按 Enter 键接受默认值即可。~/.ssh/ 是SSH客户端和服务器默认查找用户密钥和配置文件的位置。
  • 如果您想生成用于特定目的(例如连接GitHub、连接公司内部服务器)的独立密钥对,可以指定一个不同的文件名,例如 /home/your_user/.ssh/github_rsa。这将生成 github_rsa (私钥) 和 github_rsa.pub (公钥)。

如果您选择默认路径并按 Enter,如果该文件已存在,系统会提示您是否覆盖:

/home/your_user/.ssh/id_rsa already exists.
Overwrite (y/n)?

请谨慎选择。如果您不确定是否要覆盖,输入 n 并按 Enter。如果确定要覆盖,输入 y 并按 Enter。注意:覆盖现有密钥将使所有依赖旧密钥进行认证的服务失效,您需要重新配置。

如果您选择默认路径且文件不存在,或者您指定了新路径,系统将进入下一个提示。

Enter passphrase (empty for no passphrase):

提示 2: 设置私钥密码 (Passphrase)

这是第二个提示,询问您是否为私钥设置一个密码(Passphrase)。

  • 重要性: 设置密码可以为您的私钥提供额外的安全层。即使您的私钥文件被泄露,攻击者也无法在不知道密码的情况下使用它。这就像给您的私钥文件加了一把锁。
  • 便捷性: 如果您设置了密码,每次使用私钥进行SSH连接时,都需要输入这个密码。这可能会比较繁琐,尤其是在频繁连接或自动化脚本中。但是,您可以使用 ssh-agent 工具来管理已解锁的私钥,避免每次都输入密码(我们稍后会介绍)。
  • 选择:
    • 如果您追求最高安全性,并且愿意使用 ssh-agent 来管理密码,强烈建议设置一个强密码。
    • 如果您处于一个非常安全的环境,或者需要进行无人值守的自动化操作,并且您能够确保私钥文件的绝对安全,可以选择不设置密码(直接按 Enter)。但请务必理解其中的风险。

如果您决定设置密码,请输入一个您能记住的复杂密码,然后按 Enter。输入时屏幕上不会显示字符。

Enter same passphrase again:

提示 3: 确认私钥密码

为了避免输入错误,系统会要求您再次输入刚才设置的密码。再次输入相同的密码并按 Enter。

Your identification has been saved in /home/your_user/.ssh/id_rsa.
Your public key has been saved in /home/your_user/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:............................................. user@hostname
The key's randomart image is:
+---[RSA 3072]----+
| .+*+=o |
| ... +o o. |
| . . + . |
| o . .o . |
| . S oooE |
| . + =.+ |
| . . B o |
| o + = |
| o.+. |
+----[SHA256]-----+

生成完成

最后,ssh-keygen 会显示密钥的保存位置、公钥的保存位置、密钥的指纹(fingerprint)以及一个随机艺术图像(randomart image)。

  • 指纹 (Fingerprint):这是公钥的数字摘要,用于验证公钥的真实性。如果您通过不安全的通道获取了某个服务器的公钥指纹(例如通过电话),在第一次连接该服务器时,SSH客户端会显示服务器发送过来的公钥指纹,您可以对照确认是否一致,防止中间人攻击。SHA256是目前推荐的指纹算法,比MD5更安全。
  • 随机艺术图像 (Randomart image):这是公钥指纹的一种可视化表示,可以帮助您更容易地识别和区分不同的密钥,尽管其主要作用并非严格的安全性验证。

至此,您已经成功生成了一对SSH密钥。您的私钥 id_rsa 存储在 ~/.ssh/ 目录中,公钥 id_rsa.pub 也存储在那里。

第三章:自定义密钥生成

除了最简单的交互式生成方式,ssh-keygen 提供了丰富的选项,允许您自定义密钥的类型、大小、文件路径、注释、是否设置密码等。

常用选项列表:

  • -t type: 指定要生成的密钥类型。
  • -b bits: 指定密钥的长度(比特数),主要用于RSA和DSA密钥。
  • -f filename: 指定生成的密钥文件的路径和名称。
  • -P passphrase: 指定旧密码(用于修改密码时)。
  • -N new_passphrase: 指定新密码。如果为空,表示不设置密码。
  • -C comment: 为公钥添加注释。
  • -q: 静默模式,不显示进度条和大部分提示信息。

下面详细介绍如何使用这些选项:

3.1 指定密钥类型 (-t type)

ssh-keygen 支持多种非对称加密算法生成密钥对。常用的类型包括:

  • rsa: RSA算法。长期以来是默认类型。
  • dsa: DSA算法。安全性已不如其他算法,且 OpenSSH 默认禁用了小于 1024 位的 DSA 密钥。不推荐在新环境中使用。
  • ecdsa: ECDSA(Elliptic Curve Digital Signature Algorithm)算法。基于椭圆曲线加密,通常比同等安全强度的RSA密钥更短、更快。推荐使用。
  • ed25519: Ed25519算法。另一种基于椭圆曲线的算法,由Daniel J. Bernstein等人设计,被认为是目前最安全、最高效的算法之一。强烈推荐作为新生成密钥的默认类型。

示例:生成Ed25519类型的密钥

bash
ssh-keygen -t ed25519

执行此命令将生成Ed25519密钥对,后续交互式步骤与基本生成流程相同(询问保存路径、密码)。

3.2 指定密钥长度 (-b bits)

此选项用于指定密钥的长度,以比特为单位。主要适用于RSA和DSA密钥。对于ECDSA和Ed25519,密钥长度由算法类型决定,此选项通常会被忽略或无效。

  • RSA: 推荐的密钥长度至少为2048位(-b 2048),更安全的选择是3072位或4096位(-b 4096)。更长的密钥提供了更高的安全性,但生成和使用时可能稍微慢一些。 OpenSSH 默认生成的 RSA 密钥长度通常是 2048 或 3072 位(取决于版本和配置)。
  • DSA: DSA 密钥长度必须是 1024 位。不推荐使用。

示例:生成4096位的RSA密钥

bash
ssh-keygen -t rsa -b 4096

3.3 指定密钥文件路径 (-f filename)

如果您需要生成多对密钥用于不同的用途,或者不想使用默认文件名 id_rsa,可以使用 -f 选项指定完整的路径和文件名。

示例:生成用于GitHub的Ed25519密钥

bash
ssh-keygen -t ed25519 -f ~/.ssh/github_ed25519 -C "[email protected] for GitHub"

这里 -C 选项用于添加注释,通常包含用户邮箱和用途,方便识别。执行后,将生成 ~/.ssh/github_ed25519 (私钥) 和 ~/.ssh/github_ed25519.pub (公钥)。

3.4 非交互式生成(指定密码和注释)

您可以通过组合使用 -N-C 选项来实现非交互式生成密钥,避免在命令行中输入密码和注释。这在脚本或自动化场景中很有用。

示例:非交互式生成密钥(带密码和注释)

bash
ssh-keygen -t rsa -b 4096 -f ~/.ssh/my_server_rsa -N "MySecurePassphrase" -C "User for MyServer"

注意: 直接在命令行中包含密码 -N "MySecurePassphrase"不安全的,因为密码会明文出现在您的命令行历史记录中。这种方法只适用于您能够确保命令行历史记录不被泄露,或者在非常临时的、不需要长期保密的场景下。在大多数情况下,推荐使用交互式方式,或者利用脚本从安全的地方读取密码(例如环境变量或管道),但更安全的方式是生成时不设密码,然后用 ssh-keygen -p 设置,或者生成时留空,让脚本通过其他方式提供密码。

示例:非交互式生成无密码密钥

bash
ssh-keygen -t ed25519 -f ~/.ssh/automation_key -N "" -C "Key for automation script" -q

这里的 -N "" 表示设置空密码(无密码)。-q 选项使过程静默。

第四章:管理现有密钥

ssh-keygen 不仅用于生成密钥,还可以用于管理已经存在的密钥文件。

4.1 修改/添加/删除私钥密码 (-p)

如果您想更改私钥的密码、为一个没有密码的私钥添加密码,或者移除现有密码,可以使用 -p 选项。

bash
ssh-keygen -p -f ~/.ssh/id_rsa

执行后,系统会提示您:

Enter file in which the key is (/home/your_user/.ssh/id_rsa): # 如果您指定了文件名,这里会显示
Enter old passphrase: # 如果密钥有密码,需要输入旧密码
Enter new passphrase (empty for no passphrase): # 输入新密码
Enter same passphrase again: # 再次输入新密码

  • 修改密码: 输入旧密码,然后输入两次新密码。
  • 添加密码: 如果密钥没有密码,它会直接提示您输入两次新密码(不会要求输入旧密码)。
  • 移除密码: 输入旧密码,然后在新密码提示符下直接按 Enter(输入空密码)。

4.2 修改公钥注释 (-c)

公钥的注释部分通常用于标识密钥的所有者和用途。您可以使用 -c 选项来修改现有密钥的注释。

bash
ssh-keygen -c -f ~/.ssh/id_rsa

执行后,系统会提示您:

Enter file in which the key is (/home/your_user/.ssh/id_rsa): # 如果您指定了文件名,这里会显示
Enter passphrase for key '/home/your_user/.ssh/id_rsa': # 如果私钥有密码,需要输入密码
Enter new comment: # 输入新的注释内容

输入新的注释内容后按 Enter,公钥文件 (id_rsa.pub) 中的注释部分就会被更新。

4.3 查看密钥指纹和详细信息 (-l, -L)

您可以使用 -l 选项来查看公钥的指纹。

示例:查看默认公钥指纹

bash
ssh-keygen -l -f ~/.ssh/id_rsa.pub

或者,如果您想查看私钥对应的公钥指纹(即使没有 .pub 文件),可以直接指向私钥文件:

bash
ssh-keygen -l -f ~/.ssh/id_rsa

输出会类似这样:

3072 SHA256:............................................. user@hostname (RSA)

显示了密钥长度、指纹(SHA256格式)、注释以及密钥类型。

OpenSSH 较新的版本也支持 -L 选项来显示密钥的详细信息,包括类型、长度、指纹、注释等。

示例:查看密钥详细信息

bash
ssh-keygen -L -f ~/.ssh/id_rsa.pub

或者:

bash
ssh-keygen -L -f ~/.ssh/id_rsa

输出格式会更详细,可能包含公钥的具体数值信息。

4.4 从私钥导出公钥 (-y)

在某些情况下,您可能只有私钥文件,而公钥文件丢失了。您可以使用 -y 选项从私钥文件中提取出对应的公钥内容。

bash
ssh-keygen -y -f ~/.ssh/id_rsa

执行后,命令会将对应的公钥内容打印到标准输出。您可以将其重定向到一个 .pub 文件中:

bash
ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub

如果私钥有密码,执行此命令时会提示您输入密码。

4.5 检查密钥的有效性

虽然 ssh-keygen 没有一个专门的“检查”命令,但尝试用 ssh-keygen -L -f <keyfile>ssh-keygen -y -f <private_key_file> 通常可以间接验证密钥文件是否损坏且格式正确。如果命令能够成功解析文件并显示信息,通常意味着密钥是有效的。

第五章:分发公钥到远程服务器

生成密钥对后,下一步是将您的公钥放置到您希望通过SSH密钥认证方式登录的远程服务器上。远程服务器上的SSH服务会查找用户家目录下的 ~/.ssh/authorized_keys 文件来验证登录请求。

最便捷的方式是使用 ssh-copy-id 命令(通常包含在OpenSSH客户端软件包中):

bash
ssh-copy-id user@remote_host

这个命令会自动将您的默认公钥 (~/.ssh/id_rsa.pub) 添加到 remote_hostuser 用户的 ~/.ssh/authorized_keys 文件中。如果 ~/.ssh 目录或 authorized_keys 文件不存在,ssh-copy-id 也会自动创建并设置正确的权限。

如果您使用了非默认的密钥文件名,可以使用 -i 选项指定要复制的公钥文件:

bash
ssh-copy-id -i ~/.ssh/github_ed25519.pub user@remote_host

执行 ssh-copy-id 时,第一次连接该服务器可能会提示您确认服务器的指纹(请务必核对,防止中间人攻击)。然后,它会要求您输入远程用户 user 的密码,以便通过密码认证登录一次,执行添加公钥的操作。一旦公钥添加成功,下次您就可以使用密钥进行认证了(如果私钥有密码,需要输入私钥密码)。

如果 ssh-copy-id 不可用,您也可以手动完成此操作:

  1. 将您的公钥文件内容复制到剪贴板:
    bash
    cat ~/.ssh/id_rsa.pub

    或者对于非默认密钥:
    bash
    cat ~/.ssh/github_ed25519.pub

    将输出的整行内容复制。

  2. 通过密码认证方式登录到远程服务器:
    bash
    ssh user@remote_host

    输入远程用户的密码。

  3. 在远程服务器上,确保 ~/.ssh 目录存在,如果不存在,创建它并设置正确权限:
    bash
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh

  4. 将您的公钥内容追加到 ~/.ssh/authorized_keys 文件中。如果文件不存在,它会被创建。使用 >> 而不是 >,防止覆盖现有内容。
    bash
    echo "粘贴您的公钥内容在这里" >> ~/.ssh/authorized_keys

    或者更方便地,使用 cat 和管道:
    bash
    cat >> ~/.ssh/authorized_keys

    然后粘贴您的公钥内容,粘贴完成后按 Enter,再按 Ctrl+D 结束输入。

  5. 设置 authorized_keys 文件的正确权限:
    bash
    chmod 600 ~/.ssh/authorized_keys

完成以上步骤后,您应该就可以使用SSH密钥登录到远程服务器了。

第六章:密钥使用的安全最佳实践

生成和管理SSH密钥时,安全性是核心。遵循以下最佳实践可以最大程度地保护您的密钥和远程连接:

  1. 保护您的私钥文件: 这是最重要的。私钥文件的权限必须设置为只有拥有者可读写(chmod 600 ~/.ssh/id_rsa)。SSH客户端在连接时会检查私钥文件的权限,如果权限设置不正确(例如其他用户可读),会拒绝使用该私钥进行认证,并给出警告。
  2. 保护 ~/.ssh 目录: 您的 ~/.ssh 目录存放了所有密钥和SSH配置文件,其权限也应受到限制。通常设置为只有拥有者有完全权限(读、写、执行),其他用户没有任何权限(chmod 700 ~/.ssh)。SSH客户端也会检查这个目录的权限。
  3. 为私钥设置强密码 (Passphrase): 虽然会带来一些不便,但强烈建议为私钥设置一个复杂且难以猜测的密码。这为您的私钥提供了一道额外的防线,即使私钥文件被盗,没有密码也无法使用。
  4. 使用 ssh-agent 管理密码: 为了解决频繁输入私钥密码的麻烦,可以使用 ssh-agentssh-agent 是一个后台运行的程序,用于缓存已解锁的私钥。您只需要在启动会话或第一次使用密钥时输入一次密码,之后就可以在当前会话中无密码使用该密钥了。ssh-add 命令用于将私钥添加到 ssh-agent 中。
    bash
    eval "$(ssh-agent -s)" # 启动 ssh-agent 并设置环境变量
    ssh-add ~/.ssh/id_rsa # 将私钥添加到 agent 中,会提示输入密码
    # 后续使用密钥就不需要输入密码了

    ssh-add -l 可以查看当前 ssh-agent 中已加载的密钥。
    ssh-add -D 可以清空 ssh-agent 中的所有密钥。
  5. 定期审查远程服务器上的 authorized_keys 文件: 确保 authorized_keys 文件中只有您允许的公钥。移除不再需要的公钥,以防止未授权的访问。
  6. 使用现代、安全的密钥类型和长度: 优先选择 Ed25519 或 ECDSA 密钥。如果必须使用RSA,确保密钥长度至少为2048位,推荐4096位。
  7. 为不同的服务或目的使用不同的密钥对: 例如,为 GitHub 使用一个密钥,为公司服务器使用另一个密钥。这样即使某个密钥泄露,也只会影响到使用该密钥的服务,限制了潜在损害的范围。

第七章:常见问题和故障排除

  1. 权限问题 (Permissions too open): 这是最常见的SSH密钥认证失败原因。SSH客户端要求私钥文件 (~/.ssh/id_rsa 等) 的权限不能过于开放(通常必须是 600 或更严格),~/.ssh 目录的权限也不能过于开放(通常必须是 700 或更严格),authorized_keys 文件权限也不能过于开放(通常必须是 600 或更严格)。

    • 解决: 使用 chmod 命令修复权限:
      bash
      chmod 700 ~/.ssh
      chmod 600 ~/.ssh/id_rsa # 或您的私钥文件
      chmod 600 ~/.ssh/authorized_keys # 在远程服务器上执行
    • 尝试连接时,如果出现权限问题,SSH客户端通常会给出明确的警告信息。使用 ssh -v user@host 进入详细模式可以帮助诊断。
  2. 私钥密码错误: 如果您为私钥设置了密码,但在使用时输入错误,SSH认证会失败。

    • 解决: 确保您输入的是正确的私钥密码。如果忘记了,且没有备份,通常无法恢复,您需要重新生成密钥对。
  3. 远程服务器上公钥未正确配置: 公钥没有被正确地添加到远程用户家目录下的 ~/.ssh/authorized_keys 文件中,或者文件/目录权限不正确。

    • 解决: 检查远程服务器上 ~/.ssh/authorized_keys 文件是否存在,内容是否包含您的公钥(整行复制粘贴,没有换行或多余空格),以及 ~/.sshauthorized_keys 文件的权限是否正确(700 for ~/.ssh, 600 for authorized_keys)。
  4. SSH配置文件问题: 本地或远程的SSH配置文件 (~/.ssh/config, /etc/ssh/sshd_config) 可能配置错误,例如禁用了 PubkeyAuthentication。

    • 解决: 检查相关配置文件。在远程服务器上,确保 /etc/ssh/sshd_configPubkeyAuthentication yes 被启用,并且 AuthorizedKeysFile 指向正确的位置(通常是 .ssh/authorized_keys)。修改配置后需要重启SSH服务。
  5. Selinuux 或 AppArmor 限制: 在某些Linux发行版上,Selinuux 或 AppArmor 安全策略可能阻止SSH服务访问用户家目录下的 .ssh 文件。

    • 解决: 检查系统日志 (/var/log/auth.log/var/log/secure) 寻找相关错误信息。可能需要调整安全策略或改变 .ssh 目录的上下文。

第八章:总结

ssh-keygen 是管理SSH密钥的强大工具。通过本文的介绍,您应该已经掌握了如何使用 ssh-keygen 来:

  • 生成不同类型和长度的SSH密钥对。
  • 为私钥设置、修改或移除密码。
  • 为公钥添加或修改注释。
  • 查看密钥指纹和详细信息。
  • 从私钥中导出公钥。
  • 将公钥分发到远程服务器。
  • 遵循SSH密钥使用的安全最佳实践。

熟练运用这些知识,将使您的远程连接更加安全、高效。在享受SSH密钥带来的便利的同时,请务必牢记保护好您的私钥,它是您数字身份的象征,一旦泄露,后果不堪设想。结合 ssh-agent 的使用,您可以平衡安全性和便捷性,实现无密码(每次连接时)的安全登录体验。

希望这篇详细的使用指南对您有所帮助!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部