ASN.1 学习
????ASN.1
章節目錄
2.1 常見的簡單類型
2.2 結構類型
5.1 BIT STRING
5.2 IA5String
5.3 INTEGER
5.4 NULL
5.5 OCTET STRING
5.6 UTCTime
5.6 OBJECT IDENTIFIER
參考 http://luca.ntop.org/Teaching/Appunti/asn1.html.
簡介
ASN.1 全稱 Abstract Syntax Natation One. 是一個用來描述抽象類型抽象數據的語法. 類似于 XML, JSON 等, 主要用于編碼數據以便于在網絡中交換數據. 比如, X509 證書.
ASN.1 中定義了四種類型:
- 簡單類型 (Simple types) : 用于編碼基本的數據類型. 如 整形,字符串,二進制數據等.
- 結構類型 (Structured types) : 用于編碼復雜數據類型. 如, X509 證書中的公鑰.
- 標記的類型 (Tagged types) : 用于編碼從其他幾種類型引申而來的類型.
- 其他類型 (Other types) : CHOICE 或 Any.
ASN.1 中每個類型都對應與一個 class 和 非負的 tag number. 用來區別不同的 ASN.1 類型.
四種 class:
- Universal: 用來表示在所有應用中都具有相同意義的類型. 這些類型定義在 X.208
- Application: 用來表示針對于具體應用的類型. 在不同的應用中這些類型的意義往往不同
- Private: 用來表示針對用于具體企業的類型
- Context-specific: 用來表示針對于具體上下文該類型意義會變化的類型
- 列出這些類型僅供參考, 其在網絡協議中往往應用較少. 因為具體的協議往往會規定某個數據的具體ASN.1結構. 對于每個數據的每個字段也都有嚴格的規定.
Tag Numbers:
TypeTag Number (decimal)Tag Number (hexadecimal) INTEGER 2 02 BIT STRING 3 03 OCTET STRING 4 04 NULL 5 05 OBJECT IDENTIFIER 6 06 SEQUENCE and SEQUENCE OF 16 10 SET and SET OF 17 11 PrintableString 19 13 T61String 20 14 IA5String 22 16 UTCTime 23 17 下面我們詳細介紹每一種類型. 我們的目標是通過本文的描述,我們可以手工的解析一個X509證書.
-----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE-----常用數據類型
簡單類型
TypeDescrption BIT STRING 由任意的 0 和 1 構成的字符串 IA5String 任意的 ASCII 字符串 INTEGER 任意的整型 NULL 表示空值 OBJECT IDENTIFIER 由一系列的整型序列組成 OCTET STRING 由八比特值構成的字符串, 類似于比特數組 PrintableString 由任意的可打印字符構成的字符串 T61String 由八比特字符構成的字符串 UTCTime GMT 時間值 結構類型
TypeDescrption SEQUENCE 一個有序的類型集合 SEQUENCE OF 一個給定類型的有序集合 SET 一個無序的類型集合 SET OF 一個給定類型的無序集合 結構類型中可以包含可選的部分, 可選部分也可以有默認值.
Basic Encoding Rules
Basic Encoding Rules 簡稱為 BER, 規定了如何將 ASN.1 值表示為比特數組.
針對不同給數據類型, BER 規定了如下三種編碼方法: Primitive, definte-length encoding, Contructed, definite-length encoding, Constructed, indefinite-length encoding.
BER 編碼包含以下部分:
- Identifier octets: 由類型的 class 和 tag number 構成. 用來聲明該類型是基本類型還是結構化類型.
- Length octets: 對于定長編碼方法, 該部分給定 content 的長度. 對于不定長編碼方法, 該部分指明該類型是不定長的.
- Contents octets: 對于基本類型, 這部分包含對應數據的字節表示. 對于復雜類型, 這部分包含了該數據的 BER 編碼結果.
- End-of-contents octets: 對于不定長編碼方法, 該部分標識 content 的結束. 其他編碼方法, 這部分省略.
下面我們學習一下上述三種編碼方法:
-
Primitive, definte-length encoding
基本數據類型除字符串類型外均使用這種編碼方式. 這種情況下我們的數據編碼結果會是以下形式:
其中不包含 End-of-contents 部分, 因為這里我們使用定長編碼.對于 Identifier, 有兩種形式:
low tag number form: 這種形式下, Identifier 僅用一個字節表示. bit8 和 bit7 用來表示 class, bit6 為 0, 用來表示是基本類型. bit5-1表示 tag number.
high tag number form: 這種形式下, Identifier 會占用一到多個字節. 第一個字節任然是 low tag number form 形式. 但是 bit5-1 應該全為 1. 其余比特用來表示 tag number, 高字節在前.
ClassBit 8Bit 7 Universal 0 0 Application 0 1 Context-specific 1 0 Private 1 1 對于 Length, 也有兩種形式:
Short form: 這種形式下, Length 占用一個字節. bit 8 為 0, 其余七字節用于編碼長度, 因此這種形式用于表示長度 0-127.
Long form: 這種形式下, Length 占用的字節長度為 2-127 個字節. 第一個字節的 bit8 為 1, 其余字節用于表示緊接著有多少個字節用來編碼長度. 高字節在前.
-
Contructed, definite-length encoding
這種編碼方法用于編碼復雜類型和簡單類型中的字符串類型且編碼長度已知.編碼形式與 Primitive, definte-length encoding 類似. 除了 Identifier 字段的第一個字節的 bit6 為 1, 用來表示是復雜類型. -
Constructed, indefinite-length encoding
這種編碼方法用于編碼復雜類型和簡單類型中的字符串類型且編碼長度未知.編碼形式如下:
這里 Length 字段的值為 0x80, End-of-contents 字段的值為兩個字節的 0. 表示該編碼方式為不定長編碼.其余字段的編碼與 Contructed, definite-length encoding 類似. - 當編碼長度在 0-127 之間時, 必須使用 short form 形式編碼 Length 字段
- 當編碼長度大于 128 時, 必須使用 long form 形式且應使用最少的字節對長度進行編碼,也就是說如果長度為192, 那么 Length 字段只能占兩個字節. 第一個字節為0x81, 表示 Length 字段使用 Long form, 且緊接著只有一個字節用于編碼長度信息. 第二個字節為 0xc0, 用來表示長度為 192
- 對于簡單字符串類型, 必須使用 primitive, definite-length 進行編碼
- 對于復雜類型, 必須使用 constructed definite-length 進行編碼
編碼示例
BIT STRING
對 “00000110011011100101110111000000” 進行編碼,
對于 BIT STRING 類型, Identifier 字段應該為 03(這里我們不考慮 class, 僅僅考慮 tag number). 對于 Length 字段, 因為每個1或者0代表一個bit, 因此該值需要 4 字節進行編碼, 因此 Length 字段應該為 04.
編碼結果為:
BER short form encoding/DER encoding: 03 04 06 6e 5d c0 BER long form encoding: 03 81 04 06 6e 5d c0IA5String
對 "test1@rsa.com" 進行編碼, 編碼結果為:
BER short form encoding/DER encoding: 16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d BER long form encoding: 16 81 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d假設我們想將 "test1@rsa.com" 編碼為一個 IA5String 的集合, 該集合中由三個 IA5String 構成: “test1”, “@”, “rsa.com”.
這里我們要編碼一個復雜類型, 那么 Identifier 的 bit6 應該為 1, 代表復雜類型. 而 IA5String 的 tag number 為 0x16, 因此 Identifier 的值應該為 0x36. 因此編碼結果如下:
36 13 16 05 74 65 73 74 3116 01 4016 07 72 73 61 2e 63 6f 6dINTEGER
對 0 進行編碼, 編碼結果如下: 02 01 00
對 127 進行編碼, 編碼結果如下: 02 01 7F
對 128 進行編碼, 編碼結果如下: 02 02 00 80NULL
編碼結果為: 05 00 或 05 81 00
OCTET STRING
對 01 23 45 67 89 ab cd ef 進行編碼, 編碼結果如下: 04 08 01 23 45 67 89 ab cd ef
UTCTime
將要進行 ANS1 編碼的 UTCTime 應該是以下形式之一:
YYMMDDhhmmZ YYMMDDhhmm+hh'mm' YYMMDDhhmm-hh'mm' YYMMDDhhmmssZ YYMMDDhhmmss+hh'mm' YYMMDDhhmmss-hh'mm'where:YY is the least significant two digits of the year MM is the month (01 to 12) DD is the day (01 to 31) hh is the hour (00 to 23) mm are the minutes (00 to 59) ss are the seconds (00 to 59) Z indicates that local time is GMT, + indicates that local time is later than GMT, and - indicates that local time is earlier than GMT hh' is the absolute value of the offset from GMT in hours mm' is the absolute value of the offset from GMT in minutes對于時間 4:45:40 p.m. Pacific Daylight Time on May 6, 1991 進行編碼,
"910506164540-0700" "910506234540Z"
它的所有表示形式中存在以下兩種:對他們進行編碼的結果為:
17 11 39 31 30 35 30 36 31 36 34 35 34 30 2D 30 37 30 30 17 0d 39 31 30 35 30 36 32 33 34 35 34 30 5aOBJECT IDENTIFIER
一個 Object identifier 的含義是由 registration authorities 賦予的, 這里我們不多說. 列舉一些 Oid 作為示例.
Object identifier valueMeaning { 1 2 } ISOmember bodies { 1 2 840 } US (ANSI) { 1 2 840 113549 } RSA Data Security, Inc. { 1 2 840 113549 1 } RSA Data Security, Inc. PKCS { 2 5 } directory services (X.500) { 2 5 8 } directory services-algorithm 如何編碼呢 ?
編碼后的第一個字節的值為 40 * value1 + value2. (value1 要求是 0, 1 或者 2. value2 要求是 0-39.)
接下來的 value3, value4, …, valuen 以 128 為 base 進行編碼, 高字節在前. 每個數字編碼后除了最后一個字節外其他字節的 bit8 均為 1.舉個例子, 對 { 1 2 840 113549 } 進行編碼:
首先, 40 * 1 + 2 = 42. 因此編碼后第一個自己應該為 0x2a. 840 = 6 * 128 + 72. 因此 第二字節應該編碼的值是 6 且 bit8 為 1, 因此第二位 0x86. 72 編碼為第三字節, 為 0x48. 113549 = 6 * 1282 + 0x77 * 128 + 0x0d. 因此編碼之后應該為 0x86, 0xF7, 0x0d.
因此,最終編碼結果為 06 06 2a 86 48 86 f7 0d.編碼 Name (X.501 type)
這一節, 我們試著來對 Name 類型進行 ASN.1 編碼.
Name 類型的 ASN.1 描述如下:
Name ::= CHOICE {RDNSequence }RDNSequence ::= SEQUENCE OF RelativeDistinguishedNameRelativeDistinguishedName ::=SET OF AttributeValueAssertionAttributeValueAssertion ::= SEQUENCE {AttributeType,AttributeValue }AttributeType ::= OBJECT IDENTIFIERAttributeValue ::= ANYX.502 中定義 AttrubteType 可以有以下值:attributeType OBJECT IDENTIFIER ::={ joint-iso-ccitt(2) ds(5) 4 }countryName OBJECT IDENTIFIER ::= { attributeType 6 }organizationName OBJECT IDENTIFIER ::={ attributeType 10 }commonUnitName OBJECT IDENTIFIER ::={ attributeType 3 }下面我們來一步一步的編碼!
-
AttributeType
06 03 55 04 06 // countryName 06 03 55 04 0a // organizationName 06 03 55 04 03 // commonName
上述 countryName, organizationName, commonName 的值均為 OCTET STRING. 因此他們的 DER 編碼方法應該為 primitive, definite-length. 對于 OBJECT IDENTIFIER 類型, Identifier 字段應該為 06. bit8 和 bit7 為 0, 代表 Universal class. 他們的 Oid 分別為 { 2 5 4 6 }, { 2 5 4 10}, { 2 5 4 3}. 因此編碼分別為: -
AttributeValue
13 02 55 53 // "US" 13 14 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f 6e // "Example Organization" 13 0b 54 65 73 74 20 55 73 65 72 20 31 // "Test User 1"
假設上述 countryName, organizationName, commonName 屬性的值類型均為 PrintableString, 且值分別為 “US”, “Example Organization”, “Test User 1”.
編碼結果分別為: -
AttributeValueAssertion
30 09 // countryName = "US" 06 03 55 04 06 13 02 55 53 30 1b // organizationName = "Example Organization" 06 03 55 04 0a 13 14 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f 6e 30 12 // commonName = "Test User 1" 06 03 55 04 0b 13 0b 54 65 73 74 20 55 73 65 72 20 31
AttributeValueAssertion 是 AttributeType 和 AttributeValue 的有序集合.
編碼結果如下: -
RelativeDistinguishedName
31 0b 30 09 ... 55 5331 1d 30 1b ... 6f 6e31 14 30 12 ... 20 31
RelativeDistinguishedName 是 AttributeValueAssertion 的無序集合.
編碼結果如下, 為了直觀, 我們省略了部分編碼結果, 該結果均為上述步驟編碼所得. -
RDNSequence
30 42 31 0b ... 55 53 31 1d ... 6f 6e 31 14 ... 20 31
RDNSequence 是 RelativeDistinguishedName 的有序集合.
編碼結果如下: -
Name
30 4231 0b30 09 06 03 55 04 06 // attributeType = countryName 13 02 55 53 // attributeValue = "US"31 1d30 1b06 03 55 04 0a // attributeType = organizationName 13 14 45 78 61 6d 70 6c 65 20 4f 72 67 67 61 6e 69 7a 61 74 69 6f 6e // attributeValue = "Example Organization"31 1430 1206 03 55 04 03 // attributeType = commonName 13 0b 54 65 73 74 20 55 73 65 72 20 31 // attributeValue = "Test User 1"
Name 的值是一個 CHOICE 類型. 編碼結果如下:
Distinguished Encoding Rules
Distinguished Encoding Rules 簡稱為 DER, 是 DER 編碼的一個子集. 區別在于 BER 編碼結果不唯一, 而 DER 編碼結果唯一.
DER 編碼在 BER 編碼的規則之上添加了如下限制:
Ending.
最后分享一個好用的在線解析 ASN.1 的工具: https://lapo.it/asn1js/.
總結
- 上一篇: 改进初学者的PID-采样时间
- 下一篇: 外设驱动库开发笔记32:HLPM025K