有一種密碼學專用語言叫做ASN.1

2022-07-28 18:01:32

簡介

ASN.1是一種跨平臺的資料序列化的介面描述語言。可能很多人沒有聽說過ASN.1, 但是相信有過跨平臺程式設計經驗的同學可能都聽過protocol buffers和Apache Thrift,雖然ASN.1和上面兩個語言相比不是那麼出名,但是ASN.1的出現要比他們早的多,早在1984年ASN.1就出現了。

和他們相比ASN.1並沒有提供單一的開源實現,而是作為一種規範來供第三方供應商實現的。ASN.1主要用在定義各種基礎協定中,比如常用的LDAP,PKCS,GSM,X.500等。

ASN.1是一種和平臺、語言無關的描述語言,可以使用很多ASN.1的翻譯工具,將ASN.1翻譯成為C, C++, Java等程式碼。

ASN.1的例子

既然ASN.1是一個描述語言,那麼我們先來看一個直觀的例子。ASN.1的基礎是module, 我們看一下ASN.1中module的例子:

StudentCards DEFINITIONS AUTOMATIC TAGS ::= BEGIN

StudentCard ::= SEQUENCE {
dateOfBirthday DATE,
student    StudentInfo
}

StudentInfo ::= SEQUENCE {
studentName    VisibleString (SIZE (3..50)),
homeAddress Address,
contactPhone   NumericString (SIZE (7..12))
}

Address::= SEQUENCE {
street  VisibleString (SIZE (5 .. 50)) OPTIONAL,
city    VisibleString (SIZE (2..30)),
state   VisibleString (SIZE(2) ^ FROM ("A".."Z")),
zipCode NumericString (SIZE(5 | 9))
}

END

上面的例子中,我們使用ASN.1定義了一個StudentCard,最外層的以BEGIN和END包圍的就是module。StudentCards是module的名字,首字母必須大寫。

其中::= 是一個賦值符號。

module中可以有多個type, type的名字也必須首字母大寫,例如上面的StudentCard,StudentInfo等等。

每個type中定義了它的組成元件,元件的名字首字母必須小寫,這些元件的名字又叫做identifiers。

上面的dateOfBirthday後面接的DATE是ASN.1中內建的型別。而student後面的StudentInfo是一個自定義型別,並且同樣包含在module中。

StudentInfo中的studentName是一個VisibleString,這個String的限制是size在3到50之間。

上面我們定義module的時候在module後面加上了AUTOMATIC TAGS,這是什麼意思呢?

在ASN.1中,tags是ASN.1訊息中每個元件的內部識別符號,以Address為例,我們希望給Address中的每個屬性都指定一個內部的識別符號,如下所示:

Address::= SEQUENCE {
street  [0] VisibleString (SIZE (5 .. 50)) OPTIONAL,
city    [1] VisibleString (SIZE (2..30)),
state   [2] VisibleString (SIZE(2) ^ FROM ("A".."Z")),
zipCode [3] NumericString (SIZE(5 | 9))
}

這裡面的[0] [1] 就是識別符號,當然,我們可以在定義module的時候手動指定這些tags,但是如果我們使用AUTOMATIC TAGS,這些識別符號會自動建立,從而避免了手動建立識別符號可能帶來的問題。

ASN.1中的內建型別

通過上面的講解,我們對ASN.1有了一個基本的概念。如果想要對ASN.1進行更加深入的研究,那麼我們首先要知道ASN.1中的內建型別。

一般來說ASN.1中有下面的資料型別:

  • BOOLEAN

BOOLEAN和程式語言中的布林值是一致的,它有兩個可能得值:TRUE和FALSE。下面是具體而用法:

removed BOOLEAN ::= TRUE
  • INTEGER

INTEGER表示的是一個整數,如下所示,表示的是一個年例範圍是0到100,最終的取值是18:

age INTEGER (0..100) ::= 18
  • BIT STRING

位元組的位表示方法,可以給一個byte中的每一個bit進行設值:

Status ::= BIT STRING {
married(0),
handsome(1),
kind(2)
}
myStatus Status ::= {handsome, kind}

上面的例子中,我們設定了Status,並且使用Status賦值給了一個變數myStatus。

  • OCTET STRING

8進位製表示的字串:

octetExample ::= OCTET STRING
  • DATE

表示日期,格式是"YYYY-MM-DD":

birthday DATE ::= "1990-11-18"
  • TIME-OF-DAY

表示日期中的時間,格式是"HH:MM:SS":

startTime TIME-OF-DAY ::= "09:30:00"
  • DATE-TIME

時間加日期的格式,它的格式"YYYY-MM-DDTHH:MM:SS",如下所示:

endTime DATE-TIME ::= "2022-01-10T18:30:23"
  • REAL

REAL表示的是一個浮點數,可以如下表示:

Amount ::= REAL
  • ENUMERATED

ENUMERATED表示的是一個列舉,可以如下表示:

Colors ::= ENUMERATED {black, red, white}
myColor Colors ::= white
  • SEQUENCE

SEQUENCE表示的是專案的序列合集,如下所示:

StudentInfo ::= SEQUENCE {
name VisibleString,
phone NumericString
}
max StudentInfo ::= {name "J.Max", phone "18888888888"}
  • SEQUENCE OF

SEQUENCE OF表示的是一個list:

breakTimes SEQUENCE OF TIME-OF-DAY ::= {"10:00:00", "12:00:00", "14:45:00"}
  • CHOICE

CHOICE表示從眾多的item中選擇一個:

Identity ::= CHOICE {
name VisibleString,
phone VisibleString,
idCard VisibleString
}
jack Identity ::= name: "jack"
  • IA5String

IA5String表示的是ASCII字元,並且包含有控制字元。

SampleString ::= IA5String
  • VisibleString

VisibleString表示的是ASCII字元,其中不包含有控制字元。

SampleString ::= VisibleString
  • NumericString

NumericString表示的是數位和空格。

SomeNumber ::= NumericString
  • UTF8String

UTF8String表示的是Unicode字元

UnicodeString ::= UTF8String
  • NULL

是一個空值,用來佔位。

ASN.1中的限制語法

ASN.1中可以定義很多個欄位,有些欄位可能會有一些限制,比如手機號只能用數位,名字有長度限制等。

這些限制在ASN.1中叫做Constraints,一般來說有下面的一些限制:

  • FROM

FROM提供了一個資料值的讀取範圍,如下:

PermittedChars ::= IA5String (FROM("ABCDEFG1244"))

PermittedChars只允許從"ABCDEFG1244"選擇。

  • PATTERN

PATTERN表示的是正規表示式,如下所示:

phoneNumber ::= IA5String (PATTERN "1[0-9]#10")

上面列出的是一個簡單的手機號碼的正規表示式。

  • SIZE

SIZE可以表示字串的長度或者陣列的長度:

       Name ::= IA5String (SIZE (4..7))
       NameList ::= SEQUENCE SIZE (1..25) OF Name
  • RANGE

使用..可以表示一個範圍:

Age ::= INTEGER (0..100)
  • 單一值

從提供的值列表中挑選一個:

Colors ::= UTF8String ("Blue" | "White")

總結

以上就是ASN.1資料結構描述語言的基本介紹了,有了這些基礎,我們就可以很容易讀懂使用ASN.1來描寫的資料結構了。

更多內容請參考 http://www.flydean.com/46-asn-1/

最通俗的解讀,最深刻的乾貨,最簡潔的教學,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!