BER kódování

BER je specifikováno v doporučení X.209. Nověji pak v doporučeních X.690 a X.691.

Cílem BER kódování je převést zápis z ASN.1, tj. z podoby dobře čitelné pro člověka, do podoby (kódování) vhodné pro komunikaci mezi počítači.

Problémem každého kódování je interpretace jednotlivých bitů v každém bajtu. BER specifikuje pořadí v jakém se interpretují jednotlivé bity v každém bajtu tak, že nejvýznamnější bit je vlevo:

Data se v BER kódují vždy ve struktuře tří polí: typ dat, délka a hodnota:


 

Pole typu dat

Pole typu dat je pro tágy menší než 31 jednobajtové. Pro větší tágy je vícebajtové. V praxi je snaha používat v maximální míře tato pole jednobajtová.

Pole typu dat v sobě nese součet tří hodnot, ze kterých je složeno:

Univerzální typy začínají od nuly, aplikační od 64 (šestnáctkově 40), Content-specific od 128 (8016) a privátní od 192 (C016). Není-li typ jednoduchý, tj. je-li strukturovaný, pak se musí přičíst ještě bit J/K, tj. přičte se 32 desítkově, resp. 20 šestnáctkově.

Některé hodnoty univerzálních tágů jsou uvedeny v následující tabulce:
 
Typ
Tág desítkově
Tág šestnáctkově
Poznámka
BOOLEAN 1 1 Nabývá hodnot TRUE a FALSE
INTEGER 2 2 Celá kladná i záporná čísla a nula
BIT STRING 3 3 Řetězec bitů - může být zadán binárně nebo hexadecimálně. 
Příklad: 'A98A'H nebo '1010100110001010'B
OCTET STRING 4 4 Řetězec bajtů (blíže nespecifikovaný)
NULL 5 5 Prázný typ 
OBJECT IDENTIFIER 6 6 Identifikátor objektu (viz samostatná kapitola)
REAL 9 6 {Mantisa,Base,Exponent} = M x BE
ENUMERATED 10 A Výčet hodnot (nemusí být uspořádaný)
SEQUENCE a SEQUENCE OF 16 10 Uspořádaná posloupnost prvků. SEQUENCE OF může být  i prázdná.
SET a SET OF 17 11 Množina prvků (neuspořádaná). SET OF může být i prázdná. 
PrintableString 19 13 0-9 a-z A-Z mezera ' ( ) + , - . / : = ?
T61String 20 14 TeleText podle doporučení T.61 
Kromě PrintableString obsahuje: 
87 102 103 106 107 SPACE DELETE
IA5String 22 16 ASCII, tj. kromě znaků PrintableString obsahuje: SPACE DELETE
UTCTime 23 17 Čas ve formatu UTC. 
Např. 19851106210627.3-0500 
vyjadřuje 11.6.1985 v 21:06:27,3 kde místní časové pásmo je 5 hodin západně od Grenwiche.
VisibleString 26 1A
Příklad:   SEQUENCE  má hodnotu tágu šestnáctkově 10, ale sekvence není jednoduchý typ (skládá se z  prvků tvořící sekvenci), tj. je strukturovaným typem (připočítáváme tedy 2016), takže výsledná hodnota pole typu je:
1016 + 2016 = 3016.

Názvy typů začínají velkým písmenem. Názvy typů které jsou tvořeny pouze velkými písmeny (všechna písmena jsou velká jako např. INTEGER) jsou klíčovými slovy jazyka ASN.1 a nesmí se použít v jiném významu.

Pole délka dat

 Délku je možné principiálně vyjádřit dvěma způsoby: Při explicitní definici délky datového pole rozlišujeme opět dva případy:
  1. Datové pole se skládá z 0 až 127 bajtů, pak pole délky je jednobajtové (tzv. krátká forma pole délka).
  2. Datové pole je delší než 127 bajtů (tzv. dlouhá forma pole délka).
Pro případ explicitní definice délky je význam jednotlivých bitů v poli délky znázorněn na následujícím obrázku.


Poznámka k obrázku: 126x8=1008

Příklad: Datové pole je dlouhé 2 bajty, pak v poli délka může být (šestnáctkově):

Pole data

Pole data pak obsahuje vlastní data.

Příklady

 Příklad 1: Vyjádřete celé číslo 13 v kódování BER.
Celé číslo je univerálního typu INTEGER, který je nestrukturovaný. Určeme hodnotu jednotlivých polí: Výsledek je 02 01 0D nebo 02 81 01 0D atd. (V Kódování DER je přípustné pouze 02 01 0D). Řetězec 02010D se pak přenáší počítačovou sítí a každý ví (i hacker), že se jedná o třináctku.
 

Příklad 2: Nyní můžeme přistoupit ke složitějšímu příkladu. V kódování BER vyjádřete jednu položku z kartotéky zaměstnanců firmy kapitalista.cz. Tato firma má každého zaměstnance popsaného na kartě skládající se ze čtyř položek:
 
příjmení IA5String
jméno IA5String
sex BOOLEAN
známosti BOOLEAN

Jenže každá karta je v sekvencí těchto položek. Vyjádřeno tabulkou
 
příjmení IA5String
jméno IA5String
sex BOOLEAN
známosti BOOLEAN
 
SEQUENCE
 
Což v ASN.1 vyjádříme: 
Zamestnanec ::= SEQUENCE {
    prijmeni    IA5string,
    jmeno        IA5string,
    sex            BOOLEAN,
    znamosti    BOOLEAN }

