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

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

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

导入现有的 SSH 密钥

要添加密钥,您需要将密钥格式从 SSH 使用的隐私增强邮件 (PEM) 编码格式转换为 OpenPGP 格式的证书。Monkeysphere 项目提供了一个实用程序 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 (未验证)

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.