如何将您现有的 SSH 密钥导入到您的 GPG 密钥中

了解如何处理多个 SSH 密钥。
133 位读者喜欢这篇文章。
Browser of things

在本系列第一篇文章中,我解释了如何使用您的 GPG 密钥来验证您的 SSH 连接。如果您和我一样,您已经拥有一个或多个现有的 SSH 密钥。而且,如果您和我一样,您也不想必须登录到您使用的每台服务器来更新 authorized_keys 文件。一种解决方法是将您现有的 SSH 密钥导入到您的 GPG 密钥中。这将消除对私钥文件的需求。这样做使我能够消除另外九个密钥文件,大大减少了我的备份/隐私足迹。

导入现有的 SSH 密钥

要添加密钥,您需要将密钥格式从 SSH 使用的 Privacy-Enhanced Mail (PEM) 编码格式转换为 OpenPGP 格式的证书。Monkeysphere Project 提供了一个实用程序 pem2openpgp,可以为您完成此操作。

不幸的是,使这个新添加的密钥成为子密钥不是一个一步到位的过程。之所以需要这个更长的过程,是因为没有干净的方法来删除密钥环中仅是 SSH 密钥的 GPG 密钥。密钥是通过密钥指纹识别和操作的,密钥的密钥指纹是相同的,无论它是子密钥还是独立密钥。值得庆幸的是,您只需要处理私钥,因为您可以在最后重新生成公钥。

此外,如果您有较新样式的 OpenSSH 密钥,您还需要执行几个额外的步骤才能将其转换为 pem2openpgp 可以读取的内容。不幸的是,截至 0.41 版本,Monkeysphere 无法读取较新样式的 OpenSSH 密钥。(如果您的私钥文件的第一行是:-----BEGIN OPENSSH PRIVATE KEY-----,则您的密钥是较新样式的密钥。如果您的密钥以:-----BEGIN RSA PRIVATE KEY----- 开头,则您拥有 PEM 编码格式。)

要导入较新的密钥,您需要将它们转换为旧式格式。这可以通过使用 ssh-keygen 并利用其以多种密钥格式写入的能力来完成。您可以通过更改密钥密码来触发转换。在这种情况下,您不必更改密码,因此如果您愿意,可以随意重用您现有的密码。

