3

我正在尝试在 C (OpenSSL) 中为代理证书 (ProxyCertInfo Extension RFC3820 ) 创建 X509 请求,但我无法弄清楚应该如何定义 ProxyCertInfo 的数据结构。RFC 对 ASN.1 语言的定义如下:

PKIXproxy88 { iso(1) identified-organization(3) dod(6)
   internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
   proxy-cert-extns(25) }

DEFINITIONS EXPLICIT TAGS ::=

BEGIN

-- EXPORTS ALL --

-- IMPORTS NONE --

-- PKIX specific OIDs

id-pkix OBJECT IDENTIFIER ::=
       { iso(1) identified-organization(3)
            dod(6) internet(1) security(5) mechanisms(5) pkix(7) }

-- private certificate extensions
id-pe   OBJECT IDENTIFIER ::= { id-pkix 1 }

-- Locally defined OIDs

-- The proxy certificate extension
id-pe-proxyCertInfo    OBJECT IDENTIFIER ::= { id-pe 14 }

-- Proxy certificate policy languages
id-ppl  OBJECT IDENTIFIER ::= { id-pkix 21 }

-- Proxy certificate policies languages defined in
id-ppl-anyLanguage     OBJECT IDENTIFIER ::= { id-ppl 0 }
id-ppl-inheritAll      OBJECT IDENTIFIER ::= { id-ppl 1 }
id-ppl-independent     OBJECT IDENTIFIER ::= { id-ppl 2 }

-- The ProxyCertInfo Extension
ProxyCertInfoExtension  ::= SEQUENCE {
     pCPathLenConstraint     ProxyCertPathLengthConstraint OPTIONAL,
     proxyPolicy             ProxyPolicy
}

ProxyCertPathLengthConstraint  ::= INTEGER
ProxyPolicy  ::= SEQUENCE {
     policyLanguage          OBJECT IDENTIFIER,
     policy                  OCTET STRING OPTIONAL
}

END

我查看了非常有限的 OpenSSL 文档,但无法找到如何将其解析为 C 数据结构。我还阅读了http://www.openssl.org/docs/apps/asn1parse.html#,因为它解释了如何将解析器用于命令行工具,而不是如何将其包含在您自己的源代码中。

我已经设法在 X509 请求中包含了其他扩展,所以我比较确定我唯一的问题是这个特定扩展的数据结构的格式。

4

1 回答 1

5

我认为您的问题是“如何将数据格式化为 ProxyCertInfoExtension?” 如果这不正确,请告诉我。

如果您想了解一些理论,我找到的最佳参考是A Layman's Guide to a Subset of ASN.1、BER 和 DER

您问题中的代码部分描述了如何对 ProxyCertInfoExtension 的数据进行编码。可以将编码描述视为可以由解析器生成器处理的语法,就像 yacc 将语法作为输入并输出 C 代码一样。事实上,至少存在一个 ASN.1 解析器生成器 ASN1C

ASN.1 编码可以是可变大小的。数据以最外层或顶级 ASN.1 编码开始。每个 ASN.1 编码可能在其内部包含一个或多个 ASN.1 编码。这样,ASN.1 是递归的。

ASN.1 编码由头、长度、可选内容和可选结尾组成。

ASN.1 encoding { Header length [content] [end] }

标头由一个类类型、一个原始/构造位和一个标记号组成。如果标记号大于 63,则标记号将跨越多个字节。这意味着标题可能是一个字节长或多个字节长,具体取决于标记号的值。标头是字节对齐的,这意味着它总是一些字节长。

ASN.1 header { ClassType Primitive/Constructed Tag-number }

根据长度的值,长度也可以是一个字节到多个字节。同样,长度是字节对齐的。

Class 类型和 Tag-Number 告诉您 Content 中的编码内容。

最外层的编码通常是一个序列或集合,它们是复合基本类型。在您的编码中,最外层的编码是 ProxyCertInfoExtension,它是一个可选 ProxyCertPathLengthConstraint 和 ProxyPolicy 的序列。您的编码如下所示:

ProxyCertInfoExtension { [ProxyCertPathLengthConstraint] ProxyPolicy }

回顾编码规则,ProxyCertPathLengthConstraint 只是一个整数,所以你的编码真的是:

ProxyCertInfoExtension { [Integer] ProxyPolicy }

编码规则将 ProxyPolicy 定义为 policyLanguage 和可选策略的序列。所以我们可以更新编码表示,如下所示:

ProxyCertInfoExtension { [Integer] { policyLanguage [policy] } }

编码规则将策略指定为八位字节字符串(只是一些字节数)。所以进一步简化产生:

ProxyCertInfoExtension { [Integer] { policyLanguage [Octet String] } }

根据对象标识符,编码是以下之一:

ProxyCertInfoExtension { [Integer] { id-ppl-anyLanguage [Octet String] } }
ProxyCertInfoExtension { [Integer] { id-ppl-inheritAll  [Octet String] } }
ProxyCertInfoExtension { [Integer] { id-ppl-independent [Octet String] } }

我将尝试一个未经测试的示例 ProxyCertPathLengthConstraint=64 policyLanguage=id-ppl-anyLanguage policy="test" 我将从策略长度为 04 开始,这是一个可打印的字符串,所以 class=00(universal) primitive/constructed= 0(原始)和标签编号=0x13 标头字节为 0x13 长度=4,因此长度字节为 0x04 ascii 中的“测试”为 0x74 0x65 0x73 0x74 策略编码为 0x13 0x04 0x74 0x65 0x73 0x74

id-ppl-anyLanguage 是一个对象标识符,因此 class=00(通用)primitive/constructed=0(primitive)和 tag-number=0x06 标头字节为 0x06 id-ppl-anyLanguage 的值为“1.3.6.1.5.5 .7.21.0" length=18, so length byte is 0x12 "1.3.6.1.5.5.7.21.0" = 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 the encoding for policyLanguage is 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10

proxyPolicy 是一个序列,因此 class=00(通用)primitive/constructed=0(primitive)和 tag-number=0x10 标头字节为 0x10 长度= lengthof(policyLanguage)+ lengthof(policy)=(lengthof(policyLanguage headers)+ lengthof (policyLanguage content)) + (lengthof(policyheaders) + lengthof (policy content)) = (2 + 4) + (2 + 18) = 6 + 20 = 26 length=26,所以长度字节为0x1A内容为policyLanguage followed by policy = 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74 the encoding for proxyPolicy is 0x10 0x1A 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74

ProxyCertPathLengthConstraint 是一个整数,所以 class=00(universal) primitive/constructed=0(primitive) and tag-number=0x02 header byte is 0x02 length=0x01 content=0x40 encoding is 0x02 0x01 0x40

ProxyCertInfoExtension 是一个 SEQUENCE 所以 class=00(universal) Primitive/constructed=0(primitive) and tag-number=0x10 header byte is 0x10 the length = lengthof(pCPathLenConstraint) + lengthof(proxyPolicy) = lengthof(pCPathLenConstraint headers) + lengthof (pCPathLenConstraint 内容)) + (lengthof(proxyPolicy 标头) + lengthof(proxyPolicy 内容)) = (2 + 1) + (2 + 26) = 3 + 28 = 31 = 0x1F 内容= pCPathLenConstraint 后跟 proxyPolicy = 0x02 0x01 0x40 0x10 0x1A 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74 the encoding is 0x10 0x1F 0x02 0x01 0x40 0x10 0x1A 0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10 0x13 0x04 0x74 0x65 0x73 0x74

于 2011-04-21T19:46:44.400 回答