V ASN.1 se v praxi zápis Typu Zamestnanec   píše "elegantněji":
Zamestnanec ::= SEQUENCE {
    prijmeni    Prijmeni,
    jmeno        Jmeno,
    sex             Sex,
    znamosti    Znamosti }
Kde
   Prijmeni    ::= IA5string,
    Jmeno      ::= IA5string,
    Sex           ::=  BOOLEAN,
    Znamosti  ::=   BOOLEAN }

Místo typu SEQUENCE by se asi měl použít typ SEQUENCE OF, protože kartotéka může být i prázná (když všechny zaměstnance propustíme).
Takže kartu v kódování BER pro zaměstnance: Bobek Bob TRUE (Sex) FALSE (Znamosti) bychom v BER konstruovali  zevnitř (od jednoduchých typů):

Výsledek si můžeme ověřit pomocí konvertoru. Opět provedeme nejprve konverzi do Base64 (vstup se zadává hexadecimálně) a posléze konverzi PEM -> ASN.1 & DER. Výsledek z konvertoru je:

 SEQUENCE
    30 12
  IA5STRING         :Bobek
     16 05 42 6f 62 65 6b
  IA5STRING         :Bob
     16 03 42 6f 62
  BOOLEAN           :1
     01 01 01
  BOOLEAN           :0
     01 01 00

Jak je v BER-kódování kódován prázný typ?

05 00  (jediné přípustné v DER)
05 81 00
atd.
 
 

Jak je to s kódováním typu INTEGER?

Typ INTEGER se kóduje binárně tak, jak je to běžné, tj. nejvýznamější bit nastavený na 1 signalizuje záporné číslo.

Příklady kódování celých čísel:
 
 
Hodnota BER-kódování 
0 02 01 00
12710 = 7F16 02 01 7F
12810 = 8016 02 02 00 80
25610 = 10016 02 02 01 00
-12810  (10016-8016=8016 02 01 80
-12910   (1000016-8116=FF7F16) 02 02 FF 7F

 

Výčet

Pomocí typu INTEGER lze vytvořit výčet tak, že se jednotlivé hodnoty pojmenují identifikátory. V kulatých závorkách za identifikátorem hodnoty je pak uvedena pojmenovaná hodnota.

Obecně: INTEGER [{identifikátor-1 (hodnota-1) ... identifikátor-n (hodnota-n)}]

Příklad:
Barva ::= INTEGER {cervena(1) modra(2) bila (3)}
 

Příklad z definice certifikátu X.509:
Version :== {v1988(0)}

Certificate :== SEQUENCE {
        ...
        version   Version   DEFAULT   v1988
        ...}

Tím se chce sdělit, že identifikátor version je typu INTEGER a není-li položka uvedena, pak se použije hodnota 0.
 
 

Typy SEQUENCE, SEQUENCE OF, SET a SET OF

Jedná se o struktrurované typy (k tágu se připočítává 2016).

Slovo OF v obou případech vyjadřuje, že posloupnost (resp. množina) může být i prázná.

V posloupnosti (SEQUENCE) záleží na pořadí prvků, v množině (SET) nikoliv.

Syntaxe SEQUENCE o n prvcích je:

SEQUENCE  {
        [identifikátor-1] Typ-1 [{OPTIONAL | DEFAULT hodnota-1}],
        ...
        [identifikátor-n] Typ-n [{OPTIONAL | DEFAULT hodnota-n}] }

Syntaxe SEQUENCE OF, SET a SET OF je obdobná, pouze s tím rozdílem, že slovo SEQUENCE je nahrazeno slovy SEQUENCE OF, resp. SET, resp. SET OF.

Slovo OPTIONAL vyjadřuje, že prvek je volitelný (nepovinný). Slovo DEFAULT následované hodnotou pak určuje, že v případě kdy prvek není uveden, pak se použije implicitní hodnota.
 

UTCTime

čas se vyjadřuje v jednom z následujících tvarů: Znak Z specifikuje, že se jedná o GMT. Za znaménkem + či - je časový posun místní časové zóny.

Např.: 19851106210627.3-0500
vyjadřuje 11.6.1985 v 21:06:27,3 kde místní časové pásmo je 5 hodin západně od Grenwiche.
V BER-kódování se UTCTime zpravidla kóduje v ASCII, tj. uvedený čas bude:
31 39 38 35 31 31 30 36 32 31 30 36 32 37 2e 33 2d 30 35 30 30
(pro orientaci: 0=3016, 1=3116 , ...,  mínus je 2d).
Musíme ještě doplnit typ (UTCTime má 1716 ) a délka je 1516 čili:
17 15 31 39 38 35 31 31 30 36 32 31 30 36 32 37 2e 33 2d 30 35 30 30
 
 

Bit string

Řetězec bitů se zpravidla zprava doplňuje výplní tvořenou binárními nulami tak, aby jeho délka byla násobkem 8 (tj. doplní se na bajty).

Zleva se před řetězec doplní bajt binárně vyjadřující o kolik bitů byl řetězec doplněn.

Příklad:
 
Řetězec 01101110 11 
Zprava doplněn šesti binárními nulami 01101110 11000000
Převeden na bajty (vyjádřeno šestnáctkově) 6E C0
Zleva doplněn bajtem vyjadřujícím délku výplně (6) 06 6E C0
BER kódování (03 je tág pro bit string, 03 je i délka) 03 03 06 6E C0

Identifikace objektů