之前我們講到了優秀的資料描述語言ASN.1,很多協定標準都是使用ASN.1來進行描述的。對於ASN.1來說,只定義了資料的描述是不夠的,它還規定了訊息是如何被編碼的,從而可以在不同的機器中進行通訊。
ASN.1支援一系列的編碼規則,比如BER,DER,CER等。而X.690就是一個ITU-T的標準,它裡面包含了一些對ASN.1進行編碼的規則。
有人要問了,那麼什麼是ITU-T呢?
ITU-T的全稱是International Telecommunication Union Telecommunication Standardization Sector,也就是國際電聯電信標準化部門,主要用來協調電信和資訊通訊技術標準。
X.690主要包含了Basic Encoding Rules (BER),Canonical Encoding Rules (CER)和Distinguished Encoding Rules (DER)這三種編碼規則。
接下來,我們來看下這些編碼規則的實現細節。
BER的全稱是Basic Encoding Rules,它是最早的編碼規則,使用Tag-Length-Value(TLV)的格式對所有資訊進行編碼。
在BER中,每個資料元素都被編碼為型別識別符號、長度描述、實際資料元素,以及可選的內容結束標記,如下所示:
型別識別符號|長度|實際資料|內容結束標記
---|---|---|---|---
Type|Length|Value|只用在不確定長度的情況
所有的編碼都是以位元組為單位的。
ASN.1的型別有下面幾種,下表列出了ASN.1中型別和對應的十進位制的關係:
type名稱 | 基礎型別還是組合型別 | Number(十進位制) |
---|---|---|
End-of-Content (EOC) | 基礎型別 | 0 |
BOOLEAN | 基礎型別 | 1 |
INTEGER | 基礎型別 | 2 |
BIT STRING | 兩者皆可 | 3 |
OCTET STRING | 兩者皆可 | 4 |
NULL | 基礎型別 | 5 |
OBJECT IDENTIFIER | 基礎型別 | 6 |
Object Descriptor | 兩者皆可 | 7 |
EXTERNAL | 組合型別 | 8 |
REAL (float) | 基礎型別 | 9 |
ENUMERATED | 基礎型別 | 10 |
EMBEDDED PDV | 組合型別 | 11 |
UTF8String | 兩者皆可 | 12 |
RELATIVE-OID | 基礎型別 | 13 |
TIME | 基礎型別 | 14 |
Reserved | 15 | |
SEQUENCE and SEQUENCE OF | 組合型別 | 16 |
SET and SET OF | 組合型別 | 17 |
NumericString | 兩者皆可 | 18 |
PrintableString | 兩者皆可 | 19 |
T61String | 兩者皆可 | 20 |
VideotexString | 兩者皆可 | 21 |
IA5String | 兩者皆可 | 22 |
UTCTime | 兩者皆可 | 23 |
GeneralizedTime | 兩者皆可 | 24 |
GraphicString | 兩者皆可 | 25 |
VisibleString | 兩者皆可 | 26 |
GeneralString | 兩者皆可 | 27 |
UniversalString | 兩者皆可 | 28 |
CHARACTER STRING | 組合型別 | 29 |
BMPString | 組合型別 | 30 |
DATE | 基礎型別 | 31 |
TIME-OF-DAY | 基礎型別 | 32 |
DATE-TIME | 基礎型別 | 33 |
DURATION | 基礎型別 | 34 |
OID-IRI | 基礎型別 | 35 |
RELATIVE-OID-IRI | 基礎型別 | 36 |
以上就是ASN.1中的型別和對應的值。接下來我們看下這些型別是怎麼進行編碼的。
ASN.1都是以位元組為單位的,一個位元組是8bits,其中7-8bits表示的是Tag class。2個bits可以表示4種class,如下:
class | value | 描述 |
---|---|---|
Universal | 0 | ASN.1的native型別 |
Application | 1 | 該型別僅對一種特定應用程式有效 |
Context-specific | 2 | 這種型別依賴於context |
Private | 3 |
6bit表示的是這個型別是簡單型別還是組合型別,簡單型別用0,組合型別用1。
還剩下5個bits,可以表示32個不同的值,但是對於ASN.1來說,它的型別是超出32範圍的,所以這5個bits只用來表示0-30的值的範圍。如下所示:
如果想要表示超出30範圍的值,那麼可以使用兩個byte,如下:
前面一個byte的1-5bits全部用1表示,後面一個byte的第8bit用1表示,剩下的7個bits用來表示真實的值。
type編碼之後就是length編碼,length編碼有兩種格式,一種是確定長度的length,一種是不確定長度的length。
如果資料的長度是可預見的,那麼我們就可以使用確定長度的編碼形式,如果長度是不確定的,那麼就可以使用不確定長度的編碼形式。
我們看下不同型別的長度編碼形式:
首先,如果是確定長度,並且長度比較短的情況下,那麼在8bit位設定為0,剩下的7個bits可以表示0-127範圍的長度情況。
如果長度超過了127,那麼可以在8bit設定為1,並且剩下的7個bits表示的是後面儲存長度的byte個數,byte個數的範圍是(1-126)。
如果是非固定長度,那麼在8bit位設定為1,剩下的7bits設定為0。
所有bits都設定為1的是保留值。
在非固定長度的情況下,如果內容結束之後,需要額外附加一個byte表示的End-of-Contents,用來表示非固定長度編碼已經結束了。
Contents是跟在長度後面的byte欄位,Contents的長度可以為0,表示沒有Contents內容。
總體來看BER編碼,通過型別+長度+具體的內容欄位來組成的。
CER的全稱是Canonical Encoding Rules, DER的全稱是Distinguished Encoding Rules,這兩個編碼都是從BER衍生過來的,他們都是BER的變體。
為什麼會有這兩個變體呢?首先考慮一下BER的定義,BER是Basic Encoding Rules,它是一個非常基礎的編碼規則,在很多情況下並沒有提供具體的編碼實現規則,所以需要具體的實現者自行對基礎協定進行擴充套件。
那麼對應的,如果一個實現者宣告自己是支援BER編碼協定的,那麼就意味著這個實現者需要支援所有BER可能的變體編碼規則。
BER為我們提供了一個基礎標準,它的可延伸性很強,雖然我們在架構或者系統應用中經常提到可延伸性,但是在某些情況下,可變性和可延伸性並不是我們所希望的。比如在密碼學中,我們希望編碼規則的是固定的。這樣的情況就需要用到CER和DER編碼。
CER和DER編碼都是BER的擴充套件,他們和BER相比,只規定了一種具體的編碼規則,所以他們的確定性更強。
CER和DER相比,CER使用的是不確定長度的格式,而DER使用的是確定長度的格式。這就是說DER中始終包含了前導的長度資訊,而CER則是是用一個位元組的內容結束符來表示編碼的結束。
另外,在DER中,Bit string, octet string 和受限的字串必須使用基礎型別,不能使用組合型別。
DER被廣泛使用在數位憑證中,比如X.509。
以上就是X.690和對應的BER CER DER編碼詳解,看完本篇文章,你又多會了一門語言,oh yeah!
更多內容請參考 http://www.flydean.com/47-x690-ber-cer-der/
最通俗的解讀,最深刻的乾貨,最簡潔的教學,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!