一般使用另外一套编码规则DER,它是BER的一个子集,对每个ASN.1值只有唯一一种编码方法。
octet(字节)表示一个8 bit的无符号整数。
BIT类型和值用等宽字体表示。例如,它通常表示一个16进制的字节值。
n1粗斜体表示变量
[]粗的方括号表示该项为可选项
{}粗体大括号表示一组相关项
|粗体竖杠表示一组之中的可任选其一
?粗体省略号表示重复出现
=粗体等号,用一个子项表示该项
ASN.1类型和值使用一种灵活的、类似编程语言的符号表示,规则如下:z分层(换行)无特殊意义;多个空格和多个空行相当于一个空格。z注释由一对连字符(--)开头,或者一对连字符和一个空行z标识符(值或字段的名字)和类型索引(类型的名字)由大小写字母、数字、连字符和空格组成;标识符由小写字母开头,类型索引由大写字母开头。
z BIT STRING :由0和1任意组成的比特流
z IA5String :由IA5(ASCII)字符任意组成的字符流
z INTEGER :一个任意的整数
z NULL :null值
z OBJECT IDENTIFIER :对象标识符,有一列整数构成,用于确定对象,如算法或
属性类型
z OCTET STRING :任意的octet(8 bit值)流
z PrintableString :任意可打印字符流
z T61String :T.61(8bit)字符的任意流
z UTCTime : "coordinated universal time"或者格林威治平均时(GMT)值
抽象语法符号一是描述抽象类型和值的符号,缩写为ASN.1。
ASN.1的分配符(::=)给类型和值指定名字,这些名
字可以用于定义其他类型或值
结构类型由组件组成。ASN.1定义了四种,都与PKCS标准有关:
z SEQUENCE:一个或多个类型的有序集合
z SEQUENCE OF: 0个或某个给定类型多次出现的有序集合
z SET:一个或多个类型的无序集合
z SET OF: 0个或某给定类型多次出现的无序集合
结构类型允许有可选组件。可选组件可能有默认值。
使用BER,一个ASN.1的值有三种编码方法
简单定长编码,结构化定长编码,及结构化不定长编码。简单的
non-string类型使用第一种(简单定长编码) ;结构化类型可使用任一种结构化的编码方法;
简单的string类型根据值的长度是否已知可使用任一种方法。 隐式标签定义的类型可使用下
层类型的方法,显式标签定义的类型使用结构化的编码方法。
Distinguished Encoding Rules(DER,可辨别编码规则)DER是BER的子集,它定义了使用一个octet string来表示任何ASN.1值的编码方法。
IA5代表International Alphabet 5,与ASCII相同。
INTEGER类型表示任意的整数。INTEGER值可以为正数、负数或0,具有任意大小。在整个PKCS中INTEGER类型用于表示版本号
内容字节以2的补码形式给出了整数值,基于256,最高位
在先,以使用最少的字节。值0编码为一个00字节
OBJECT IDENTIFIER类型表示一个对象识别符,由一列整数组件组成
OBJECT IDENTIFIER值由注册机构指定其含义
OCTET STRING类型表示任意的字节流。一个OCTET STRING值可以为任意长度,
包括0。该类型为string类型
T61String类型表示由T.61字符组成的任意流。T.61是ASCII字符集的8bit扩展。
特殊的"escape"序列定义了随后字符作为其他语言(如日语)的解释。
UTCTime类型表示"coordinated universal time"或格林威治平均时间值。一个UTCTime
值包括精确到分钟或秒的本地时间,及相对于GMT的偏移(单位为小时和分钟) 。
AttributeType类型通过对象标识符来识别一个属性。AttributeValue类型指定
任一个属性值。属性值的实际类型由属性类型决定。
Identifier octets,有两种形式:较小的标签值(标签值在0 和30之间)和较大的标签值(标签值大于等于31)
context-specific 类型的标签只能出现在
结构类型或CHOICE类型的组件中。
0x04 OCTET String 任意的octet(8 bit)流
0x05 NULL 编码值固定为05 00.
0x06 OBJECT IDENTIFIER=OID :对象标识符,有一列整数构成,用于确定对象,如算法或属性类型
0x10 SEQUENCE and SEQUENCE of 有序集合,of可以为0个
0x11 SET and SET OF 无序集合,of可以为0个
0x13 printableString
0x14 T61String T.61(8 bit)字符的任意流
0x16 IA5String 由IA5(ASCII)字符任意组成的字符流
0x17 UTC time :"coordinated universal time"或者格林威治平均时(GMT)值。
ASN.1提供了一些基本的预定义的数据类型:
UNIVERSAL 0 保留给编码规则使用
UNIVERSAL 1 布尔类型
UNIVERSAL 2 整数
UNIVERSAL 3 二进制字符串类型 位串
UNIVERSAL 4 八进制字符串类型 八位位组串
UNIVERSAL 5 空类型
UNIVERSAL 6 对象标识符类型
UNIVERSAL 7 对象描述符类型
UNIVERSAL 8 外部类型和类型实例
UNIVERSAL 9 实数类型
UNIVERSAL 10 枚举类型
UNIVERSAL 11 嵌入的pdv类型
UNIVERSAL 12 UTF8字符串类型
UNIVERSAL 13 相关对象标识符类型
UNIVERSAL 14-15 保留
UNIVERSAL 16 序列和类型序列
UNIVERSAL 17 集合和类型的集合
UNIVERSAL 18-22,25-30 字符串类型
UNIVERSAL 23-24 时间类型
不必为每一个点分数字进行asn1编码,具体说来就是将一个点分数字拆分为7bit一组的序列,然后除了最后一个的最高位填入0之外其余的最高位都填1
由于OID的前两极的标识数字都不是很大,因此更好的办法就是将OID的前两级编码到一个7bit的数中(由于标识more bit需要最高位,所以只剩下7位可以存数据),第一级OID只有3个,分别是itu-t(0),iso(1),joint-iso-itu-t(2),并且第二级OID标识最多也就23,挂于joint-iso-itu-t之下,现在需要一个算法,将第一级和第二级的OID标识编码到一个7bit的数里面,这就需要用一种平坦的方式来索引前两级的数据,构造一组虚拟的标识,为了对待三个一级OID标识更公平,最好是将127个“位置”平均分到三个一级标识,于是就将127除以3,结果是40,于是头40个虚拟标识分给itu-t,中间40个分给iso,后面的47个分给joint-iso-itu-t,这样,前两级是a.b的OID的a和b就被编码成了40*a+b,如此也就节省了一个编码byte。本质上这种编码的思想是在分级的标识上构造一组平坦的虚拟标识。
关于整形编码:
编码过程规定对于正整数,第一个字节的最高位必须为0
因此,假设第一个字节大于127(如49468(0xC13C) 0xC1>0x7F),看上去其编码应该是0x02 02 C1 3C, 但他的最高位为1,所以应该看成负数,最简单有效的办法是用前段零字节填充,即49468编码为0x02 03 00 C1 3C。
http://blog.csdn.net/xiao628945/article/details/8006092
参考链接:http://blog.csdn.net/taolinke/article/details/6248968
http://blog.csdn.net/baidu_36649389/article/details/53538223
http://www.cnblogs.com/dspeeding/p/3418035.html
http://blog.csdn.net/gdwzh/article/details/19232#reply
openssl asn.1的相关介绍:
http://blog.csdn.net/jasenwan88/article/details/7718851
各种算法的OID,参考http://blog.csdn.net/wak0408/article/details/38516339
https://msdn.microsoft.com/en-us/library/aa923698.aspx
hash算法的算法ID
https://msdn.microsoft.com/en-us/library/ff635603.aspx
在线P7数据解析:
https://lapo.it/asn1js/
http://qistoph.blogspot.jp/2012/01/manual-verify-pkcs7-signed-data-with.html
定长编码不定长编码问题
http://blog.csdn.net/sever2012/article/details/7698297
结构解析P7签名和P7数字信封
http://hbaojun.github.io/2014/02/18/PKCS7%E7%BB%93%E6%9E%84%E5%88%86%E6%9E%90%E4%B9%8B%E7%AD%BE%E5%90%8D/
TLV格式编码解码
b6决定当前的TLV数据是一个单一的数据和复合结构的数据。复合的TLV是指value域里也包含一个或多个TLV,类似嵌套的编码格式. b5~b1如果全为1,则说明这个tag下面还有一个子字节,占两个字节,否则tag占一个字节。
来源:http://blog.csdn.net/kxd_ysheng/article/details/21237957
http://blog.csdn.net/chexlong/article/details/6974201