【问题标题】:How to create an ASN.1 DER-encoded blob simply如何简单地创建 ASN.1 DER 编码的 blob
【发布时间】:2011-04-07 22:38:07
【问题描述】:

您好,

如何将一些二进制数据简单地编码为 ASN.1 DER 编码的 blob?我正在使用 C/C++,我认为应该可以简单地在二进制 blob 前面加上一些适当的字节,这些字节表示数据的类型是八位字节字符串并且具有给定的长度(并且在长度为 1 的序列中)猜)。

感兴趣的背景:

我为什么要以这种方式滥用 ASN.1?对于一个研究项目,我需要在具有关联 X.509 证书的数字签名中嵌入一些数据。 (如果重要的话,我在 Peter Gutmann 的 cryptlib 库中使用 createSignatureEx 来创建符合 CMS / S/MIME-2/3 / PKCS-#7 的签名。我没有对要编码的数据进行签名,只是将其添加为元数据到签名以丰富它。)据我了解,具有任意扩展数据的严重签名需要使用ASN.1 DER对扩展数据进行编码。我的数据是二进制 blob,仅对我的应用程序有用,因此对数据的每个部分进行正确的 ASN.1 编码没有真正的价值。我想通过一些工作我可以学会使用 asn1c 来做到这一点,但它看起来很复杂,而且我快到最后期限了。同样重要的是,这似乎是不必要的,而且这些信息似乎对其他想要避免正确 ASN.1 编码的痛苦的开发人员有用。

谢谢!

【问题讨论】:

  • 如果我正确理解了luca.ntop.org/Teaching/Appunti/asn1.html 的第 5.10 节,对于短 blob,我可以通过前缀“04 08”将它们编码为八位字节流。据推测,这只适用于长度为 127 左右的 blob。他们说“01 23 45 67 89 ab cd ef”DER 原始编码为“04 08 01 23 45 67 89 ab cd ef”。谁能验证我的理解?这足以制作有效的 ASN.1 流吗?对于长度不超过 64k 或 32k 的 blob,这种情况有何变化?
  • ans.1 不使用字节边界。例如,如果你有一个结构并且一个元素是 6 个元素的枚举,它只会占用 3 位。如果下一个元素是字节,则 5 位将占用该字节的剩余空间。
  • 如果你一天之内需要它,你可以构建一个基于变异的模糊器。因此,获取一个真正的 ASN.1 编码结构并对其进行迭代并开始将半字节设置为 0x0 或 0xF,您可以尝试一次执行一个字节或 2 位,甚至只是翻转每个位。这取决于您的测试工具有多快……Peach 是一个非常酷的项目。

标签: c++ c security blob asn.1


【解决方案1】:

我会使用ASN.1 Compiler

人们滥用 ASN.1,因为它是一种编码数据结构的方法。任何时候你有一个 C/C++ 程序使用攻击者控制的数据结构,比如:缓冲区溢出和整数溢出,开始发挥作用。 ASN.1 并不比 XML 或 JSON 或 bencode 更不安全,因为这些都是可能的故障点。编码库本身可能存在问题,例如nasty Microsoft vulnerability. 但无论您使用哪种编码方法,此陈述都是正确的。 ASN.1 是一个不错的选择,因为生成的消息非常小,而且它是我所知道的任何编码方法中最有效地利用空间的方法。

【讨论】:

  • 有趣。我可以看到正确编码所提供的保护价值。但这只是一个研究项目,我需要在昨天完成这项工作。如果可以的话,我正在尝试避免使用所有样板代码等来使用 asn1c。如果我使用 asn1c,无论如何我都会将其编码为二进制 blob(八位字节字符串)。请不要惊慌失措;我是一名安全研究员,但这只是需要完成。
  • @Paul 作为一名安全研究员,我不知道您要完成什么。
  • @Paul,听起来您正在尝试编写 ASN.1 模糊器,祝您一天之内好运。如果您攻击的应用程序比您需要了解所有 ASN.1 结构,例如专门针对 X.509 的处理。
  • 啊。不,我不是要攻击什么。我只是想用一些我声称提供安全价值的额外数据来增强数字签名(我不能说更多)。 Fuzzing 可能会发现有效输入,但我今天早些时候对编译器进行了快速旋转,我想我会这样做。最初我只会编码为单个八位字节字符串,然后也许以后我会喜欢并正确编码我的结构。关于如何清理 asn1c 输出以进行颠覆的任何建议?它正在生成 60 个文件,我希望不要将它们全部检入。
  • 顺便说一句,使用 asn1c (正是我问如何避免这样做:))是我最终选择的路径,它比我预期的要容易,但仍然需要几个小时(然后是当我做了更详细的事情时,还有更多)。所以如果没有更好的答案出现,我会接受这个。
