为什么 PGP 主密钥只有一个子密钥,并且默认将认证与签名绑定?

信息安全 加密 密码学 公钥基础设施 pgp
2021-09-02 21:23:23

在了解了有关 PGP 子密钥以及如何拆分 (S) 签名、(E) 加密、(A) 身份验证和 (C) 认证的角色的更多信息后,我发现在大多数情况下(?)默认主密钥有一个子密钥分离出加密的工作:

pub  2048R/AAAAAAAA  usage: SC
sub  2048R/BBBBBBBB  usage: E

在这里,AAAAAAAA是万能钥匙。S允许签署内容,C允许创建新的子密钥。(这样做的一个好处是您可以提供AAAAAAAA更长的到期时间BBBBBBBB,然后创建一个新的加密密钥,AAAAAAAA因为它具有C使用权限。)

但是,在我看来,对于在单台机器上工作的用户来说,以下内容的安全性并不低,但为希望从例如工作和家庭接收加密邮件的用户提供更高的安全性:

pub  2048R/AAAAAAAA  usage: C
sub  2048R/BBBBBBBB  usage: E
sub  2048R/CCCCCCCC  usage: S

使用此设置,主密钥AAAAAAAA无法签名/验证或加密/解密,但可以收集信任。因此,您可以给主AAAAAAAA密钥更长的到期时间,并使用它来添加新的子密钥。到那时,如果没有BBBBBBBB主密钥,将导出并导出CCCCCCCC到一台单独的工作计算机,该计算机移动更多且安全性较低,如果工作计算机受到破坏,则可以撤销子密钥并添加新密钥,而不会失去任何声誉。

(当然,您甚至可以将主证书密钥的秘密部分保存在超级安全的秘密掩体中。)

我知道通过 GUI 进行设置似乎是不可能的(他们似乎并不热衷于查看或编辑子键,更不用说控制主键能做什么和不能做什么),但我的问题是:

现有的 PGP 实现没有这样做是否有特定的原因?将密钥导出到没有认证权限的其他机器似乎是一个巨大的安全胜利。(如果只有 GUI 让它变得更容易。)我唯一可能的想法是导入带有残缺主密钥的秘密子密钥可能没有得到广泛支持,正如--export-secret-subkeys(在gpg(1)手册页中)暗示的那样:

--export-secret-keys

--export-secret-subkeys
       Same  as --export, but exports the secret keys instead.  This is
       normally not very useful and a security risk.  The  second  form
       of  the  command  has  the special property to render the secret
       part of the primary key useless; this  is  a  GNU  extension  to
       OpenPGP  and  other  implementations can not be expected to suc‐
       cessfully import such a key.  See the option  --simple-sk-check‐
       sum  if  you  want  to import such an exported key with an older
       OpenPGP implementation.

编辑:看起来 Debian 也遵循同样的做法?https://wiki.debian.org/subkeys

3个回答

我对这个问题有两种观点:一种是基于历史事实(并且有点技术性),而另一种纯粹是我自己的原创观点。

无论如何,使用单独的密钥进行签名似乎确实更安全,或者至少更方便;这样,您只使用您的主密钥进行认证(并且可以将其存储起来),如果您的密钥被泄露,您不必再次检查所有认证过程(IRL 会议)。

史实

在仔细查看了 GnuPG 稳定版本(1.4 和 2.0)的 C 源代码后,我发现负责设置公钥默认能力的函数;代码(在文件中g10/misc.c)如下所示:

476 int
477 openpgp_pk_algo_usage ( int algo )
478 {
479     int use = 0;
480
481     /* They are hardwired in gpg 1.0. */
482     switch ( algo ) {
483       case PUBKEY_ALGO_RSA:
484           use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
485                  | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
486           break;
487       case PUBKEY_ALGO_RSA_E:
488           use = PUBKEY_USAGE_ENC;
489           break;
490       case PUBKEY_ALGO_RSA_S:
491           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
492           break;
...
509       default:
510           break;
511     }
512     return use;
513 }

我发现这个函数是因为我首先查看了密钥生成是如何完成的(g10/keygen.c);确实在(子)密钥生成期间,GnuPG 可能会为密钥提供“角色”。创建主密钥后,您无法更改其功能。

