雖然自訂網路協定常有重造輪子的習慣,但在描述新協定時,沿用既有設計有時更合理。二進位協定中一個常見的既有格式就是抽象語法記法一(Abstract Syntax Notation 1, ASN.1)。
ASN.1 是簡單網路管理協定(Simple Network Management Protocol, SNMP)等協定的基礎,也是各種密碼學值(例如 X.509 憑證)的編碼機制。
ASN.1 與 DER#
ASN.1 由 ISO、IEC 與 ITU 在 X.680 系列中標準化。它定義了一套抽象語法來表示結構化資料;資料在協定中實際如何呈現,則取決於所採用的編碼規則(encoding rules),而編碼規則有很多種。
你最可能遇到的是可辨別編碼規則(Distinguished Encoding Rules, DER),它的設計目標是讓 ASN.1 結構的表示方式無法被誤讀——這對密碼學協定是很有用的性質。
DER 的表示法正是 TLV 協定的好例子。認得 TLV 模式,你就已經掌握了讀懂 DER 傾印的一半基礎。
範例:X.509 憑證#
以下是 X.509 憑證的 ASN.1 定義:
Certificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
extensions [3] EXPLICIT Extensions OPTIONAL
}這份 X.509 憑證的抽象定義可以用 ASN.1 的任何一種編碼格式來表示。
實例:用 OpenSSL 傾印 DER 編碼形式
用 OpenSSL 工具把 DER 編碼形式以文字傾印出來:
$ openssl asn1parse -in example.cer
0:d=0 hl=4 l= 539 cons: SEQUENCE
4:d=1 hl=4 l= 388 cons: SEQUENCE
8:d=2 hl=2 l= 3 cons: cont [ 0 ]
10:d=3 hl=2 l= 1 prim: INTEGER :02
13:d=2 hl=2 l= 16 prim: INTEGER :19BB8E9E2F7D60BE48BFE6840B50F7C3
31:d=2 hl=2 l= 13 cons: SEQUENCE
33:d=3 hl=2 l= 9 prim: OBJECT :sha1WithRSAEncryption
44:d=3 hl=2 l= 0 prim: NULL
46:d=2 hl=2 l= 17 cons: SEQUENCE
48:d=3 hl=2 l= 15 cons: SET
50:d=4 hl=2 l= 13 cons: SEQUENCE
52:d=5 hl=2 l= 3 prim: OBJECT :commonName
57:d=5 hl=2 l= 6 prim: PRINTABLESTRING :democaASN.1 的完整內容足以寫成一本書。實務上你不需要背下規格,只要能認出「這是 ASN.1/DER」,就可以直接把
openssl asn1parse這類現成工具接上去解析。