Hlavní navigace

ASN.1 - příklad X.509, základy a kódování

13. 9. 2005
Doba čtení: 12 minut

Sdílet

ASN.1 je abstraktní syntaxová notace, používaná například v kryptografii, u certifikátů X.509 či v elektronické poště formátu S/MIME. Dnes si ukážeme příklad definičního zápisu formátu certifikátů X.509 v ASN.1, základy jazyka ASN.1 Kódování dat pomocí pravidel BER. Uvedeme si též příčiny vzniku jiných typů kódování (DER, PER, SER apod).
Tento článek navazuje a dokončuje úvodní díl ASN.1 – koncept abstraktní syntaxové notace.

Příklad – zápis certifikátu X.509 v ASN.1

Základní formát certifikátu X.509 v3 je pomocí ASN.1 definován těmito dvěma zápisy:


Certificate  ::=  SEQUENCE  {
tbsCertificate       TBSCertificate,
signatureAlgorithm   AlgorithmIdentifier,
signatureValue       BIT STRING  }
TBSCertificate  ::=  SEQUENCE  {
version          [0] EXPLICIT Version DEFAULT v1,
serialNumber         CertificateSerialNumber,
signature            AlgorithmIdentifier,
issuer               Name,
validity             Validity,
subject              Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID   [1] IMPLICIT UniqueIdentifier OPTIONAL,
                     -- pokud přítomen, version MUSÍ být v2 nebo v3
subjectUniqueID  [2] IMPLICIT UniqueIdentifier OPTIONAL,
                     -- pokud přítomen, version MUSÍ být v2 nebo v3
extensions       [3] EXPLICIT Extensions OPTIONAL
                     -- pokud přítomen, version MUSÍ být v2 nebo v3
}

Typ SEQUENCE je asi nejpoužívanější strukturovaný typ v ASN.1 vůbec. Jedná se o analogii typů record v Pascalu, popř. struct v jazyku „C“. Typ SEQUENCE je seřazená kolekce jednoho nebo více typů, z nichž některé mohou být obsaženy i jen volitelně (optional). Každá hodnota typu je seřazený seznam hodnot – složek, z nichž každá odpovídá typu v definici SEQUENCE, přičemž hodnoty volitelných složek typu nemusí být obsaženy.

Identifikátory složek (např. version, serialNumber, signature) v SEQUENCE  se nikdy nekódují, slouží jen pro orientaci a případné odkazování v rámci ASN.1, dále pro čitelnost specifikace i pro komentování struktury v doprovodném textu, zejména pokud je složka poměrně obecného typu (např. INTEGER). Druh typu složky není nijak zásadně omezen, je možné uvádět jednoduché typy, strukturované typy, dokonce i rekurzivně, pokud rekurzivní typ není jedinou složkou.

Z uvedeného příkladu plyne, že řada definic typů (např. AlgorithmIdentifier, Version, CertificateSerialNumber atd.) zde není zobrazena. Nalézt jejich definice lze buď v rámci modulu samotného doporučení X.509 (např. typ Extensions), nebo jsou jejich definice obsaženy v jiných modulech, popř. souvisejících i s jinými doporučeními, než je právě X.509. Na počátku formálního zápisu modulu X.509 jsou proto uvedeny za slovem IMPORTS názvy jiných modulů, z nichž je potřeba chybějící typové definice dohledat. Modul naopak veřejně vystavuje uvnitř něj definované typy pomocí klíčového slova EXPORTS. Přehled modulů ASN.1 definovaných v rámci X.509 v3 naleznete zde a konkrétní definiční modul certifikátu X.509 v ASN.1 se vší plnou a oficiální parádou je zde. Z přehledu závislostí z modulů X.509 si pak můžete učinit obrázek o všech odkazovaných typech a o existující hloubce zanoření až o cca jedenáct modulů.

Např. typ Name v příkladu je součástí modulu InformationFramework , který je součástí X.501. Typy atributů pro typ RDNSequence ale naleznete (netriviálně) až v X.520, resp. v jeho modulu SelectedAttributeTypes .