以下工作流程将引导我们完成这些步骤。

  1. 如果您有较新样式的 OpenSSH 密钥,请使用 ssh-keygen 实用程序进行转换。您可以使用此实用程序更改密码(如果您愿意)并强制密钥以旧格式重写。ssh-keygen 的典型用法与此用法的唯一区别是添加了 -m 来更改密钥格式。
    $ ssh-keygen -p -m PEM -f <private-key-file>
  2. 备份您现有的 GPG 密钥。
    $ gpg2 -a --export-secret-keys 96F33EA7F4E0F7051D75FC208715AF32191DB135 > my_gpg_key.asc
  3. 在一个新的密钥环中,导入您现有的 GPG 密钥。
    $ mkdir temp_gpg
    $ chmod go-rwx temp_gpg/
    $ gpg2 --homedir temp_gpg --import my_gpg_key.asc 
    gpg: key 8715AF32191DB135: public key "Brian Exelbierd" imported
    gpg: key 8715AF32191DB135: secret key imported
    
    # Optionally, verify the import
    $ gpg2 -K --homedir temp_gpg/
    /home/bexelbie/temp_gpg/pubring.kbx
    --------------------------------
    sec   rsa2048 2019-03-21 [SC] [expires: 2021-03-20]
          96F33EA7F4E0F7051D75FC208715AF32191DB135
    uid           [ unknown] Brian Exelbierd
    ssb   rsa2048 2019-03-21 [E] [expires: 2021-03-20]
    ssb   rsa2048 2019-03-21 [A]
  4. 将 SSH 密钥作为新的独立 GPG 密钥导入。
    # get the software
    $ dnf install -y monkeysphere
    
    # temporary_id is a temporary identifier required by GPG
    $ pem2openpgp temporary_id < .ssh/my_fancy_key  | gpg2 --import --homedir temp_gpg/
    Enter PEM pass phrase:
    gpg: key 66091F2C70AF02A9: public key "temporary_id" imported
    gpg: key 66091F2C70AF02A9: secret key imported
    gpg: Total number processed: 1
    gpg:               imported: 1
    gpg:       secret keys read: 1
    gpg:   secret keys imported: 1
    
    # verify the key loaded and get the keygrip of the new GPG key and the hash of your GPG key
    $ gpg2 -K --with-keygrip  --homedir temp_gpg/
    /home/bexelbie/temp_gpg/pubring.kbx
    --------------------------------
    sec   rsa2048 2019-03-21 [SC] [expires: 2021-03-20]
          96F33EA7F4E0F7051D75FC208715AF32191DB135
          Keygrip = 90E08830BC1AAD225E657AD4FBE638B3D8E50C9E
    uid           [ unknown] Brian Exelbierd
    ssb   rsa2048 2019-03-21 [E] [expires: 2021-03-20]
          Keygrip = 5FA04ABEBFBC5089E50EDEB43198B4895BCA2136
    ssb   rsa2048 2019-03-21 [A]
          Keygrip = 7710BA0643CC022B92544181FF2EAC2A290CDC0E
    
    sec   rsa2048 2019-03-23 [C]
          D4F6B35B52B96A092FB8F418A41A06197749FBA4
          Keygrip = 1F824257B107D9E3371B9A4957751D78FC8BB190
    uid           [ unknown] temporary_id
    
    # We can remove monkeysphere unless you need it for other reasons
    $ dnf remove -y monkeysphere
  5. 将 SSH 密钥添加为您 GPG 密钥的子密钥。
    $ gpg2 --homedir temp_gpg  --expert --edit-key 96F33EA7F4E0F7051D75FC208715AF32191DB135 
    gpg> addkey
    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
      (10) ECC (sign only)
      (11) ECC (set your own capabilities)
      (12) ECC (encrypt only)
      (13) Existing key
    Your selection? 13
    Enter the keygrip: 1F824257B107D9E3371B9A4957751D78FC8BB190
    
    Possible actions for a RSA key: Sign Encrypt Authenticate 
    Current allowed actions: Sign Encrypt 
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? s
    Your selection? e
    Your selection? a
    
    Possible actions for a RSA key: Sign Encrypt Authenticate 
    Current allowed actions: Authenticate 
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? q
    Please specify how long the key should be valid.
    Key is valid for? (0) 
    Key does not expire at all
    Is this correct? (y/N) y
    Really create? (y/N) y
    
    sec  rsa2048/8715AF32191DB135
         created: 2019-03-21  expires: 2021-03-20  usage: SC  
         trust: unknown       validity: unknown
    ssb  rsa2048/150F16909B9AA603
         created: 2019-03-21  expires: 2021-03-20  usage: E   
    ssb  rsa2048/17E7403F18CB1123
         created: 2019-03-21  expires: never       usage: A   
    ssb  rsa2048/4A9EE7790817C411
         created: 2019-03-23  expires: never       usage: A   
    [ unknown] (1). Brian Exelbierd
    
    gpg> quit
    Save changes? (y/N) y

    请注意,现在有两个身份验证子密钥。

  6. 导出您现有的带有新子密钥的 GPG 密钥。
    $ gpg2 --homedir temp_gpg -a --export-secret-keys 96F33EA7F4E0F7051D75FC208715AF32191DB135 > my_new_gpg_key.asc
  7. 将您现有的带有新子密钥的 GPG 密钥导入到您常用的密钥环中(仅子密钥将被导入)。
    $ gpg2 --import my_new_gpg_key.asc 
    gpg: key 8715AF32191DB135: "Brian Exelbierd" 1 new signature
    gpg: key 8715AF32191DB135: "Brian Exelbierd" 1 new subkey
    gpg: key 8715AF32191DB135: secret key imported
    gpg: Total number processed: 1
    gpg:            new subkeys: 1
    gpg:         new signatures: 1
    gpg:       secret keys read: 1
    gpg:   secret keys imported: 1
    gpg:  secret keys unchanged: 1
    
    # verify the input and get the keygrip (it should be the same)
    $ gpg2 -K --with-keygrip 
    /home/bexelbie/.gnupg/pubring.kbx
    ------------------------------
    sec   rsa2048 2019-03-21 [SC] [expires: 2021-03-20]
          96F33EA7F4E0F7051D75FC208715AF32191DB135
          Keygrip = 90E08830BC1AAD225E657AD4FBE638B3D8E50C9E
    uid           [ultimate] Brian Exelbierd
    ssb   rsa2048 2019-03-21 [E] [expires: 2021-03-20]
          Keygrip = 5FA04ABEBFBC5089E50EDEB43198B4895BCA2136
    ssb   rsa2048 2019-03-21 [A]
          Keygrip = 7710BA0643CC022B92544181FF2EAC2A290CDC0E
    ssb   rsa2048 2019-03-23 [A]
          Keygrip = 1F824257B107D9E3371B9A4957751D78FC8BB190
  8. 可选地,您可能想要预先指定此密钥用于 SSH。这意味着您不必使用 ssh-add 来加载密钥。为此,请在 ~/.gnupg/sshcontrol 文件中指定密钥。此文件中的条目是密钥指纹。
    ~/.gnupg/sshcontrol file.  The entries in this file are key grips
    
    # Add the new keygrip to your sshcontrol file
    $ echo 1F824257B107D9E3371B9A4957751D78FC8BB190 >> ~/.gnupg/sshcontrol

