Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

以PKCS10规范为例学习ASN.1 #34

Open
chenpengcong opened this issue Jul 3, 2021 · 0 comments
Open

以PKCS10规范为例学习ASN.1 #34

chenpengcong opened this issue Jul 3, 2021 · 0 comments

Comments

@chenpengcong
Copy link
Owner

chenpengcong commented Jul 3, 2021

本文以PKCS10的ASN.1 module作为范例,介绍其中涉及到的ASN.1语法知识,也作为自己学习ASN.1的一个知识总结。

PKCS10 Module的ASN.1语法定义如下

1.    PKCS-10 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
2.    pkcs-10(10) modules(1) pkcs-10(1)}
3. 
4.    DEFINITIONS IMPLICIT TAGS ::=
5. 
6.    BEGIN
7. 
8.    -- EXPORTS All --
9. 
10.    -- All types and values defined in this module are exported for use
11.    -- in other ASN.1 modules.
12. 
13.    IMPORTS
14. 
15.    informationFramework, authenticationFramework
16.         FROM UsefulDefinitions {joint-iso-itu-t(2) ds(5) module(1)
17.         usefulDefinitions(0) 3}
18. 
19.    ATTRIBUTE, Name
20.         FROM InformationFramework informationFramework
21. 
22.    ALGORITHM
23.         FROM AuthenticationFramework authenticationFramework;
24. 
25.    -- Certificate requests
26.    CertificationRequestInfo ::= SEQUENCE {
27.         version       INTEGER { v1(0) } (v1,...),
28.         subject       Name,
29.         subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
30.         attributes    [0] Attributes{{ CRIAttributes }}
31.    }
32. 
33.    SubjectPublicKeyInfo {ALGORITHM: IOSet} ::= SEQUENCE {
34.         algorithm        AlgorithmIdentifier {{IOSet}},
35.         subjectPublicKey BIT STRING
36.    }
37. 
38.    PKInfoAlgorithms ALGORITHM ::= {
39.         ...  -- add any locally defined algorithms here -- }
40. 
41.    Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
42.    CRIAttributes  ATTRIBUTE  ::= {
43.         ... -- add any locally defined attributes here -- }
44. 
45.    Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
46.         type   ATTRIBUTE.&id({IOSet}),
47.         values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
48.    }
49. 
50.    CertificationRequest ::= SEQUENCE {
51.         certificationRequestInfo CertificationRequestInfo,
52.         signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
53.         signature          BIT STRING
54.    }
55. 
56.    AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE {
57.         algorithm  ALGORITHM.&id({IOSet}),
58.         parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
59.    }
60. 
61.    SignatureAlgorithms ALGORITHM ::= {
62.         ... -- add any locally defined algorithms here -- }
63. 
64.    END

行 1 ~ 2 定义了模块(module)名称 PKCS-10,并且定义该模块的对象标识符(object identifier)为{iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-10(10) modules(1) pkcs-10(1)},也可以表示为1.2.840.113549.1.10.1.1,用于唯一标识该模块

行 4 定义了模块的"tagging environment"

tagging environment 这个术语参考自书籍《ASN.1 Complete》

"tagging environment"影响TLV数据中T的编码,有3种选项

  • IMPLICIT TAGS
  • EXPLICIT TAGS
  • AUTOMATIC TAGS

下面以实际例子来展示它们是如何影响数据的Tag

首先对比IMPLICIT及EXPLICIT, 定义下面两个module

Article-Implicit-Tagging-Schema DEFINITIONS IMPLICIT TAGS ::= 
BEGIN
  Article ::= SEQUENCE       
  {
     title [2]     UTF8String,
     author [4]    UTF8String
  }                                                     
END
Article-Explicit-Tagging-Schema DEFINITIONS EXPLICIT TAGS ::= 
BEGIN
  Article ::= SEQUENCE       
  {
     title [2]     UTF8String,
     author [4]    UTF8String
  }                                                     
END

当遵循以上标准使用BER编码下面这个值时

value Article ::= {
  title "ans.1 learning",
  author "cc"
}

遵循Article-Implicit-Tagging-Schema的BER编码结果为:3014820E616E732E31206C6561726E696E6784026363

这里借助了ASN.1的在线编解码工具https://asn1.io/asn1playground/

30 - tag number 16(SEQUENCE), constructed type
	14 - length
	82 - tag number 2, context-specific class #UTF8String的默认tag number 12被覆盖成2
		0E - length
		616E732E31206C65617 - ans.1 learning
	84 - tag number 4, context-specific class #UTF8String的默认tag number 12被覆盖成4
		02  - length
		6363 - cc

遵循Article-Explicit-Tagging-Schema的BER编码结果为:3018A2100C0E616E732E31206C6561726E696E67 A4040C026363