【解决方案2】:

您不能只是将 ASN.1 的 blob 附加到 X.509 证书并期望它成为证书的一部分。该证书是一个 ASN.1 值序列,因此它以一个 SEQUENCE 标记和一个长度开始,它包含所有证书。

如果您想在证书结构中添加一个字段(这可能意味着它不再是有效的证书,但仍可能是有效的 ASN.1 结构),那么您将不得不更改该字段的长度封闭序列以及附加数据。

是的,04 08 01 23 45 67 89 ab cd ef 是八位字节字符串的有效 DER 编码。开头的 04 是 OCTET STRING 的标记,08 是字符串的长度。请注意,最多 127 的长度被编码在一个字节中,并且更大的长度使用更长的编码。

有关 ASN.1 的良好介绍——尤其是它在加密消息中的使用——请参阅“ASN.1、BER 和 DER 子集的外行指南”,您应该可以在rsa.com 网站。

【讨论】:

  • 啊,我想我明白你在想什么了。我不只是在数字签名上添加一些 ASN.1 编码位。我正在使用加密库 cryptlib,它允许我指定任意证书扩展,因为它们是 ASN.1 格式的对象,使用如下函数: int cryptAddCertExtension( const CRYPT_CERTIFICATE certificate, const char *oid, const int criticalFlag, const void *extension, const int extensionLength );
  • 我的 ASN.1 被接受,我的 oid(1 2 3 4 5 或 1 2 3 4 6,都来自他们的测试代码)被接受,但是当实际创建签名的位时,库我的段错误。 add 函数确实拒绝至少一些 OID,但我不知道检查是否彻底(也不知道是否可以)。您认为无效的 OID 可能会导致崩溃吗? (这对我来说似乎是合理的。我已经向图书馆作者 Peter Gutmann 发送了电子邮件)。如何确定要使用的有效 OID?这只是一个研究项目;我不需要它与任何东西进行互操作。非常感谢。
  • 好的,您正在向自己创建的证书添加一些内容。这应该会让事情变得容易一些。 OID 1.2.3.4.5 是合法的,应该是安全的(1.2 表示“ISO 成员主体”,似乎没有 ISO 主体 #3。我没有使用过 Cryptlib,但看起来你需要通过您的 OID 编码为 ASN.1 对象 ID (Hex: 06 04 2A 03 04 05) - 注意 OID 值的前两个字节在 ASN.1 中组合的奇怪方式。Peter Gutmann 的 X.509 样式指南很棒证书格式参考。
  • 如果其他人需要知道这一点,请注意 cryptlib 似乎实际上并不需要 ASN.1 中包含的 OID;它只是指定为添加 ASN.1 的函数的参数。
【解决方案3】:

我建议使用Quick DER,并为其der_pack() 例程提供结构描述,您可以使用其asn2quickder 编译器进行编译。如果是使用标准结构,您可以只使用#include <quick-der/rfc5280> 并使用其预定义数据。

您可以使用der_unpack() 进行具有相同结构描述的解包。它将验证结构方面,尽管不是 ASN.1 语法可能包含的约束。当您使用放置和获取整数范围的实用函数时,会检查整数范围。

很抱歉推送我的 onw 库;但它实际上是为了方便(开源)C/C++ 和 Python 开发人员访问 ASN.1 而编写的。

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 1970-01-01
    • 2015-12-10
    • 2010-11-19
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 2017-06-29
    相关资源
    最近更新 更多