成功!

您现在可以删除旧的 SSH 私钥文件。当您尝试 SSH 连接到相应的服务器时,系统将提示您解锁您的 GPG 密钥(最好设置了密码!),然后 gpg-agent 将提供身份验证以代替 ssh-agent。您需要安全备份的文件更少,并且您的密钥管理也更容易一些。如果您需要新密钥,您可以按照之前的文章中的说明创建更多身份验证子密钥。如果您的项目结束,您可以随时删除您最终获得的任何额外的子密钥。

在第三篇也是最后一篇文章中,我将分享一些管理多个身份验证子密钥/SSH 密钥的技巧。一旦您拥有两个或三个以上的密钥,情况就会变得稍微复杂一些。

接下来阅读什么
User profile image.
Brian "bex" Exelbierd 是 RHEL 社区业务负责人,致力于通过社区努力告知 RHEL 路线图,并支持操作系统社区。在 Red Hat,Brian 曾担任技术作家、软件工程师、内容策略师、社区架构师,现在担任产品经理。

6 条评论

我想知道这一切如何与 keybase 协同工作?

据我所知,keybase.io 不支持身份验证子密钥。我不确定他们总体上对子密钥的支持程度如何。

理论上,他们应该能够扩展其 API 以支持身份验证,但需要在 ssh-agent 或 gpg-agent 中编写一个钩子。我想知道对于那些选择将其密钥存储在 keybase 上的人来说,用启用 keybase 的代理替换 gpg-agent 是否有用。

虽然我确实有一个 keybase 帐户,但没有人通过它与我互动,我也没有给他们我的私钥。

嘿 Bex,

我一直在关注您的 ssh 博客文章,感谢您,它们写得很好!

在执行这些步骤时,我在将较新样式的 ssh 密钥转换为 PEM 格式时遇到了问题。由于当我使用您在文章中使用的 -p 选项进行转换时,没有错误或输出,因此它并没有立即显现出来,所以我只是假设它已被转换并在步骤中继续前进。

似乎无法将 ED25519 密钥类型更改为 PEM 格式

$ ssh-keygen -e -m PEM -f .ssh/my_special_key_id_ed25519
do_convert_to_pem: 不支持的密钥类型 ED25519

我找不到任何关于此错误的信息,只是想知道您有什么想法吗?

嗨 Blake,据我回忆,monkeysphere 项目可以使用 pem2openpgp 处理大多数格式,但并非所有格式。您尝试过吗?如果没有,我鼓励您与上游进行沟通。

回复 作者:Blake

> 而且,如果您和我一样,您也不想
> 必须登录到您使用的每台服务器来更新
> authorized_keys 文件。一种解决方法是将
> 您现有的 SSH 密钥导入到您的 GPG 密钥中。

您提出了这个说法,但随后没有任何内容解释如何将我的私有 SSH 密钥放入我的 gpg 密钥库会自动授予我访问计算机的权限,而无需将我的公钥放入 authorized_keys 文件中,作为明确声明哪些私钥被授权访问的措施。这需要我至少登录一次以更新 authorized_keys 文件。

我真的无法理解您的说法。您能详细说明一下它是如何工作的吗?

嗨 @boxofrox

如果您将现有的 SSH 密钥导入到您的 GPG 密钥中,您并没有更改您的密钥。因此,任何已经在其 authorized_keys 文件中设置了您的 SSH 密钥的机器都将继续与新的 GPG 存储密钥一起工作。

您包含的引文旨在表示您不必更新您已授权的主机。没有系统可以为您自动处理此事,您始终必须执行登录或 ssh-key-copy 才能进行初始设置。

在本系列的第三部分中,我将讨论管理多个导入的 SSH 密钥以避免密钥尝试失败。

回复 作者:boxofrox (未验证)

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 获得许可。
© . All rights reserved.