我可以更改哪些具体参数以使受密码保护的私有 gpg 密钥更安全

信息安全 密码 密码学 蛮力 gnupg 密码
2021-08-28 08:30:17

有几个问题讨论了受密码保护的私有 gpg 密钥对暴力攻击的抵抗力。看来,这样的讨论可以永远持续下去。

我不想再开始这些无休止的讨论,我只想问一下我可以更改哪些具体选项/参数,gpg.conf以使我的受密码保护的私有 gpg 密钥更安全。

据我了解,选择默认选项主要是为了兼容性,而不是最大的安全性。例如,默认的迭代次数s2k-count是 65536,因此即使是慢速 arm 处理器也可以以毫秒为单位进行计算。

我不在乎慢臂处理器。我宁愿再等 100 毫秒,然后让我的密码重复65011712几次。

我不是加密专家。有人可以建议其他可以从默认值更改的选项吗?目前,我的 gpg.conf.

cipher-algo AES256
s2k-count 65011712

我正在gnupg 1.4.12使用Debian Wheezy

更新(赏金):

除了cipher-algo并且s2k-count我可以更改之外,真的没有其他参数可以使我的受密码保护的密钥更能抵抗潜在的(暴力)密码攻击吗?

特别是,我不喜欢用于散列密钥的默认算法是SHA1. 这个算法是不是已经过时了?

我不应该s2k-digest-algo SHA256改用吗?还是有充分的理由使用SHA1(即哈希大小)?

4个回答

s2k 的合理默认值

您可以调整多个参数。通常s2k-mode应该保持它的默认值 3:这在应用摘要功能期间同时使用盐并重复盐和密码。进一步的参数是对称加密s2k-cipher-algo算法s2k-digest-algos2k-count所有这些选项都可以在 GnuPG 配置文件~/.gnupg/gpg.conf或命令行中设置(--例如,前缀为--s2k-digest-algo)。

对于三个“可调”选项,您必须平衡执行时间和安全性。

  • s2k-cipher-algo:由于要加密的数据量非常小,因此在加密上花费多少开销并没有显着差异。默认值AES128应该没问题,但是如果我们不会遭受显着更高的计算工作量,为什么不使用额外的安全边际呢?

  • s2k-digest-algos2k-count影响尝试破解密码时花在散列上的时间。默认的 SHA-1 有一些已知的弱点并且被认为是过时的,所以选择一些 SHA-2 套件的算法。在写这个答案时,65011712 次重复和 SHA512 导致每个解密操作都需要一个显着的延迟,但在我的移动 Core i7 上远低于一秒;如果解密的密钥无论如何都被缓存,那么gpg-agent可能有人可以忍受。

    我不知道这里讨论了合理的默认值,通常建议是使散列尽可能昂贵。

我不在乎慢臂处理器。我宁愿再等 100 毫秒,然后让我的密码重复 65011712 次。

如果您真的不介意,“重型”配置将是

s2k-mode 3              # default anyway
s2k-cipher-algo AES256
s2k-digest-algo SHA512
s2k-count 65011712

对于仍然完全正常但速度更快的配置,通过使用较小的s2k-countor值来减少散列的计算工作量SHA256AES128 作为密码很好,但不会导致显着更快的计算。

使用这些默认值进行私钥加密

TL;DR:您需要再次触发保存密钥(例如通过更改密码),因为导出只是从硬盘转储。GnuPG 2.1(现代)受到一个错误的影响。

更长的版本:

您必须区分 OpenPGP/GnuPG 中摘要算法的几种用途。

OpenPGP 指纹

为了计算指纹,OpenPGP要求使用 SHA1 对密钥进行哈希处理,您可以在RFC 4880, Section 12.2, Key IDs and Fingerprints中阅读:

V4 指纹是八位字节 0x99 的 160 位 SHA-1 哈希,后跟两个八位字节的数据包长度,然后是从版本字段开始的整个公钥数据包。

没有选择或可能对此进行配置。我们将进一步观察这一点。

修改检测码包

所述改变检测码的分组也使用SHA-1散列来保护加密的消息从被操纵,没有选择留给进行配置。这与进一步的讨论无关,我只是为了完整性而提到它。

对称加密的会话密钥和数据包

这些包既用于为公钥加密的“普通”OpenPGP 消息(其中它们再次包含文字数据包),也用于使用密码加密的消息。

在第一种情况下,对称密钥使用 RSA 等非对称算法加密,不涉及密码(或此类密码的散列)。

