如何使用 OpenSSL 获得“百万轮 PKCS#8 + PBKDF2”?

信息安全 密码学 密码管理 openssl
2021-08-19 11:59:34

我发布了这个问题受密码保护的 SSH 私钥是否容易受到字典攻击?几天前。

最终答案的摘录:

使用 PKCS#8 + PBKDF2 和一百万轮(OpenSSL 需要一些哄骗来产生它),您可以获得 20 位(因为 2 20大约等于一百万)。

...

openssl 命令行工具不允许选择迭代次数——但 OpenSSL 库支持它(OpenSSH 也支持,因为 OpenSSH 使用 OpenSSL)。生成加密的密钥文件需要一些编程(使用适当的参数调用库)。

现在,有没有人知道任何可以完成上述任务的现有实用程序?如果没有,有人可以编写这样的程序并为了所有人的利益将其公开......因为我相信其他人也会发现它有用吗?

(我对安全性、密码学​​、密钥格式和相关主题完全陌生,而且对 OpenSSL 的源代码一点也不熟悉,因此无法让 OpenSSL 做一些它还没有做的事情。)

1个回答

最简单的方法还是打补丁OpenSSL,即命令行工具(不是库)。演练(假设是 Linux 主机):

下载OpenSSL 源代码获取最新的,页面以红色显示(现在,版本 1.0.1g)。

解压到某个目录:

cd /tmp
tar xvzf ~/Downloads/openssl-1.0.1g.tar.gz

编辑源文件/tmp/openssl-1.0.1g/apps/pkcs8.c:搜索字符串“iter”,直到你想找到这些行:

            else if (!strcmp (*args, "-noiter"))
                    iter = 1;
            else if (!strcmp (*args, "-nocrypt"))
                    nocrypt = 1;

这是 1.0.1g 版本中的第 158 行。编辑这些行,使它们看起来像这样:

            else if (!strcmp (*args, "-noiter"))
                    iter = 1;
            else if (!strcmp (*args, "-iter"))
                    {
                    if (!args[1]) goto bad;
                    iter = atoi(*(++args));
                    if (iter <= 0) goto bad;
                    }
            else if (!strcmp (*args, "-nocrypt"))
                    nocrypt = 1;

换句话说,只需添加处理名为“-iter”的新命令行参数的 6 行。保存文件。

然后编译代码:

cd /tmp/openssl-1.0.1g
./config --prefix=$HOME/local
make
make test
make install

您在主目录的子目录中有一个全新的openssl命令行工具和库local(您可以使用该选项将其放在您希望的任何位置--prefix,但在您的主目录中写入不需要root访问,也不会干扰您的操作系统提供工具)。命令行工具命令pkcs8现在有一个-iter可用于选择迭代次数的选项:

$HOME/local/bin/openssl genrsa -out rsaraw.pem 2048
$HOME/local/bin/openssl pkcs8 -topk8 -v2 aes128 -iter 1000000 -in rsaraw.pem -out rsapk8.pem

生成的文件可以与完全标准的 OpenSSL 或 OpenSSH 一起使用,因为该库一直支持 PBKDF2 的一百万次迭代。在这里,我们只是修补了命令行工具,以便能够设置迭代次数。查看生成的对象将表明确实考虑了迭代计数:

openssl asn1parse -i -in rsapk8.pem

将显示以下内容:

  0:d=0  hl=4 l=1312 cons: SEQUENCE          
  4:d=1  hl=2 l=  74 cons:  SEQUENCE          
  6:d=2  hl=2 l=   9 prim:   OBJECT            :PBES2
 17:d=2  hl=2 l=  61 cons:   SEQUENCE          
 19:d=3  hl=2 l=  28 cons:    SEQUENCE          
 21:d=4  hl=2 l=   9 prim:     OBJECT            :PBKDF2
 32:d=4  hl=2 l=  15 cons:     SEQUENCE          
 34:d=5  hl=2 l=   8 prim:      OCTET STRING      [HEX DUMP]:A4E21F4F210DEB6F
 44:d=5  hl=2 l=   3 prim:      INTEGER           :0F4240
 49:d=3  hl=2 l=  29 cons:    SEQUENCE          
 51:d=4  hl=2 l=   9 prim:     OBJECT            :aes-128-cbc
 62:d=4  hl=2 l=  16 prim:     OCTET STRING      [HEX DUMP]:DAA184B3F6CC303B6A40A131E5C8C451
 80:d=1  hl=4 l=1232 prim:  OCTET STRING      [HEX DUMP]:2C15CF37D5ACC537AA92B
 (...)

看到“ 0F4240”了吗?那是一百万,以十六进制表示。

补丁是微不足道的;我会尝试将它提交给 OpenSSL 维护者。