2013-07-17 97 views
0

我在學習語法ASN.1,我已經讀了很多相關材料在線:ASN.1序列混亂

http://www.itu.int/rec/T-REC-X.690-200811-I/en
http://luca.ntop.org/Teaching/Appunti/asn1.html
http://www.obj-sys.com/asn1tutorial/node11.html

我非常困惑於ASN.1 SEQUENCE類型的編碼。總的來說,我意識到SEQUENCE基本上是一個聚合 - 在大多數編程語言中我們稱之爲OBJECT或INSTANCE。它基本上是名稱/值對的列表,類似於JSON對象。但與JSON對象不同,ASN.1 SEQUENCE具有隱式SCHEMA,因爲它是「類」的實例。

因此,對於SEQUENCE類/模式可能是這樣的:

{ 
    name UTF8String 
    age INTEGER 
} 

以及架構的INSTANCE可能是SEQUENCE

{ 
    "John Smith" 
    42 
} 

但我完全糊塗了至於如何分辨實際BER編碼中CLASS和INSTANCE之間的差異。事實上,我很困惑,我甚至不確定ASN.1 SEQUENCE應該是一個類定義還是一個類的實例。

文檔似乎暗示它是一個實例:

8.9序列值

8.9.1序列值的編碼的編碼應是建造。

8.9.2內容字節必須在 定義由一個數據值從每個在序列類型的ASN.1定義 列出的類型的完整編碼的,在他們出現的次序,除非該類型被關鍵字OPTIONAL 或關鍵字DEFAULT引用。

8.9.3的數據值的編碼可以,但不需要,存在對於將其與關鍵字OPTIONAL或關鍵字 DEFAULT引用的類型。如果存在,它將出現在對應於ASN.1定義中的類型外觀的點 的編碼中。

所以看起來SEQUENCE只是一個數據值的列表,它必須對應某個模式(類)。但ASN.1沒有CLASS類型,那麼如何獲得實際的類,那麼您知道給定的SEQUENCE是什麼類是一個實例?

回答

1

假設你編寫如下:

ř定義AUTOMATIC TAGS :: =

BEGIN

USPostalAddress :: = SEQUENCE {

street  IA5String, 

    city  IA5String, 

    state  IA5String (SIZE (2)) (FROM("A".."Z")), 

    zipcode IA5String (SIZE (5)) (FROM("0".."9")) 

}

END

上面BEGIN和END之間的部分稱爲「類型分配」。 「USPostalAddress」是(用戶定義的)「類型」的名稱。通過編寫上述內容,您已經指定了一個用戶定義的類型,並給出了一個名稱。每個SEQUENCE構建體(例如上述SEQUENCE構建體)是「類型」。這是一個複雜的類型,因爲它包含一個或多個「字段」,每個字段都有其自己的類型。上述類型的一種可能的「值」表示如下:

{街道「1234主街」,城市「紐約」,國家「NY」,郵政編碼「12345」}

我們只是談論類型和它們的價值,而不是關於類和實例。就像你可以有一個類型爲INTEGER(0..15)的值是0到15之間的整數一樣,你可以有一個SEQUENCE類型,其值是低級值的排列。上面的序列類型是可以在ASN.1中定義的數據結構(「類型」)的一個非常簡單的例子。

(在ASN.1還有一種叫做「類」,但它是一個完全不同的事情。)

在ASN.1,協議的消息通常被指定爲頂層類型(通常它們是SEQUENCE或CHOICE類型)。特定的「消息值」是頂級類型的值。當您掌握了頂級類型的值時,可以使用標準編碼規則之一(BER,PER等)將該值編碼爲位流。當您收到來自網絡的比特流時,您知道這是一個以BER,PER等編碼的特定ASN.1類型的值,您可以解碼這些比特並獲得原始值。

0

ASN.1文件包含通常類型分配(類型定義)這樣SEQUENCE類型:

myMessage ::= SEQUENCE 
{ 
    a INTEGER(0..100), 
    b INTEGER 
} 

ASN.1文件中這些序列類型可以被認爲相同C++/JAVA或結構定義類在C.

SEQUENCE的實例可以採用編碼格式(BER,PER,DER等)或者以程序內部的本地格式(對象/變量)。

例如,你怎麼能實現那些在C代碼:

struct myMessage_t   
{ 
    int a; 
    int b; 
}; 

char buffer[1000]; // BER encoded instance will be stored to this buffer 
myMessage_t msg;  // this is the local instance 

msg.a = 1; 
msg.b = 2; 

size_t berLen = berEncode_myMessage(&msg, buffer, sizeof(buffer)); 

和解碼側爲:

myMessage_t msg2;    
berDecode_myMessage(buffer, berLen, &msg2); 
assert(msg2.a == 1); 

通常你知道什麼是編碼實例的頂層類型,你解碼之前它。