【问题标题】:Automate Splitting a PEM File into multiple Certs自动将 PEM 文件拆分为多个证书
【发布时间】:2014-09-24 00:46:02
【问题描述】:

我需要找到一种方法来自动化将 PEM 文件拆分为多个 PEM 文件的过程。我正在考虑使用一个批处理脚本来抓取 PEM 并在每次找到时进行分离:

-----开始证书-----

-----结束证书-----

不过,这似乎有点“骇人听闻”。我希望 OpenSSL 有一个工具可以做到这一点,但我似乎找不到任何东西。

最好的方法是什么?

【问题讨论】:

标签: batch-file ssl scripting openssl certificate


【解决方案1】:

我遇到了类似的问题,csplit 似乎很合适。

以下一行查找-----BEGIN 模式并基于它(任意次数)拆分为单独的文件:

$ csplit -sz private.pem '/.*BEGIN/' '{*}'

【讨论】:

    【解决方案2】:

    我希望 OpenSSL 有一个可以做的工具

    我不知道有什么 OpenSSL 功能或 OpenSSL 工具可以做到这一点。查看源代码,PEM_bytes_read_bio 可能是执行此操作的功能。但它没有记录,所以我不确定。 (函数名称以大写字母开头 - PEM_*。各种小写字母 - pem_* 是私有的,不应使用)。

    如果你有OpenSSL sources 方便,那么解析例程的源代码在<openssl src>/crypto/pem/pem_lib.c 中。这就是实现PEM_bytes_read_bio 的地方。


    但是这似乎有点“hacky”。​​

    好吧,它并没有那么老套——你必须卷起袖子来编写代码。您也许可以使用 Bison 和 Flex 来创建解析器和词法分析器。你如何从 shell 中调用它是另一回事。使用词法分析器,我认为您可以在 O(n) 中解析 PEM 对象。


    我需要找到一种方法来自动化将 PEM 文件拆分为多个 PEM 文件的过程...最好的方法是什么?

    我在PEM Pack 为 Crypto++ 写过类似的文章。它增加了对 PEM 编码密钥的支持,包括加密密钥。 Crypto++ 是一个 C++ 库,但相同的通用算​​法应该适用于您选择的语言。

    Crypto++ 中感兴趣的例程称为PEM_NextObject,它位于源文件pem-rd.cpp 中。您可以在页面底部的 ZIP 文件中找到源文件。 PEM_NextObject 找了四个项目:

    • 领先-----BEGIN
    • 以下-----
    • 尾随-----END
    • 以下-----

    我使用了四个索引 - 每个标记一个。我会一次读取 64+1 个字节,因为 OpenSSL 以 64 个字符输出中断。我会将一行读入string 并将字符串连接到一个累加器中。然后我会使用find 在累加器中定位令牌(有些人放弃,因为它们是安全字符串)。如果我没有找到特定的索引,我会阅读另一行。

    搜索token时,第一个token的搜索从位置0开始。下一次搜索是在找到上一个索引之后开始的。例如,对索引 2 的搜索从索引 1 加上令牌的大小开始;并且对索引 3 的搜索从索引 2 加上令牌的大小开始。如果找不到标记,我只搜索当前行和 10 个字符,以防标记跨越先前读取和当前读取。

    我使用索引而不是迭代器,因为如果容器的大小增加,迭代器就会失效。串联会导致这种情况。幸运的是,索引总是有效的,因为它只是从字符串开头的偏移量。在 bash(或任何你选择的)中你可能没有这个问题。

    如果我读到流的末尾但没有找到所有四个索引,那么我会抛出错误。

    如果我找到了所有四个索引,那么我就有了一些声称是 PEM 编码的东西。我丢弃了所有前导字符,并修剪了尾随空格。所以 PEM 对象位于 (Index1)(Index4 + 5) (+5 表示尾随 -----)。

    因为我可能解析了无效的 PEM 对象(即 -----BEGIN FOO----------END BAR-----),所以我需要另一个例程来对解析的 PEM 对象的类型进行分类。该函数称为PEM_GetType

    该算法应该运行良好,因为从算法分析的角度来看它并不令人震惊,而且 PEM 对象通常很小(小于 2K 或 4K)。我认为分析是O(n + m*10),其中m是文件中的行数。 m*10 是基于扫描 64 个字符的行以查找具有 10 个字符“倒带”的令牌,读取另一行,然后再次扫描令牌。回想一下,如果令牌跨行,我会“倒带”一点。

    如果没有 PEM 对象且文件很大,则此算法执行正常。我很确定它在最坏的情况下也以 O(n + m*10) 运行。 如果n >>> m,那么它本质上是一个O(n)函数,因为m*10只是一个很大的边界c

    您可能还对 Server Fault 上的 How to split a PEM file 和 Stack Overflow 上的 Where is the PEM file format specified? 感兴趣。


    -----BEGIN CERTIFICATE----- 到 -----END CERTIFICATE-----

    当您显示证书时,还有其他类型的对象。例如,公钥和加密私钥。 如果您需要解密一个加密的密钥,那么您需要解除/借用/使用 OpenSSL 的EVP_BytesToKey

    EVP_BytesToKey 是一种非标准,因此它变成了复制/粘贴操作以确保互操作性。我似乎记得 EVP_BytesToKey 相当于 PKCS#5 派生 if EVP_BytesToKey 产生的字节数为 16 或更少。如果生成了 17 个或更多,则 OpenSSL 使用“非标准”扩展。


    如果您对测试感兴趣,请查看pem-create-keys.sh。它会创建格式错误的 PEM 编码密钥(不是证书)。例如,它将不带换行符连接多个键,它会删除一个尾随破折号,它会删除一个尾随破折号,然后连接另一个键。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-05
      • 2010-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多