30 - tag number 16(SEQUENCE), constructed type
	18 - length
	A2 - tag number 2, context-specific class, constructed type # 新增的的TAG
		10 - length
		0C - tag number 12(UTF8String)
			0E - length
			616E732E31206C6561726E696E67 - ans.1 learning
	A4 - tag number 4 # 新增的的TAG
		04 - length
		0C - tag number 12(UTF8String)
			02 - length
			6363 - cc

重点关注这一行title [2] UTF8String

Article-Implicit-Tagging-Schema的编码结果是直接覆写UTF8String类型的tag number,从12改成2
而Article-Explicit-Tagging-Schema是新增一层TLV结构,用来包装原数据的TLV,且该新增的TAG为2

预备知识:tag notation的用法及含义如下示例

[UNIVERSAL 29] tag-value 29, "universal" class
[APPLICATION 10] tag-value 10, "application" class
[PRIVATE 0] tag-value 0, "private" class
[3] tag-value 3, "context-specific" class

AUTOMATIC TAGS的作用是自动的为每个参数分配tag number,从[0]开始递增,示例如下

Article-Automatic-Tagging-Schema DEFINITIONS AUTOMATIC TAGS ::= 
BEGIN
  Article ::= SEQUENCE       
  {
     title     UTF8String,
     author    UTF8String
  }                                                     
END

对前面的value值进行BER编码的结果为:3014800E616E732E31206C65 61726E696E6781026363。

可以看到title的tag number为0,author的tag number为1

行 6 ~ 23是EXPORTS/IMPORTS语句,EXPORTS可以导出本模块中的值或类型,IMPORTS则是导入其他模块中的值或类型。当省略EXPORTS时表示本模块中的所有类型都可以被其他模块导入。

可以看到PKCS-10模块没有EXPORTS语句,所以默认所有类型和值都可以被其他模块导入,规范中注释也说明了这一点

先看行15 ~ 17,从UsefulDefinitions(2.5.1.0.3)模块导入了两个值(value reference) informationFramework和authenticationFramework,UsefulDefinitions(2.5.1.0.3)模块定义在X.501规范,这里列出X.501规范中我们需要的一些定义

UsefulDefinitions {joint-iso-itu-t ds(5) module(1) usefulDefinitions(0) 3}
DEFINITIONS ::=
BEGIN
...
ID ::= OBJECT IDENTIFIER
ds ID ::= {joint-iso-itu-t ds(5)}
module ID ::= {ds  1}
...
informationFramework ID ::= {module informationFramework(1) 3}
authenticationFramework ID ::= {module authenticationFramework(7) 3}
...

可以看出informationFramework及authenticationFramework都是OBJECT IDENTIFIER类型,informationFramework的值为2.5.1.1.3,authenticationFramework的值为2.5.1.7.3

接下来看行 19 ~ 23,从OID(object identifier)为2.5.1.1.3的InformationFramework模块导入ATTRIBUTE及Name,从OID为2.5.1.7.3的AuthenticationFramework模块导入ALGORITHM

AuthenticationFramework模块定义在X.509

InformationFramework模块定义在X.501

下面列出ATTRIBUTE,Name及ALGORITHM的定义,方便查阅

-- Module InformationFramework (X.501 TC2:08/1997)
InformationFramework {joint-iso-itu-t ds(5) module(1) informationFramework(1) 
  3} DEFINITIONS ::=
BEGIN
...
-- ATTRIBUTE information object class specification 
ATTRIBUTE ::= CLASS {
  &derivation            ATTRIBUTE OPTIONAL,
  &Type                  OPTIONAL, -- either &Type or &derivation required 
  &equality-match        MATCHING-RULE OPTIONAL,
  &ordering-match        MATCHING-RULE OPTIONAL,
  &substrings-match      MATCHING-RULE OPTIONAL,
  &single-valued         BOOLEAN DEFAULT FALSE,
  &collective            BOOLEAN DEFAULT FALSE,
  -- operational extensions 
  &no-user-modification  BOOLEAN DEFAULT FALSE,
  &usage                 AttributeUsage DEFAULT userApplications,
  &id                    OBJECT IDENTIFIER UNIQUE
}
WITH SYNTAX {
  [SUBTYPE OF &derivation]
  [WITH SYNTAX &Type]
  [EQUALITY MATCHING RULE &equality-match]
  [ORDERING MATCHING RULE &ordering-match]
  [SUBSTRINGS MATCHING RULE &substrings-match]
  [SINGLE VALUE &single-valued]
  [COLLECTIVE &collective]
  [NO USER MODIFICATION &no-user-modification]
  [USAGE &usage]
  ID &id
}
...
Name ::= CHOICE { -- only one possibility for now --rdnSequence  RDNSequence
}
...
END -- InformationFramework
-- Module AuthenticationFramework (X.509:08/1997)
AuthenticationFramework {joint-iso-itu-t ds(5) module(1)
  authenticationFramework(7) 3} DEFINITIONS ::=