Odkazy do modulů jiných doporučení nakonec znamenají, že chcete-li skutečně dokonale porozumět formátu X.509, potřebujete v ideálním případě znát ještě několik dalších doporučení z rodiny X.500, která určují sémantický smysl obsahu v nich definovaných typů.

Pro uvedený příklad certifikátu X.509 je v doporučení určeným kódováním DER (viz níže).

Základy ASN.1

Definičním zápisům v ASN.1 bývá při základní znalosti angličtiny vesměs celkem dobře intuitivně rozumět. Je vhodné vědět, že ASN.1 slouží pro zápis definic typů a definic hodnot.

Typ (type) je pojmenovaná množina hodnot.

Hodnota (value) je rozlišitelný prvek množiny hodnot.

Názvy typů začínají vždy velkým písmenem (např. Certificate, TBSCertificate, ale i AlgorithmIdentifier  apod.), hodnoty (příklad zde není uveden) a identifikátory (např. version, serialNumber) začínají malými písmeny.

Klíčová slova jazyka ASN.1 a již „vestavěných typů“ se zapisují téměř výhradně pouze velkými písmeny (např. SEQUENCE, EXPLICIT, IMPLICIT). Bohužel zde existuje několik výjimek starých znakových řetězcových typů, jako je např. IA5String. Rovněž jen výjimečně klíčová slova ASN.1 sestávají ze dvou slov spojených mezerou, např. v příkladu X.509 názvu vestavěného typu  BIT STRING.

Typy lze v ASN.1 dělit na jednoduché a strukturované (též zvané konstruované). Jednoduché typy je možné v abstraktní (ale i kódovací) rovině považovat za dále nedělitelné „atomické“ typy. Ostatní typy se v ASN.1 vytvářejí z jednoduchých typů několika různorodými postupy.

Z jiného pohledu obsahuje ASN.1 množství vestavěných typů, jež lze zhruba rozdělit:

  • základní jednoduché typy ( INTEGER, BOOLEAN, ENUMERATED, NULL, BIT STRING, OCTET STRING, REAL, OBJECT IDENTIFIER…),
  • znakové řetězcové typy založené na tzv. ISO Reg v ISO 2022 a ISO 2375 ( VisibleString, IA5String, TeletexString, VideotexString, GraphicString, GeneralString),
  • znakové řetězcové typy z ISO 10646 / Unicode ( UniversalString, UTF8StringBMPString),
  • znakové řetězcové typy z ITU-T ( PrintableString a NumericString),
  • znakový řětězcový typ neomezeně obecný – CHARACTER STRING,
  • řetězcové typy pro datum-čas a popis objektů ( GeneralizedTime, UTCTime, ObjectDescriptor),
  • strukturované typy ( SEQUENCE, SET, SEQUENCE OF, SET OF),
  • další typy ( CHOICE, ANY…).

V ASN.1 je nadbytečně velké množství řetězcových typů. To souvisí s historickým vývojem standardů pro znakové abecedy v ISO, v ITU-T a samotném ASN.1.

Historicky se textové řetězce v ASN.1 vyvíjely od typu PrintableString, jenž bohužel neobsahuje znak „@”, nutný pro zápis adresy internetové elektronické pošty. Proto se do kryptografických standardů prosadily místy zejména řetězce IA5String, a pro zápis mezinárodních znaků UTF8String, jenž je preferován v prostředí Internetu, popř. i  BMPString.

Z uvedených typů stojí za zmínku i typ OBJECT IDENTIFIER. Typ OBJECT IDENTIFIER neslouží pro obsažení vlastního objektu (kterým se v kontextu ASN.1 míní dobře definovaný kus informace, definice nebo specifikace, která vyžaduje jednoznačné pojmenování za účelem identifikace při vzájemné komunikaci), ale pro zápis syntaxe identifikátoru objektu (pojem objekt v ASN.1 nikdy nemá zhola nic společného s objektovým programováním, jedná se o zcela jiné koncepty). Samotný objektový identifikátor (též OID) je vždy světově jedinečný a plní v ASN.1 podobnou funkci, jako ve webových systémech mají jednoznačné identifikátory URI. Esenciálně je OID seznam celých kladných čísel ve složených závorkách. Způsob zápisů OID plyn nejlépe z příkladů:


id-set         OBJECT IDENTIFIER ::= { 2 23 42      }
id-set-vendor  OBJECT IDENTIFIER ::= { 2 23 42 9    }

Názvy objektových identifikátorů musí začínat malými písmeny (id-set) a slouží pro uvádění objektového identifikátoru v jiných částech definic, nebo z jiných modulů ASN.1 Je též možné nahradit totožnou část sekvence zápisu identifikátorem, následující zápis je totožná hodnota OID jako výše:


id-set-vendor  OBJECT IDENTIFIER ::= { id-set 9 }

Protože čistá sekvence nezáporných celých čísel je málo vypovídající a náchylná k chybám při opisování, existuje ještě další možnost zápisu identifikátoru, v němž je ke každé složce přiřazen ještě popisný řetězec.


id-set-vendor OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) internationalRA(23) set(42)  vendor(9) }

Objektové identifikátory se dnes používají pro identifikaci doporučení nebo standardů, algoritmů, firem a organizací (včetně registračních autorit), projektů, modulů ASN.1, typů ASN.1 (abstraktní syntaxe), kódovacích pravidel (přenosové syntaxe), informačních objektů, SNMP MIB (Management Information Base) pro správu sítí apod.

V ASN.1 se definují pouze syntaktická pravidla tvorby hodnoty OID – jejich praktické přiřazování se provádí podle samostatného doporučení X.660.

Ohledně typů ještě stojí za pozornost, že typy je možné „ocedulkovat“ (viz též odstavec níže), čímž vznikne v ASN.1 nový, odvozený typ. Další možností je typy omezit, buď formou „constraint“ nebo „subtype“.

Hodnoty zapsané v ASN.1 se běžně nikdy neobjeví v kódování; slouží pouze pro použití v definicích uvnitř ASN.1 tak, jako se v programovacích jazycích nejčastěji používají konstanty. Používání konstant má smysl při inicializacích nebo na omezení typu, nemá však význam je přenášet, protože nemohou nést žádnou informaci. Kódují se vždy reálná data, jež se právě mají přenášet ve formátu určitého typu.

Během 90. let byly ve snaze o maximální přesnost specifikací do ASN.1 zavedeny tzv. informační objektové třídy, informační objekty a informační objektové množiny, rovněž i použití parametrů v typech a použití maker. Tyto nástroje zaplevelily zápisy v ASN.1 do té míry, že ASN.1 přestalo být intuitivně srozumitelné – proto se např. v internetových specifikacích tyto vymoženosti ASN.1 běžně nepoužívají. Ve výše odkazovaných modulech, registrovaných v ITU-T, však tyto konstrukce naleznete.

Kódovací pravidla BER

V kódování BER (Basic Encoding Rules – základní kódovací pravidla) se reprezentace provádí v oktetové (zde budeme psát spíše bytové) formě. Každá hodnota se zapisuje vždy v tzv. struktuře T-L-V (tag-length-value), tj. cedulka-délka-hodnota. Cedulka T slouží pro indikaci typu obsahu, délka L obsahuje délku kódování hodnoty V, hodnota V obsahuje vlastní „obsah“, tj. hodnotu. BER tak plynule navázalo na v ITU-T již dříve používaný způsob zápisu specifikací pomocí struktur T-L-V.

Např. několik možných hodnot „výšky“ z prvého uvedeného příkladu v minulém článku, v němž se jedná o hodnoty typu INTEGER, může být v BER kódováno dle následující tabulky:

Výška (INTEGER) /dekadicky/ Kódování BER (T-L-V) /hexadecimálně/
71 02 01 47
127 02 01 7F
130 02 02 00 82

Příklad tří různých celých čísel v kódování BER (DER zde totožné)

První číslo (02) je cedulka T indikující typ, v tomto případě typ INTEGER. Do cedulky T se kóduje jak číslo typu, tak tzv. třída typu. Cedulka může být i vícebytová, většinou však bude pouze jednobytová. Druhé číslo (01 resp. 02 na třetím řádku) udává délku L, tj. počet bytů, v nichž následuje za byty L hodnota V. U jednoduchých typů se při kódování většinou pro zápis L rovněž vystačí s jedním bytem, BER však připouští i délku zakódovat ve více bytech (až ve 127 bytech). Třetí, poslední část představuje vlastní hodnotu V. Protože rozebíraný typ INTEGER zahrnuje i záporné hodnoty, kóduje se v dvojkové komplementání formě, do jednoho bytu nelze zapsat hodnotu větší než 127, pro příklad zachycení hodnoty 130 na třetím řádku se již musí použít dva byty.

Příjemce hodnoty (např. 02 02 00 82 ze třetího řádku) zakódované v BER je schopen ze samotného zápisu většinou zjistit její typ i hodnotu, tj. v tomto případě je schopen zjistit, že přijal celé číslo hodnoty 130. V kódování BER se však již neobjevuje informace o tom, jaké abstraktní jméno typ měl, nebo to, že u něj byl uveden identifikátor. BER vždy kóduje reálnou hodnotu, nikoliv abstraktní definice typu.

U strukturovaných (a též řetězcových) typů, jako je např. uvedený příklad typu Zaznam v minulém článku, se u typu SEQUENCE hodnota V dále štěpí pomocí tzv. konstruovaného zápisu, viz obrázek.

1884
Obrázek: kódování BER pro strukturovanou hodnotu (např. typu SEQUENCE se třemi jednoduchými složkami) 

Zobrazené vnořování může mít libovolný konečný počet úrovní, na jeho konci se vždy nachází některý typ v tzv. primitivním kódování (tj. dále nedělitelná hodnota V v trojici T-L-V).

Pravidla BER jsou tedy souhrn jednotlivých pravidel pro kódování T, L a V pro všechny typy ASN.1.

„Cedulky“ jako [0], [1], [2], …

Pravidla kódování by běžně neměla ovlivňovat abstraktní zápis v ASN.1. Bohužel ani tomu tak není zcela bez výjimky, protože první navržená kódovací pravidla BER aspirovala na alespoň částečnou schopnost rozkladu hodnoty dat v přenosové syntaxi i bez znalosti zápisu ASN.1, podle něhož byla stvořena. To vedlo k zavedení tzv. cedulek (tag), jež se příležitostně zpětně objevují i v abstraktním zápisu (v uvedeném příkladu certifikátu X.509 výše jako hodnoty [0], [1], [2], [3]) a slouží v přenosové syntaxi zejména pro odlišení těch položek, které nelze jednoznačně navzájem rozeznat, např. proto, že několik hodnot následujících těsně po sobě je shodného typu a přitom je každá jen volitelně přítomná (optional). Účelem uvedení cedulky je umožnit jednoznačné dekódování reprezentace v BER. Pro posouzení „abstraktních kvalit“ typu (v rovině ASN.1) nejsou cedulky důležité a čtenář nezajímající se o výsledné kódování je může při čtení ignorovat.

Jiné typy kódování (DER, CER, PER, XER, SER…)

V kódování BER existují v jistých případech záměrně vytvořené varianty kódování. Účelem je efektivní implementace v závislosti na prostředí a druhu dat. Podél přenosové trasy však mohou uzly podle své potřeby a platně provádět při retranslaci převod z jedné varianty BER do druhé, aniž by došlo ke změně výsledné přenášené hodnoty dat nebo k porušení pravidel BER. Toto běžně nevadí, pokud data (tj. jejich jistá oktetová reprezentace) nejsou například (elektronicky) digitálně podepsána, nebo jejich integrita není kontrolována jinak.

Při návrhu doporučení X.509 (kde se jedná o podepsaný certifikát – data) byla proto navržena kódovací pravidla DER (Distinguished Encoding Rules – rozlišitelná kódovací pravidla). DER je naprosto shodné kódování jako BER až na to, že ve všech případech variant kódování určuje jednoznačně jednu z variant, a to tu, jež je zpravidla vhodnější pro kratší data. Hodnota v DER bude tedy vždy zakódována jednoznačně a „po cestě“ nemůže dojít k její samovolné změně. Z uvedeného plyne, že dekodér BER bude vždy bez potíží akceptovat data z kodéru DER, obráceně to však nutně neplatí.