源代码并没有说明太多(除了用于签名的 RSA 密钥还带有认证能力),但运行网络搜索评论(上面的第 481 行)导致我在 2005-08-03 上发布消息在gnupg-users邮件列表中,

GnuPG 还没有区分 C 和 S。所以有一种选择它的方法没有多大意义。

因此,这些默认设置的存在似乎只是因为GnuPG 过去不区分签名密钥和证书密钥。

此外,正如Simon Richter 指出的那样,这些默认设置可能由于DSA而存在:

很长一段时间以来,gpg 默认使用 DSA 密钥,该密钥只​​能用于签名,然后必须附加一个 elGamal 子密钥(只能用于加密)才能获得功能齐全的密钥。

对于 RSA,这不是必需的,但由于某种原因它被保留了。

“仅签名”或“仅加密”RSA 子类型不是算法的技术限制。

原始事实

如今,我认为唯一的原因(默认主键功能设置为SC而不是C单独设置)是帮助普通用户验证签名

假设您的密钥环中有这两个密钥:

pub  4096R/00000001  1970-01-01       usage: C
uid                  Alice Owl
sub  4096R/AE687A0C  1970-01-01       usage: S
sub  4096R/F77A9AF1  1970-01-01       usage: E

pub  4096R/FFFFFFFE  1970-01-01       usage: CS
uid                  Bob Penguin
sub  4096R/00FF42CD  1970-01-01       usage: E
  • Alice Owl是一个普通的 GnuPG 用户,她对 OpenPGP 很有信心,并生成了一个带有 GnuPG--expert标志的密钥对,因此她可以设置自己的密钥能力。主键当然C有标志,但她用子键签署文件。
  • Bob Penguin对密码学几乎一无所知。他唯一想要的就是一点隐私/亲密。他像任何普通用户一样生成了他的密钥(没有触及他不理解的任何设置)。

现在,让我们假设您(读者)也是初学者。您会收到来自 Alice 和 Bob 的签名文件。您了解 的基础知识gnupg,尤其是:

  • 用户用他们的主键标识:
    • 所以我知道Alice 是00000001,我也知道Bob 是FFFFFFFE
  • 可以使用 GnuPG--verify--verify-files选项来验证消息。

现在,让我们验证他们发送给您的文件。

$ gpg --verify from-bob.txt.asc
gpg: Signature made <date> using RSA key ID FFFFFFFE
gpg: Good signature from "Bob Penguin"

$ gpg --verify from-alice.txt.asc
gpg: Signature made <date> using RSA key ID AE687A0C
gpg: Good signature from "Alice Owl"

等等,什么?我以为爱丽丝的钥匙是00000001

事实上,文件上的签名不一定是使用万能钥匙进行的;它们是使用具有签名能力的密钥 ( S) 制作的。初学者不太可能知道这一点。


也许实际的解释与这个假设无关(“使用SC密钥的初学者越多,对其他初学者来说就越好”),但这是我能在不打扰 GnuPG 贡献者的情况下提出的唯一解释。

蒂蒂对历史背景的看法几乎是正确的,但真正的历史原因在于他/她省略的部分。

很长一段时间以来,gpg 默认使用 DSA 密钥,该密钥只​​能用于签名,然后必须附加一个 elGamal 子密钥(只能用于加密)才能获得功能齐全的密钥。

对于 RSA,这不是必需的,但由于某种原因它被保留了。

“仅签名”或“仅加密”RSA 子类型不是算法的技术限制。

当您为签署数据和签署证书制作不同的密钥时,“签署您的密钥”的人实际上必须签署您的证书密钥,而不是您的数据签名密钥;否则,信任网络不会通过您的密钥进行网络连接。但是,当您签署电子邮件时,您使用的是您的数据签名密钥,而不是您的证书密钥,这就是您在电子邮件中复制的数据签名公钥。

因此,分离签名和认证密钥是可行的,但需要相关人员和/或软件实现对他们签署和分发的内容更加小心。我可以想象你可能会遇到可用性问题。