它还可以用于基于密码对消息进行对称加密,例如 using gpg --symmetric,它将要求输入密码并从 STDIN 进行加密。pgpdump类似于 `gpg --list-packets 的工具,但有时提供更合适的输出)输出这样的消息看起来像

$ echo "foo" | gpg --passphrase "bar" --symmetric | pgpdump
Old: Symmetric-Key Encrypted Session Key Packet(tag 3)(13 bytes)
    New version(4)
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA1(hash 2)
        Salt - 1d cd 72 c8 c3 30 df 84 
        Count - 65536(coded count 96)
New: Symmetrically Encrypted Data Packet(tag 9)(26 bytes)
    Encrypted data [sym alg is specified in sym-key encrypted session key]

观察string-to-key程序的设置:摘要算法(默认为 SHA1)和 mangle 计数。这些可以使用--s2k-digest-algo和进行配置--s2k-count让我们看看如果我们将它们设置为 SHA512 和最大值 65011712 会发生什么:

$ echo "foo" | gpg --passphrase "bar" --s2k-digest-algo SHA512 --s2k-count 65011712 --symmetric | pgpdump
Old: Symmetric-Key Encrypted Session Key Packet(tag 3)(13 bytes)
    New version(4)
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA512(hash 10)
        Salt - ea 62 a1 ff 0b 2b f6 6a 
        Count - 65011712(coded count 255)
New: Symmetrically Encrypted Data Packet(tag 9)(26 bytes)
    Encrypted data [sym alg is specified in sym-key encrypted session key]

我们使用这些选项成功地更改了密码修改--s2k-...选项。

受密码保护的导出密钥

现在,让我们再看看该string-to-key过程的另一种用途,即加密导出的密钥。RFC 4880, 5.5.3。Secret-Key Packet Formats表明string-to-key应该使用相同的过程,但实际上,--s2k-digest-option不再--s2k-count有任何效果:

$ gpg --s2k-digest-algo SHA512 --s2k-count 65011712 --export-secret-subkeys 0xDEADBEEF | pgpdump
[snip]
Old: Secret Subkey Packet(tag 7)(510 bytes)
    Ver 4 - new
    Public key creation time - Mon Jun  1 16:06:06 CEST 2015
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - ...
    RSA e(17 bits) - ...
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA1(hash 2)
        Salt - ab 7d c8 36 6a 67 4d dd 
        Count - 65536(coded count 96)
    IV - e9 76 d3 c4 b0 de 24 3c 
    Encrypted RSA d
    Encrypted RSA p
    Encrypted RSA q
    Encrypted RSA u
    Encrypted SHA1 hash
[snip]

这实际上让我困惑了好一阵子

不过,解决方案相当简单:只需按原样gpg --export导出密钥。secring.gpg设置选项gpg --edit-key(通过参数或gpg.conf文件)并随后使用passwd触发器更改密码短语,将加密密钥写入到另一端secring.gpg- 瞧,密钥按照我们想要的方式加密,我们甚至不必设置--s2k-...导出期间的选项:

$ gpg --export-secret-subkeys 0xDEADBEEF | pgpdump
[snip]
Old: Secret Subkey Packet(tag 7)(510 bytes)
    Ver 4 - new
    Public key creation time - Mon Jun  1 16:06:06 CEST 2015
    Pub alg - RSA Encrypt or Sign(pub 1)
    RSA n(1024 bits) - ...
    RSA e(17 bits) - ...
    Sym alg - CAST5(sym 3)
    Iterated and salted string-to-key(s2k 3):
        Hash alg - SHA512(hash 10)
        Salt - e1 82 c3 9f 07 74 7f 0c 
        Count - 65011712(coded count 255)
    IV - 97 20 69 ae 8d ec 0d 3c 
    Encrypted RSA d
    Encrypted RSA p
    Encrypted RSA q
    Encrypted RSA u
    Encrypted SHA1 hash
[snip]

GnuPG 2.1(现代)

截至 2015 年 6 月 1 日,GnuPG 2.1(“现代”分支)受到错误的影响(GnuPG 问题 #1800):在这里,gpg-agent负责所有这些操作,但根本不关心--s2k-...选项。这应该很快得到解决,因为 GnuPG 的主要开发人员 Werner Koch 已经将该错误标记为紧急。

您的 GnuPG 配置参数已经足够强大。关于 SHA-1 的弱点,实际上它们并不像人们想象的那么重要。来自GnuPG 手册

尽管 SHA-1 算法也显示出弱点,但创建冲突仍然非常困难且耗时。实施原像攻击仍然遥不可及。因此,对于 GnuPG 的标准使用,基于 SHA-1 的签名仍然可以。为了为未来的发展做好准备,GnuPG 正在向前发展,并且一些默认值已更改为更喜欢 SHA-256 而不是 SHA-1。如果几年后现代 GnuPG 版本的安装代码库足够大,那么我们准备弃用 SHA-1。

也许这不是您正在寻找的确切答案,但是如果您想加强您的 GnuPG 安装,我的建议是将私钥存储到加密磁盘中,尤其是为私钥选择一个强密码(以及密钥文件容器,不同于 GnuPG 密码)。强密码的基本规则是:

  1. 由小写和大写字符、数字和符号组成
  2. 随机的,即尽可能不显示任何可预测的模式
  3. 越长越好
  4. 只储存在你的脑海中

您必须在第 2 点和第 4 点之间找到折衷方案,因为看起来随机的密码短语很难记住。

如果有人可以窃取您的加密密钥,那么他们就可以读取您的私人文件:他们很可能可以在您的机器中执行代码并嗅探您的密钥密码(无论多么强大)。

带有外部键盘GnuPG 智能卡可同时保护卡和密码。

编辑:您还可以修补 GPG 以允许更高的 s2k 计数值。

你可以在 ~/.gnupg/gpg.conf 中加入一些偏执的选项。检查我的。它强制 gpg 使用强大的 AES 算法,在将密码用作密钥之前对您的密码进行 20000000 次哈希处理,这使得暴力攻击变得更加困难。

s2k 密码算法 AES256
s2k-digest-algo SHA256
密码算法 AES256
摘要算法 SHA256
s2k 计数 20000000
s2k 模式 3
强制-MDC