Jistým doplňkem k DER jsou kódovací pravidla CER (Canonical Encoding Rules – kanonická kódovací pravidla), která také vychází z BER, ale volí naopak vždy tu z variant, jež je vhodnější pro dlouhá data.

Všechny výše uvedené typy kódování, tj. BER a jeho podmnožiny DER a CER, jsou považovány za upovídané a tudíž neefektivní pro použití v prostředích citlivých na přenosové pásmo, např. v datových sítích GSM. Pokud má příjemce k dispozici příslušné definice ASN.1, je kódování hodnot T a často i L  zbytečné. Pokud je většina kódovaných hodnot jednoduchého typu, je „přehlavičkování“ jasně až 50 procent.

Proto bylo navrženo kódování PER (Packet Encoding Rules – paketová kódovací pravidla). Reprezentace PER zásadně nekóduje cedulky T a délky L, s výjimkou nutných případů. Reprezentace není oktetová, ale bitová, čehož se např. využívá při kodování hodnot typů BOOLEAN i pro kódování přítomnosti volitelných položek optional. Úspora velikosti činívá okolo 40–60 procent podle typu dat. Překvapivě se zjistilo, že PER bývá efektivnějším i na výpočetní čas a prostředky, opět až o polovinu. Cenou je pouze výchozí předpoklad – pro dekompozici zprávy v PER je nutné mít příslušnou definici dat v ASN.1.

Kódování XER (XML Encoding Rules) slouží pro případ, že se data mají přenášet ve formátu XML, nebo se s jeho pomocí mají zobrazovat. Kódování sice není přenosově úsporné, nicméně vlastní přenos může být na nižší úrovni komprimován, takže komunikační pásmo nemusí být přetíženo a přesto lze těžit z dobré čitelnosti formátu.

Za zmínku stojí ještě kódování SER (Signalling Encoding Rules), které vzniklo metodami „zpětného inženýrství“ z některých již dříve existujících protokolů okolo norem Signalling Standard 7. Po získání definic v ASN.1 je možné provádět další rozšiřování těchto protokolů již v ASN.1 a těžit ze všech výhod, jež poskytuje ASN.1 samo o sobě i nástroje s ASN.1 souvi­sející, pro testování bezchybnosti zápisu, pro automatizaci implementací atd.

Další literatura o ASN.1

Je mimo možný rozsah dvou článků podat i jen přehledový popis ASN.1, o vyčerpávajícím ani nemluvě, když samotné reference ASN.1 a jeho kódování sestávají z několika set stran. Hlavní koncepty zde nicméně byly načrtnuty v architektonicko-systémové rovině. Zájemci o podrobnější informace mohou pokračovat dále.

Aktuální referenční popis ASN.1 a souvisejících doporučení se nachází v X.680 až X.693 (papírovou sadu od ITU-T lze mít za cca 197 CHF). Na rozdíl od jiných doporučení lze ale uvedené doporučení zpravidla stáhnout zdarma v elektronické podobě z webu ITU-T. Kromě uvedených doporučení může být vhodné získat i X.660.

cif 24 - early cena - média

Pokud potřebujete mít mermomocí standardy od organizace ISO – ITU-T na ASN.1 a souvisejících doporučeních spolupracuje s ISO od roku 1987. ISO vydává relevantní standardy v rámci standardů ISO 8824 (ASN.1) a ISO 8825 (kódování).

V české literatuře, pokud je mi známo, existuje kapitola o ASN.1 v knize o bezpečnosti v TCP/IP od L. Dostálka. Jinak je též pro komfort mého čtenáře poměrně rozsáhlá výkladová kapitola o ASN.1 v mé studii o elektronickém podpisu.

Co nejčastěji preferujete při kódování dat aplikací pro přenos?

Byl pro vás článek přínosný?

Autor článku

Autor se několik let specializuje na Elektronický podpis v ČR aj. konzultace v oblasti počítačové bezpečnosti.
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).