X.509v3 ASN.1 到 C 数据结构
我正在尝试创建代理证书的 X509 请求(ProxyCertInfo 扩展 RFC3820) C (OpenSSL),但我无法弄清楚应该如何定义 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 请求中,因此我相对确定我唯一的问题是此特定扩展的数据结构的格式。
I'm trying to create a X509 Request for a Proxy Certificate (ProxyCertInfo Extension RFC3820) in C (OpenSSL), but I cannot figure out how the datastructures of the ProxyCertInfo should be defined. The RFC defines the ASN.1 language as follows:
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
I have looked at the very limited documentation of OpenSSL and cannot find out how to parse this to C data structs. I've also read http://www.openssl.org/docs/apps/asn1parse.html# as it explains how to use the parser for the command line tool, but not how to include this in your own source code.
I have managed to include other extensions to the X509 request already, so I'm relatively sure my only problem is with the formatting of the data structures for this particular extension.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您的问题是“如何将数据格式化为 ProxyCertInfoExtension?”如果这不正确,请告诉我。
如果您想了解一些理论,我找到的最佳参考是A Layman's Guide to a ASN.1、BER 和 DER 的子集。
您问题中的代码部分描述了 ProxyCertInfoExtension 的数据如何编码。将编码描述视为可以由解析器生成器处理的语法,就像 yacc 将语法作为输入并输出 C 代码一样。事实上,至少存在一个 ASN.1 解析器生成器 ASN1C
ASN.1 编码可能具有可变大小。数据以最外层或顶级 ASN.1 编码开始。每个 ASN.1 编码在其内部可能包含一个或多个 ASN.1 编码。这样ASN.1就是递归的。
ASN.1 编码由标头、长度、可选内容和可选结尾组成。
标头由类类型、原始/构造位和标记号组成。如果标记号大于 63,则标记号将跨越多个字节。这意味着标头可能是一个字节长或多个字节长,具体取决于标记号的值。标头是字节对齐的,这意味着它总是有一定数量的字节长。
长度也可以是一个字节到多个字节长,具体取决于长度的值。同样,长度是字节对齐的。
类类型和标签号告诉您内容中编码的内容。
最外面的编码通常是序列或集合,它们是复合基本类型。在您的编码中,最外面的编码是 ProxyCertInfoExtension,它是可选 ProxyCertPathLengthConstraint 和 ProxyPolicy 的序列。您的编码看起来像这样:
回顾一下编码规则,ProxyCertPathLengthConstraint 只是一个整数,因此您的编码实际上是:
编码规则将 ProxyPolicy 定义为策略语言和可选策略的序列。因此,我们可以将编码表示更新为如下所示:
编码规则将策略指定为八位字节字符串(只是一些字节数)。因此,进一步简化会产生:
根据对象标识符,编码是以下之一:
我将尝试一个未经测试的示例
ProxyCertPathLengthConstraint=64
策略语言=id-ppl-anyLanguage
政策=“测试”
我将从保单长度为 04 开始彻底研究
这是一个可打印的字符串,因此 class=00(universal)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(universal) Primitive/constructed=0(primitive) 和 tag-number=0x06
标头字节为 0x06
id-ppl-anyLanguage 的值为“1.3.6.1.5.5.7.21.0”
length=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
策略语言的编码是
0x06 0x12 0x11 0x0E 0x03 0x0E 0x16 0x0E 0x11 0x0E 0x15 0x0E 0x15 0x0E 0x17 0x0E 0x12 0x11 0x0E 0x10
proxyPolicy 是一个序列,所以 class=00(universal) 原始/构造= 0(原始)和标签号=0x10
标头字节为 0x10
长度= lengthof(policyLanguage) + lengthof(policy)
= (lengthof(policyLanguage 标头) + lengthof (policyLanguage 内容)) + (lengthof(policyheaders) + lengthof (策略内容))
= (2 + 4) + (2 + 18)
= 6 + 20 = 26
length=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 0x 73 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 0x 74 0x65 0x73 0x74
ProxyCertPathLengthConstraint 是一个整数,因此 class=00(universal)primitive/constructed=0(primitive) 和 tag-数字=0x02
标头字节为 0x02
长度=0x01
内容=0x40
编码是 0x02 0x01 0x40
ProxyCertInfoExtension 是一个序列,所以 class=00(universal)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
内容= 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 0 x10 0x13 0x04 0x74 0x65 0x73 0x74
编码为 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
I think your question is "How do I format data as a ProxyCertInfoExtension?" If this in incorrect please let me know.
If you want to know some theory, the best reference I have found is A Layman's Guide to a Subset of ASN.1, BER, and DER.
The code section in your question is a description of how the data for the ProxyCertInfoExtension is encoded. Think of the encoding description as a grammar that could be processed by a parser generator, much as yacc take a grammar as input and outputs C code. In fact at least one ASN.1 parser generator exists ASN1C
ASN.1 encodings may be of variable size. The data begins with an outtermost or top level ASN.1 encoding. Each ASN.1 encoding may contain one or more ASN.1 encoding inside itself. In this way ASN.1 is recursive.
An ASN.1 encoding is composed of a header, a length, optional content, and an optional end.
The header is composed of a Class type, a Primitive/Constructed bit, and a Tag-Number. If the Tag-Number is larger than 63 then the Tag-Number will span multiple bytes. This means that the header may be one byte long or many bytes long depending on the value of the Tag-Number. The header is byte aligned meaning that is always some number of bytes long.
The length may also be one byte to many bytes long depending on the value of the length. Again the Length is byte aligned.
The Class type and the Tag-Number tell you what is encoded in the Content.
The outtermost encoding is usually a sequence or set, which are compound basic types. In your encoding, the outtermost encoding is the ProxyCertInfoExtension which is a sequence of an optional ProxyCertPathLengthConstraint and a ProxyPolicy. Your encoding looks like this:
Looking back at the encoding rules, ProxyCertPathLengthConstraint is just an integer, so your encoding is really:
The encoding rules define a ProxyPolicy as a sequence of a policyLanguage and an optional policy. So we can update the encoding representation to look like this:
The encoding rules specify policy as an Octet String (Just some number of bytes). So firther simplification produces:
Depending on the object identifier, the encoding is one of:
I'll try an untested example
ProxyCertPathLengthConstraint=64
policyLanguage=id-ppl-anyLanguage
policy="test"
I'll work inside out starting with policy length is 04
this is a printable string so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x13
the header byte is 0x13
length=4, so length byte is 0x04
"test" in ascii is 0x74 0x65 0x73 0x74
the encoding for policy is 0x13 0x04 0x74 0x65 0x73 0x74
id-ppl-anyLanguage is an Object Identifier so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x06
the header byte is 0x06
the value for id-ppl-anyLanguage is "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 is a sequence so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x10
the header byte is 0x10
the length= lengthof(policyLanguage) + lengthof(policy)
= (lengthof(policyLanguage headers) + lengthof (policyLanguage content)) + (lengthof(policyheaders) + lengthof (policy content))
= (2 + 4) + (2 + 18)
= 6 + 20 = 26
length=26, so length byte is 0x1A
the content is 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 is a integer so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x02
the header byte is 0x02
the length=0x01
the content=0x40
the encoding is 0x02 0x01 0x40
ProxyCertInfoExtension is a SEQUENCE so class=00(universal) primitive/constructed=0(primitive) and tag-number=0x10
the header byte is 0x10
the length = lengthof(pCPathLenConstraint) + lengthof(proxyPolicy)
= lengthof(pCPathLenConstraint headers) + lengthof (pCPathLenConstraint content)) + (lengthof(proxyPolicy headers) + lengthof(proxyPolicy content))
= (2 + 1) + (2 + 26) = 3 + 28 = 31 = 0x1F
the content= pCPathLenConstraint followed by 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