Basic Encoding Rules
Basic Encoding Rules (abbreviazione BER) è un sistema di codifica composto da una serie di regole per la conversione di dati eterogenei in flussi di byte.
La codifica BER è strettamente legata allo standard ASN.1 ed è utilizzata per le comunicazioni SNMP e LDAP.
Sistema di codifica
Il sistema di codifica è basato sul concetto di tripla <T,L,V> (Type o Tag, Length, Value) dove:
- Type o Tag : indica il tipo del dato codificato
- Length : indica la lunghezza in byte di "Value"
- Value : È il dato codificato vero e proprio
Quindi ad esempio per codificare il dato 7 come INTERO occorreranno 3 bytes:
- il primo che indica il Type ();
- il terzo è la codifica del dato INTERO secondo le regole BER (in questo caso );
- il secondo che indica la Length di v (in questo caso = ).
In definitiva INTEGER 7 in BER diviene dove si distinguono chiaramente T,L e V.
BER e ASN.1
BER è strettamente legata ad ASN.1 soprattutto per quanto riguarda i tipi di dati. Come si può immaginare la codifica di V dipende dal tipo T. Ci sono alcuni tipi predefiniti in ASN.1 (si dice che sono Tag appartenenti alla Class UNIVERSAL). Per maggiori informazioni a tal proposito consultare [1] o [2]
Codifica BER
In generale quando si deve effettuare la codifica BER di un dato si procede ne seguente modo:
- si codifica T;
- si codifica V;
- dalla lunghezza di V si passa alla codifica di L.
Vediamo ora la codifica di ogni campo.
Codifica di T
La codifica del campo T di solito chiede un unico Byte. La codifica dipende dai seguenti fattori:
- La classe di appartenenza del Tag
- Il tipo è PRIMITIVE o CONSTRUCTED
- L'identificativo del Tag nella classe di appartenenza
Se l'identificativo del tipo allora la codifica di T richiede un unico byte, altrimenti il numero di byte di T dipenderà dal valore di ID
Primo byte di T
Vediamo qui sotto come si presenta il primo byte di T:
La codifica di CLASS segue la seguente tabella:
bit 7 bit 6 CLASS ----------------------------------- 0 0 UNIVERSAL 0 1 APPLICATION 1 0 context-specific 1 1 PRIVATE
Il bit P\C = 0 indica che il tipo è PRIMITIVE (cioè è un tipo semplice come INTEGER o OID)
Il bit P\C = 1 indica che il tipo è CONSTRUCTED (cioè è un tipo composto da più tipi semplici come ad es. SEQUENCE)
I 5 bit di TAG invece:
- Contengono il valore binario di ID se
- Contengono se
Nel primo caso, come è stato già detto, il T è composto da un unico byte. Nel secondo caso vanno invece codificati gli altri bytes di T.
Altri byte di T
Per codificare gli altri byte si procede nel seguente modo:
- si converte l' ID in binario
- si aggiunge un 1 ogni 7 bit
- si completa il byte con un 1 in testa
NB !!! da correggere !!! l'ultimo byte che compone l'ID viene composto con uno '0' in testa, proprio per indicare che l'ID finisce con quel byte.
Ad es. se ID = 250 in base 10, allora:
- 11111010 -> 1 11111010
- 1 11111010 -> 10000001 11111010
In definitiva ID = 250 viene codificato con
Esempio 1 di codifica di T
Codifica di INTEGER. Questo è di classe UNIVERSAL ed è PRIMITIVE. Il suo ID nella classe UNIVERSAL è 2.
- e quindi basterà 1 solo byte per T
Quindi:
- CLASS = 00
- P\C = 0
- Tag = 00010
da cui se segue:
Esempio 2 di codifica di T
Supponiamo di voler codificare un tipo PRIVATE e PRIMITIVE con
- e quindi serviranno più byte per T
Primo byte:
- CLASS = 11
- P\C = 0
- Tag = 11111 -->
Altri byte (come abbiamo visto in precedenza) sono pari a perché
In definitiva in questo caso ed è di 3 byte.
Codifica di L
In questa sezione si indica con Len(V) il numero di byte di V.
La codifica di L è strettamente legata alla lunghezza del dato codificato V. Se si conosce a priori Len(V) allora si procede con la codifica definite length, altrimenti si applica la codifica indefinite length. La prima tecnica è preferibile in quanto permette un Decoding più semplice.
Encoding di L 'definite length'
In questo tipo di encoding si distinguono 2 casi distinti:
- se allora L viene codificato in 1 byte (short definite form)
- se allora L viene codificato in più byte (long definite form)
Caso 1: L in 1 byte - short definite form
Questo è il caso più semplice. V è codificato in meno di 127 bytes ed L contiene esclusivamente il valore di Len(V) in esadecimale.
Il limite di 127 byte è dato dal fatto che 127 è 7F in esadecimale (01111111 in binario) e quindi il primo bit di L è sicuramente zero.
Ciò è utile in fase di Decoding, infatti se il primo bit è zero, significa che è stata usata la codifica di L su un solo byte.
Caso 2: L in più bytes - long definite form
In questo caso si procede nel seguente modo:
- si codifica in binario Len(V)
- si calcola , cioè la lunghezza in bytes di Len(V)
- si pone nel primo byte di L =
- si pone nei bytes seguenti Len(V)
La formula del punto 3 ha la seguente giustificazione:
- aggiungendo si obbliga l'ultimo bit del primo byte di L ad essere 1.
- nei primi 7 bit del primo byte di L c'è in realtà la lunghezza dei byte restanti di L, infatti indica proprio la lunghezza di L
In fase di Decoding per capire che stiamo usando una codifica di L su più byte di tipo long definite form deve quindi essere:
- il primo bit del primo byte di L= 1
- gli altri 7 bit del primo byte devono essere diversi da
Esempio 1 di Codifica di L in definite form
V è codificato su 120 bytes.
Poiché deve essere quindi usata la short definite form
- In definitiva:
Esempio 2 di Codifica di L in definite form
V è codificato su 1000 bytes.
Poiché deve essere quindi usata la long definite form.
Quindi:
- byte 1 di L
- bytes 2,3 di L
In definitiva: ed è di
Encoding 'indefinite length'
Questo tipo ti encoding è usato quando non si conosce la Len(V) a priori.
In questo caso si procede con i seguenti passi:
- si pone
- si aggiunge V
- in coda a V si aggiungono 2 bytes di zeri
Codifica di V
La codifica di V, come è stato più volte detto, dipende tal tipo T e dalla sua definizione tramite sintassi ASN.1 In questa sede sarà illustrata la codifica dei 3 tipi principali: INTEGER, OCTECT STRING e OBJECT ID. Per una panoramica completa di codifica decodifica si rimanda ancora a [3] o [4]
Codifica di INTEGER
La codifica di un dato INTEGER dipende dal suo segno. Il primo bit del primo byte codificato è detto bit segno. Se questo è 0 allora il numero è positivo, altrimenti è negativo.
INTEGER Positivi
In questo caso la codifica è data dal valore binario del numero, a patto che si rispetti il bit segno, altrimenti bisogna aggiungere in testa un byte di zeri
Infatti se l'integer è ad es. allora si ha: . In questo caso il bit segno è zero e quindi la codifica è corretta.
Se invece l'integer è ad es. 250 allora si ha: . In questo caso il bit segno è 1 e quindi in fase di decodifica rappresenterebbe un numero negativo, vanno quindi aggiunti gli zeri in testa. In definitiva . Come si puo' notare, aggiungendo gli zeri in testa il bit segno è correttamente zero.
INTEGER Negativi
Per gli integer negativi si utilizza il Complemento a due del valore. Ciò assicura che il bit segno è sempre negativo. In particolare i passi da seguire sono:
- si codifica con le regole indicate sopra
- si calcola il Complemento a uno cioè si nega bit a bit
- si aggiunge infine al numero ottenuto
Ad esempio se valore = -100 si ha:
- (vedi es. INTEGER Positivi)
- complemento a 1:
- aggiungere . Si ottine
Quindi
Se invece valore = -250 si ha:
- (vedi es. INTEGER Positivi)
- complemento a 1:
- aggiungere . Si ottine
Quindi
Codifica di OCTECT STRING
In ASN.1 sono definite una grande varietà di stringhe, ma l'OCTECT STRING è quella fondamentale. In questo caso ogni carattere occupa 1 byte e viene utilizzata la codifica ASCII.
Ad esempio l' OCTECT STRING "ciao" viene codificato in 4 byte in
Codifica di OBJECT IDENTIFIER
Un OBJECT IDENTIFIER (abbreviato è OID) è un identificatore univoco di un campo della MIB.
Un OID è formato da n numeri divisi da n-1 punti. Un esempio di OID è il seguente: 1.2.250.1.16.9
I passi per codificare un OID sono i seguenti:
- si pone nel primo byte il valore
- si codificano gli altri numeri in byte separati con le seguenti regole:
- se si usa semplicemente la rappresentazione binaria di numero
- se si usa la rappresentazione binaria di numero con:
- uno 0 inframezzato ad ogni 7 bit
- un 1 come primo bit del primo byte
Ad esempio codifica di 1.2.250.1.16.9:
- -> 1000 0001 | 0111 1010 -> 1000 0001 0111 1010 =
Quindi 1.2.250.1.16.9 -> 2A 817A 01 10 09 =
Voci correlate
Collegamenti esterni
- (EN) Olivier Dubuisson - ASN.1: Communication Between Heterogeneous Systems - Free PDF book
- (EN) Professor John Larmouth - ASN.1 Complete - Free PDF book