BEGIN
...
--  information object classes 
ALGORITHM ::= TYPE-IDENTIFIER
...

TYPE-IDENTIFIER是ASN.1预定义的信息对象类(information object class),定义如下

-- TYPE-IDENTIFIER definition from X.681
TYPE-IDENTIFIER ::= CLASS
{
    &id OBJECT IDENTIFIER UNIQUE,
    &Type
}
WITH SYNTAX {&Type IDENTIFIED BY &id}

行 26 ~ 31定义了CertificationRequestInfo类型

26.    CertificationRequestInfo ::= SEQUENCE {
27.         version       INTEGER { v1(0) } (v1,...),
28.         subject       Name,
29.         subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
30.         attributes    [0] Attributes{{ CRIAttributes }}
31.    }

version参数的类型符号(type notation)含义如下

  • {}称为named number list,用标识符来代表某个具体整数值,增加可读性
  • ()称为single value subtyping,用于约束允许的整数值
  • ...称为extension marker,表示允许出现其他值,比如该标准后面更新了,就可以增加一个v2(1)的版本值

subjectPKInfo参数的类型符号含义如下

  • SubjectPublicKeyInfo{{ PKInfoAlgorithms }}最外层的{}称为参数化(Parameterization),表示将参数{ PKInfoAlgorithms }传递给SubjectPublicKeyInfo,从规范下文关于SubjectPublicKeyInfo的定义也能看出该类型接收一个参数,且该参数是一个ALGORITHM类型的information object set
  • SubjectPublicKeyInfo{{ PKInfoAlgorithms }}最内层的{}是引用object set的用法,可以认为是固定用法

行 33 ~ 36定义了SubjectPublicKeyInfo类型,因为用到的语法均在介绍CertificationRequestInfo类型时提及,所以这里不展开讨论

行 38 ~ 39 定义了一个information object set,名称为PKInfoAlgorithms

38.    PKInfoAlgorithms ALGORITHM ::= {
39.         ...  -- add any locally defined algorithms here -- }

如何看出PKInfoAlgorithms是一个object set

第一种角度:类型ALGORITHM是information object class且PKInfoAlgorithms以大写开头 (一般情况下object set名称大写开头,object以小写开头)

第二种角度:PKInfoAlgorithms 作为SubjectPublicKeyInfo类型的参数时使用了{}符号

行 41 ~ 43 涉及到的ASN.1相关知识均已提及,在此不赘述

接下来看行 45 ~ 48

45.    Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
46.         type   ATTRIBUTE.&id({IOSet}),
47.         values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
48.    }

首先看type参数的声明type ATTRIBUTE.&id({IOSet})

  • ATTRIBUTE.&id表示type参数使用ATTRIBUTE的&id字段作为自己的值,因此type参数的类型与&id一致为OBJECT IDENTIFIER
  • ATTRIBUTE.&id后面加上({IOSet})表示&id的取值被限制在IOSet这个information object set中,只能取IOSet中出现的&id值。在ASN.1中该用法术语称为table constraint

接下来看values参数的声明values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})

  • SIZE(1..MAX)称为Size constraint,用来约束values集合的大小,这里表示至少有一个元素

  • 与type参数的声明相比,values增加了relation constraint,即{@type}这个表达式,它表示将ATTRIBUTE.&Type与Attribute的type参数关联起来,通过上文分析我们知道type参数实际就是ATTRIBUTE.&id,为方便理解我们可以说将ATTRIBUTE.&Type和ATTRIBUTE.&id关联起来,意思就是说ATTRIBUTE.&Type及ATTRIBUTE.&id两个字段必须属于同一个information object

    这里举个例子,比如说IOSet此时由下面两个information object组成

    object1 ATTRIBUTE ::=  {
    	{
    		&Type	PrintableString,
    		&id		{iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) challengePassword(7)}
    	}
    }
    
    object2 ATTRIBUTE ::=  {
    	{
    		&Type	SigningTime,
    		&id		{iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) signing-time(5)}
    	}
    }
    IOSet ATTRIBUTE ::= {object1 | object2}
    

    一旦Attribute的type参数值为{iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) signing-time(5)},那么values的类型一定是SigningTime,因为{@type}限定了ATTRIBUTE.&Type和ATTRIBUTE.&id必须属于同一个object

到这一步基本把看懂PKCS10规范所需要的ASN.1知识简单介绍了一遍,剩下的就不赘述了。不过关于information object的知识还是很晦涩的,建议看《ASN.1 Complete》辅助理解。

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant