使用 openssl C API 解析 asn1 文档

Zoh*_*r81 3 c parsing openssl ssl-certificate x509certificate

我想使用 openssl 库解析 asn1 格式的证书。不幸的是,一些 API 命令缺乏相关文档,所以我自己尝试了它们。我已经看到了与这个主题的许多关系,但没有准确的用法解释。

首先,我将考虑以下应该返回一般 asn1 对象的命令。

int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
                int *pclass, long omax);
Run Code Online (Sandbox Code Playgroud)

从我在网上找到的例子来看,输入参数的描述似乎如下:

pp - 指向对象(或证书)开头的指针,它是可变的,因为在应用该函数后,该值移动到下一个对象。

plength - 表示对象长度的输出。

ptag - 表示对象类型的输出(简单如 INTEGER,或复杂 SEQUENCE)。

pclass - 我不知道这是什么意思。

omax - 证书结束前的长度。

也许一些 openssl 经验丰富的用户可能会验证我上面的总结,并阐明 pclass 的含义。

谢谢

Cra*_*own 7

回答

pclass参数表示对象类型的标签编号所在的标签类。


解释

首先,ASN.1 对象的一些背景。为了解释起见,我将在这里简化很多。当使用 BER/DER 编码对 ASN.1 对象进行编码时,它通常采用以下结构:

+-------------------+---------------+-----------------+
| Identifier octets | Length octets | Contents octets |
| (Type)            | (Length)      | (Value)         |
+-------------------+---------------+-----------------+
Run Code Online (Sandbox Code Playgroud)

标识符八位字节是 8 位,用于指定值的类型。标识符八位字节通常是这样编码的:

     +-----+-----+-----+-----+-----+-----+-----+-----+
Bits |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
     +-----------+-----+-----------------------------+
     | Tag class | P/C |         Tag number          |
     +-----------+-----+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

标记类可以是 4 种事物之一 - 通用、应用程序、特定于上下文或私有。Universal 类包含 ASN.1 原生的类型(如 Integer 和 String)。除非您正在处理自定义类型,否则您可以期望该类是通用的,由00. 这是通过pclass 参数返回的内容。

标签号是指定该类中类型的 5 位。这通过ptag参数返回。例如,Universal 类中的 Integer 具有标记号00010

因此,例如,您可以ASN1_get_object通过以下方式测试您是否获得了 ASN.1 整数:

ASN1_get_object(&pp, &plength, &ptag, &pclass, omax);
if (pclass == V_ASN1_UNIVERSAL && ptag == V_ASN1_INTEGER)
{
    // this is the native ASN.1 Integer type
}
Run Code Online (Sandbox Code Playgroud)

如果您知道您纯粹是在处理通用类型,您可能会认为测试pclass变量有点多余。


文档

你对参数作用的一些定义有点偏离。这是我对该函数文档的尝试。我应该指出,我已经尝试通过查看代码和 ASN.1 规范自己解决这个问题,所以如果我有任何错误,我欢迎任何编辑。

int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, int *pclass, long omax)
Run Code Online (Sandbox Code Playgroud)

摘要:将BER/DER 编码的ASN.1 对象解码为其值的类型、长度和起始位置。

参数

**pp: 一个指向BER/DER 编码对象开始的指针。当函数返回时,该指针被调整为指向 ASN.1 值(内容八位字节)的开始。

*plength: 指向 a 的指针long。当函数返回时,它包含 ASN.1 值的长度,指定为八位字节数。如果长度以不定形式编码,则为plength0。

*ptag: 指向int. 当函数返回时,它包含 ASN.1 标签号,它定义了值的类型。请注意,这只是标签编号,不包括标签类或原始/构造指标。

*pclass: 指向int. 当函数返回时,它包含 ASN.1 标签的类。

omax:BER/DER 编码对象的最大长度。如果对象比这更长,则会发生错误。

返回: 一个整数。如果设置了第 8 位 ( 0x80),则发生错误。如果设置了第 6 位 ( 0x20),则该类型是一种构造类型(即内容八位字节编码一个或多个数据值)。如果设置了第 1 位 ( 0x01),则该值的长度是不确定的,并且该值将以“内容结束八位字节”结尾。