OpenSSL中文手册之ASN1库详解(未完待续)

openssl之ASN.1系列之1—引言和ASN.1概述

【引言】
ASN.1全称为Abstract Syntax NotationOne,是一种描述数字对象的方法和标准。openssl的编码方法就是基于该标准的,目前,很多其他软件的编码方法也是基于该标准。对于直接使用openssl的API或者应用程序来说,可能对ASN.1的了解并不需要很清楚,但是为了使大家对后续介绍的各个API有一个更深刻的编码知识基础,所以对该ASN.1以及openssl相应提供的API处理函数作介绍。

【ASN.1概述】
ASN.1作为一个数字对象描述标准,包括了两部分,分别为数据描述语言(ISO8824)和数据编码规则(ISO8825)。ASN.1的数据描述语言标准允许用户自定义基本数据类型,并可以通过简单的数据类型组成更复杂的数据类型。比如一个复杂的数据对象,如X509证书,就是在其它一些数据类型上定义的,而其它数据类型又是在更基本的数据类型上建立的,直到回溯到定义的最基本的数据类型。
比如ASN.1定义的X509证书的一个子域Validity(证书有效期)就定义如下:
Validity ::= SEQUENCE
{
notBefore UTCTIME,
notAfter UTCTIME
}
其意义就是定义Validity为一个有序序列,由两个个UTCTIME类型的数据notBefore和notAfter组成。然后,就需要找出UTCTIME是怎么定义的,当然,事实上UTCTIME是ASN.1定义的一个基本的时间数据类型。
在上述数据定义的基础上,ASN.1定义了一组编码规则,以规定怎么将上述描述的对象转换成应用程序能够处理和进行传输的二进制编码形式。ASN.1定义了多种编码方法,包括了BER, DER, PER, 和XER等,不过,虽然最基本最常用的编码方式是BER(Basic EncodingRules),但是由于该编码方法可能对一个相同的对象有几种不同的合法二进制编码,所以在openssl里面使用的是BER的子集DER(Distinguished Encoding Rules),使用DER编码方法,对于每一个ASN.1对象,其相应的二进制编码是唯一的。

ASN.1里定义的每个基本对象都有一个对应的数字标识tag,在进行二进制编码的时候需要使用该标志。
【ASN.1定义的基本数据类型】
下面列出ASN.1定义的部分基本数据类型,其各字段的意义如下:
[数据类型]-[数据说明]-[Tag(16进制)]
[BOOLEAN]-[有两个值:false或true]-[01]
[INTEGER]-[整型值]-[02]
[BIT STRING]-[0位或多位]-[03]
[OCTET STRING]-[0字节或多字节]-[04]
[NULL]-[NULL值]-[05]
[OBJECT IDENTIFIER]-[相应于一个对象的独特标识数字]-[06]
[OBJECT DESCRIPTOR]-[一个对象的简称]-[07]
[EXTERNAL]-[ASN.1没有定义的数据类型]-[08]
[REAL]-[实数值]-[09]
[ENUMERATED]-[数值列表,这些数据每个都有独特的标识符,作为ASN.1定义数据类型的一部分]-[0a]
[SEQUENCE和SEQUENCE OF]-[有序数列,SEQUENCE里面的每个数值都可以是不同类型的,而SEQUENCE OF里是0个或多个类型相同的数据]-[10]
[SET和SET OF]-[无序数列,SET里面的每个数值都可以是不同类型的,而SET OF里是0个或多个类型相同的数据]-[11]
[NumericString]-[0-9以及空格]-[12]
[PrintableString]-[A-Z、a-z、0-9、空格以及符号 ()+,-./:=?]-[13]
[UTCTime]-[统一全球时间格式]-[17]
除了上述基本类型,ASN.1还定义了另外一些专用的数据类型,这里不再一一叙述。

openssl之ASN.1系列之2—ASN.1编码方法简介
参考资料:“Computer Network”,“A Layman s Guide to a Subset of ASN.1, BER, and DER”

