Hlavní navigace

Analogie ASN.1

14. 7. 2004
Doba čtení: 6 minut

Sdílet

ASN.1 neboli Abstraktní Syntaktická Notace verze 1 je formální jazyk pro popis strukturovaných dat pro komunikační protokoly distribuovaných systémů. Jinými slovy, na první pohled to vypadá nepříjemně abstraktně a taky to nepříjemně abstraktní je. Cílem tohoto článku je demonstrovat ASN.1 co možná konkrétně, na praktickém příkladu, se kterými se setkávají nevinní praktikující programátoři (jako já).

ASN.1 neboli Abstraktní Syntaktická Notace verze 1 (potěšilo mě, když jsem se dozvěděl, že žádná jiná verze není a nebude) je formální jazyk pro popis strukturovaných dat pro komunikační protokoly distribuovaných systémů. Jinými slovy, na první pohled to vypadá nepříjemně abstraktně a taky to nepříjemně abstraktní je. Cílem tohoto článku je demonstrovat ASN.1 co možná konkrétně, na praktickém příkladu, se kterými se setkávají nevinní praktikující programátoři (jako já). Vědět, že autentizační certifikáty pro PKI vycházejí z telekomunikačního standardu X.509, který používá ASN.1, může být ohromný pokrok…

ASN.1 vs. XML

Dalším krokem je zjištění, že většina jednovětých definic ASN.1 popisuje zrovna tak dobře XML. Obě technologie skutečně řeší tentýž problém strojové komunikace (a samozřejmě nejsem první kdo si toho všimnul) – ale řeší ho jinde. ASN.1 byl vyvinut pro komunikaci v telefonních sítích (byl standardizován v 80. letech komisí CCITT) – v zásadě hierarchických a rozhodně uzavřených – zatímco XML je pro Internet. Srovnání těchto technologií je tedy velice instruktivní.

Na první pohled viditelným rozdílem mezi ASN.1 a XML daty je jejich čitelnost. ASN.1 data jsou binární: šetří každý bit a při pohledu prostým okem jsou nerozlišitelná od šumu. To je velká výhoda v sítích, kde se platí za každý byte – například v páteřních sítích telekomunikačních operátorů – a ovšem i bariéra pro masové rozšíření. Distribuované aplikace na mobilních zařízeních používající ASN.1 by opravdu byly efektivnější než Web Services – kdyby si někdo dal tu práci a implementoval je… A efektivnější nejen v šířce pásma: ASN.1 data jsou poskládána tak, aby se dala parsovat s minimální pamětí a výkonem procesoru. Při srovnání s XML nelze také pominout, že ASN.1 data obecně nejsou v dokumentech. Certifikáty jsou dokumenty, ale komunikační protokoly definované pomocí ASN.1 pracují s proudy dat, které vůbec nemusejí mít konec.

Zásadním rozdílem mezi ASN.1 a XML je jejich postoj k datovým typům: zatímco primárním typem XML je řetězec znaků Unicode (a další typování je volitelné), veškerá ASN.1 data musejí mít definovaný typ, odpovídající zhruba deklaraci struct v jazyce C. Striktní typování vede k silnějším vazbám (coupling) mezi komunikujícími stranami. To nemusí být nevýhoda v konkrétním projektu, ale rozhodně je to handicap pro technologii navrhovanou pro „celý Internet“.

Stručně řečeno:

Tabulka č. 585
  ASN.1 XML
styl Stanford Berkeley
věk starý mladý
jazyk Lisp C
scéna katedrála bazar
motto Do the Right Thing Worse is Better

…ale možná to takhle zní poněkud kabalisticky…

BER, CER, DER…

Stejně jako je serializovaný XML dokument pouhým zápisem abstraktního infosetu (který se koneckonců dá serializovat různě, třeba s hodnotami atributů stejně dobře v apostrofech jako v uvozovkách), rozlišuje i ASN.1 struk­turovaná data, se kterými pracuje aplikační logika, od proudu bytů posílaného po síti. Konverzi mezi těmito úrovněmi specifikují kódovací pravidla neboli Encoding Rules (která určují samozřejmě kódování i dekódování).

Základní možností jsou BER neboli Basic Encoding Rules, jejichž základním blokem je triplet typu, délky a hodnoty (TLV). Typ (vystupující rovněž pod jménem „tag“) specifikuje, jak interpretovat zbytek tripletu, délka určuje, kde triplet končí, a hodnota může být buď primitivní (řekněme číslo), nebo složená, což je opět TLV.

Kromě čísel (celých i s desetinnou čárkou) patří mezi standardně podporované typy také řetězce znaků. Tady mi ASN.1 připoměl C++ – problém není, že by ASN.1 neměl typ řetězce, ale že jich má velmi mnoho. Pěkně to ilustruje třeba RFC 2459 (z ledna 1999): „Typ DirectoryString je jeden z PrintableString, TeletexString, BMPString, UTF8String a UniversalString … Všechny certifikáty vydané po 31. prosinci 2003 MUSÍ používat UTF8String (kromě níže uvedených výjimek).“ V telekomunikačních aplikacích řetězce zjevně nikdo moc nepěstoval, tak vyrostly dost divoce…

