我正在尝试为C(OpenSSL)创建一个X509请求代理证书(ProxyCertInfo扩展名RFC3820),但是我无法弄清楚应该如何定义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请求中,所以我相对确定我唯一的问题是该特定扩展的数据结构格式。

最佳答案

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

如果您想了解一些理论,我发现的最佳参考是A Layman's Guide to a Subset of ASN.1, BER, and 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] }

标头由一个Class类型,一个Primitive / Constructed位和一个Tag-Number组成。如果标记号大于63,则标记号将跨越多个字节。这意味着报头可以是一个字节长,也可以是多个字节长,具体取决于标记号的值。标头是按字节对齐的,这意味着它总是一定数量的字节长。
ASN.1 header { ClassType Primitive/Constructed Tag-number }

长度也可以是一个字节到多个字节,具体取决于长度的值。同样,长度是字节对齐的。

类类型和标记号告诉您内容中编码的内容。

最外面的编码通常是序列或集合,是复合的基本类型。在您的编码中,最外面的编码是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(通用)primitive / constructed = 0(primitive)且tag-number = 0x13
标头字节为0x13
length = 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”
长度= 18,因此长度字节为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
policyLanguage的编码是
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标头)+ lengthof(policyLanguage内容))+(lengthof(policyheaders)+ lengthof(策略内容))
=(2 + 4)+(2 + 18)
= 6 + 20 = 26
长度= 26,因此长度字节为0x1A
内容为policyLanguage,后跟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
proxyPolicy的编码为
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 0x73

ProxyCertPathLengthConstraint是一个整数,因此class = 00(通用)primitive / constructed = 0(primitive)且tag-number = 0x02
标头字节为0x02
长度= 0x01
内容= 0x40
编码为0x02 0x01 0x40

ProxyCertInfoExtension是一个SEQUENCE,因此class = 00(通用)primitive / constructed = 0(primitive)且tag-number = 0x10
标头字节为0x10
长度= lengthof(pCPathLenConstraint)+ lengthof(proxyPolicy)
= lengthof(pCPathLenConstraint标头)+ lengthof(pCPathLenConstraint内容)+(lengthof(proxyPolicy标头)+ lengthof(proxyPolicy内容))
=(2 +1)+(2 + 26)= 3 + 28 = 31 = 0x1F
content = 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 0x73
编码为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 074

关于c - X.509v3 ASN.1至C数据结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5582395/

10-12 16:10