ASN.1对象的编码是ASN.1标准的重要部分,目前,通常采用的是BER,而DER则是其一个子集。本文将对该编码方法作简单的介绍。
一个标准的ASN.1编码对象有四个域:对象标识域、数据长度域、数据域以及结束标志(可选,在长度不可知情况下需要,openssl中没有该标志)。
【对象标识域】
对象标识域有两种形式,低Tag数字(Tag值在0到30)和高Tag数字(Tag值大于30)形式。
低Tag数字形式只有一个字节,包含三部分,从低位为1开始编号,8和7位是Tag类型,共有四种,分别是universal(00)、application(0 1)、context-specific(1 0)和private(11);第6位是0,表明编码类型是基本类型,第5-1位是Tag值。
高Tag数字形式可以有两个或多个字节,第一个字节跟低Tag数字形式一样,但低5位值全为1,而在后续的第二个和其后的字节中给出Tag值,这些字节都只使用了低7位为数据位,最高位都设为0,但最后一个字节的最高位设为1,采用高位优先,经可能少的数字原则。
【数据长度域】
数据长度域也有两种形式,短形式和长形式。
短形式的数据长度域只有一个字节,第8位为0,其它低7位给出数据长度。
长形式的数据长度域有2到127个字节。第一个字节的第8位为1,其它低7位给出后面该域使用的字节的数量,从该域第二个字节开始给出数据的长度,基于256,高位优先。
【数据域】
数据域给出了具体的数据值。该域的编码对不同的数据类型不一样,这里就不在一一详述了,有兴趣的可以参看参考资料。

【一个编码例子】
下面是SSLDocument给出的对一个对象进行DER编码的例子,更多的例子可以参看本文给出的参考资料。
例子使用的对象是ASN.1定义的BIT STRING类型的对象,其编码的步骤如下:
1.对位串使用”0”进行填补,使其长度为8的整数倍(如果已经是整数倍,则不需要进行填补);
2.计算填补的位数并写下来,成为数据内容的第一个字节;
3.写入填补后的位串,高位字节优先。这些数据跟前面的一个字节组成数据内容的全部字节;
4.在这些数据前面加上一个头字节,这个字节定义如下(编号是从低位为1开始):
第8、7位:00(universal类型)
第 6 位 :0(表明是基本类型,有限长度的编码)
第5-1位:0x03(表明是BIT STRING)
这个字节定义了对象标识域;
5.然后在对象标识域字节和数据字节之间加入下面计算的定义的字节:
计算有多少字节的数据内容(对象标识域数据除外),如果少于127字节,那么就定义一个字节如下:
第8位:0
第7-1位:数据内容的字节数量
如果数据内容的字节数量大于127,就需要定义两个或多个字节,其中,第一个字节的定义如下:
第8位:1
第7-1位:该域后面还有多少字节
其后的字节是数据内容的字节数量,每字节基于256,高位优先
下面是一个实际的数据例子:
位串: 01000100111011
1.补齐两个0在后面,成为8的整数倍,得到 0100010011101100 ;
2. 02 作为第一个数据内容的字节;
3. 44 ec 作为其余的数据内容的字节;
4. 03 作为前面的对象标识字节;
5.因为BIT STRING的tag值3<=127,所以只有一个字节的长度域 03 ;
那么得到的这个位串的DER编码就是03 03 02 44 ec,其中,第一个字节是对象标识域,第二个字节是数据长度域,其他为数据域。

openssl之ASN.1系列之3—ASN.1函数概述和结构
【ASN.1函数库概述】
因为X509相关的协议都是基于ASN.1和DER编码的,所以openssl提供了一组函数,这些函数可以读取DER编码的对象,并将它们转换成openssl能够处理的内部格式;这些函数也可以将openssl里定义的C格式的对象结构转换成DER编码的对象。此外,该系列还提供了一些对这些对象进行比较、读取和设定指定值的函数。该系列函数还包括了一些签名函数,这是因为在签名之前,有些对象需要进行DER编码。

下面对ASN.1函数库中重要的数据结构做简单的介绍。
【ASN1_CTX】
该结构用来在ASN1处理过程中维护跟踪各种相关变量,其定义如下:
typedef struct asn1_ctx_st
{

unsigned char *p;
int eos;
int error;
int inf;
int tag;
int xclass;
long slen;
unsigned char *max;
unsigned char *q;
unsigned char **pp;
int line;
} ASN1_CTX;
参数p是工作字符指针,其最大长度由参数max指定;
eos是indefinite编码模式的结束标识标志;
error是错误代码;
inf值为0x20代表constructd模式,为0x21代表indefinite模式;
tag是最后取得的对象的tag值;
xclass是最后取得的

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝月心语

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值