Hojně používaným a dobře integrovaným typem je univerzální jméno (v kontextu Internetu a XML známé jako URN, URI či URL) neboli OID. „Identifikátor objektu“ je jednoduše řada čísel. OID jsou uspořádána do stromu a každý, kdo má u „vyšší“ registrační autority (ASN.1 definuje autority nejvyšší úrovně, což jsou opět nějaké telekomunikační komise) registrované OID, je taky registrační autorita, vlastní celý jeho podstrom a může si v něm zavádět své identifikátory. Potud to funguje jako DNS – rozdíl je ovšem v tom, že délka OID není omezena. Takže například OID 1.2.840.113549­.1.7 identifi­kuje kryptografický standard PKCS #7 od společnosti RSA, která má registrované OID 1.2.840.113549. To poslední číslo je tak velké, protože autorita 1.2.840 registruje OID americkým firmám – kdo si řekne, dostane číslo. V tomto jmenném prostoru je všude místa dost. S orientací v globálním stromu je to horší, ale na vyhledávání máme Internet: veřejně známé identifikátory shromažďuje na svých stránkách Harald Alvestrand.

Délka obecně nemusí být uvedena – v tom případě je hodnota ukončena dvěma nulami, což je vlastně triplet nulového typu a délky. CER (Canonical) a DER (Distinguished) pravidla jsou deriváty BER vybírající všude tam, kde má BER nějaké varianty, jednu „standardní“. Jejich použití tedy zaručuje, že tatáž data mají vždy stejnou kódovanou formu, což potřebují např. kryptografické signatury. Mohutné datové toky kóduje PER (Packed) a existuje i řada dalších kódování, mj. i XER, transformující ASN.1 do XML.

Parsování ASN.1

Z předchozího je zřejmé, že k parsování ASN.1 musíme vědět, jaké naše data používají kódování. Například parsovat „X.509 DER v Base64“ znamená nejdřív konvertovat do binárních dat, z nich postupně číst triplety TLV a interpretovat je podle definice formátu certifikátu. A kde že je ta definice formátu? Je zapsána (v textu nějaké specifikace) v ASN.1. ASN.1 je jazyk pro popis datových struktur – ve stejném smyslu, jako je IDL jazyk pro popis rozhraní.

Namátkou (certifikáty jsou definovány na mnoha místech) třeba v RFC 2315:

The signed-data content type shall have ASN.1 type SignedData:

SignedData ::= SEQUENCE {
  version Version,
  digestAlgorithms DigestAlgorithmIdentifiers,
  contentInfo ContentInfo,
  certificates
    [0] IMPLICIT ExtendedCertificatesAndCertificates
      OPTIONAL,
  crls
    [1] IMPLICIT CertificateRevocationLists OPTIONAL,
  signerInfos SignerInfos } 

Čte se to podobně jako ABNF: nové jméno (standardně jsou psána KonvencíPascalu) je definováno kombinací existujících. Primárním prostředkem kombinace v ASN.1 je SEQUENCE (klíčová slova ASN.1 se píší velkými písmeny). Interpretace je zřejmá: PodepsanáData začínají číslem verze, za ním jsou jména algoritmů (nejspíš nějaká SEQUENCE OF OID) atd. ASN.1 má i další struktury, např. SET; SEQUENCE se ovšem používá zdaleka nejčastěji. Čísla v hranatých závorkách jsou tagy specifikující, kterou větev si má parser vybrat. Používají se, když jsou větve tak složité, že to nelze poznat přímo z parsovaných dat (jako se pozná, kde končí jména algoritmů a začínají „informace o obsahu“). V místech, kde není uvedený explicitní tag, vybírá parser podle typu dat – např.

Answer ::= CHOICE {
  word PrintableString,
  flag BOOLEAN } 

vystačí s implicitními tagy.

cyber23

Proti obecné ABNF má notace ASN.1 podstatnou výhodu: je zkompilovatelná, podobně jako jazyk programů lex a yacc. Strojově čitelný zápis ASN.1 je maličko komplikovanější než ukázky výše – jednotlivé deklarace je třeba shromáždit do modulu a explicitně specifikovat jeho závislost na ostatních modulech – ale když je jasné, jaké bude systém používat datové struktury, je zbytek už celkem mechanická práce. Existuje řada překladačů pro různé programovací jazyky (C, C++, Java) – jak komerčních (nejznámější je asi OSS Nokalva), tak Open Source. Je možné napsat „rukodělný“ parser, ale pro industriální aplikace ASN.1 je lepší použít vhodné nástroje.

Další informace

Patrně definitivní knihou o ASN.1 a primárním zdrojem tohoto článku je ASN.1 – Communication between heterogeneous systems Oliviera Dubuissona. Je v ní mnohem víc, než jsem kdy chtěl vědět o ASN.1, a všechno, co jsem dosud potřeboval.

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

Autor článku