FK~

Moje odkazy

Ostatní odkazy

Close Windows
Nenajdete mě na Facebooku ani Twitteru
Rozpad EU
Jsem členem FSF
There Is No Cloud …just other people's computers.
Sane software manifesto / Manifest příčetného softwaru

Jména a jmenné prostory, URI, RDF, OID, UUID či Tor

vydáno: 4. 8. 2020 16:32, aktualizováno: 15. 10. 2020 17:50

Když se řekne „jmenný prostor“ hodně lidí si představí xmlns v XML nebo balíčky v Javě odvozené od internetových domén. Jmenné prostory jsou ale obecný koncept se kterým se setkáme prakticky všude a odvozovat je můžeme i jinak. Dobře definovaná jména (názvy) jsou pak nutným předpokladem prakticky veškerého uvažování a komunikace.

jmenné prostory, hierarchie

V tomto článku se podíváme na různé příklady jmenných prostorů a souvislosti mezi nimi. Ukážeme si, jak vytvořit jmenný prostor i bez placení a internetové domény – a dokonce i anonymně a bez závislosti na nějaké centrální autoritě. Nahlédneme do zajímavého světa RDF a ukážeme si, jak vytvářet URI, která budou globálně unikátní jednou provždy.

Jmenný prostor je množina jmen. V rámci této množiny jsou jména jedinečná, zatímco napříč jinými množinami už jedinečná být nemusí (a obvykle nejsou). Viz ilustrace výše, kde X ve větvi A označuje jiný objekt než X ve větvi B.

Jmenný prostor může být anonymní a existovat implicitně jako kontext, ale většinou si i jmenný prostor chceme nějak pojmenovat. Pod slovy „jmenný prostor“ se pak často rozumí právě název tohoto prostoru. Ze souvislosti je většinou zřejmé, zda mluvíme o názvu nebo o množině jmen, takže tento dvojsmysl až tak ničemu nevadí, nicméně je dobré o něm vědět.

Jmenné prostory nejsou nějaký „počítačový vynález“ – využití mají v mnoha oborech. Např. v rámci prostoru ISO 4217 jsou třípísmenné kódy měn (CZK, USD, JPY atd.) jednoznačným identifikátorem. Pokud tedy známe kontext a víme, že mluvíme o měnách, jsou daná tři písmena dostačující. Pokud bychom kontext neznali, mohla by ta ta samá tři písmena znamenat mnoho různých věcí. Třeba taková písmena „BND“ mohou znamenat brunejský dolar, ale i německou tajnou službu. A takový „CAD“ může být kanadský dolar nebo třeba computer-aided design či letiště v Michiganu. Až připojením kontextu před lokální název tedy získáme globálně unikátní identifikátor.

Oblíbeným bonmotem v oboru softwarového inženýrství je výrok:

We can solve any problem by introducing an extra level of indirection.

který se honosně nazývá Fundamental theorem of software engineering. Po přečtení tohoto článku bude zřejmé, proč…

Srovnání různých možností a schémat

Jmenné prostory a globálně unikátní názvy lze implementovat různými způsoby. V následujících podkapitolách se podíváme na některé z nich.

Internetové domény, DNS

Začneme s nejrozšířenějším systémem, o kterém slyšel prakticky každý – tím jsou internetové domény a systém pro jejich překlad DNS.

  • vydávající autorita: Technologie (TCP/IP, BGP, RIP, OSPF, DNS…), na kterých stojí Internet, jsou plně otevřené a svobodné. Nic nám nebrání si postavit vlastní obdobu Internetu, definovat si vlastní domény prvního řádu (TLD), provozovat si vlastní kořenové servery a nebýt na nikom závislý ani žádat nikoho o svolení. Tímto způsobem můžeme vytvořit vlastní internet, pomocí kterého se propojíme se svými kamarády nebo sousedy. Někdy se proto rozlišuje velikostí písmen „Internet“ (ta jedna konkrétní a všem známá globální síť) a „internet“ (obecně nějaká síť propojující jiné sítě). Pokud chceme komunikovat se zbytkem světa a připojit se k tomu, co ostatní považují za Internet, nezbude nám než respektovat (nebo alespoň strpět) některé autority a jejich pravidla. Na kořenovou DNS zónu dohlíží ICANN (Internet Corporation for Assigned Names and Numbers) a IANA (Internet Assigned Numbers Authority). Jednotlivé TLD spravují různé další organizace – např. pro .cz doménu je to CZ.NIC. Ani s nimi ale koncový uživatel nepřijde přímo do styku (byť se na něj jejich pravidla vztahují) a doménu získá u tzv. registrátora (těch je hodně a jsou to typicky komerční firmy často poskytující i jiné služby jako hosting, SSL certifikáty atd.). Kromě toho existují i alternativní kořenové DNS zóny a různé neoficiální TLD domény, ale u nich je problém, že je málokdo uznává a mohlo by dojít ke kolizi jmen.
  • cena: Vytvoření nové domény prvního řádu (TLD jako je např. com nebo org) a hlavně její uznání organizací ICANN by nás vyšlo v přepočtu na více než čtyři miliony korun. Valné většině z nás stačí si zaregistrovat doménu druhého řádu (např. example.com nebo frantovo.cz). Standardní cena takové domény je 250 až 300 Kč včetně DPH za rok. Některé nové generické domény lze „v akci“ pořídit cca za 100 Kč, ale je třeba počítat s tím, že se poplatky v dalších letech mohou zvýšit. Těch 250 až 300 Kč je cena, za kterou správce domény může v pohodě a dlouhodobě dělat svoji práci (a např. takový CZ.NIC z toho zvládne financovat i vývoj různého svobodného softwaru a jinou užitečnou činnost). Některé národní nebo generické domény mají výrazně vyšší poplatky, stojí třeba kolem 1000 Kč ročně nebo i více. Částka se dělí mezi registrátora a správce dané TLD (a stát, kterému z toho bohužel odvádíme daň). Domény třetího řádu (např. franta.example.com) bývají zpravidla zdarma – stačí se domluvit s vlastníkem příslušné domény druhého řádu. Pokud nám ale na takové doméně záleží, je vhodné tuto dohodu pojistit písemnou smlouvou, protože se stáváme závislí na vlastníkovi této domény (a na tom, že za ni bude platit poplatky a bude udržovat DNS záznamy tak, jak jsme se dohodli).
  • počet jmen: téměř nekonečno; Název domény je hierarchický, délka jedné části (anglicky label) může být až 63 znaků a celková délka by měla být do 253 znaků. Takže pod každou TLD může být přibližně 626 193 587 911 053 245 820 119 936 702 692 663 462 002 903 414 006 624 911 824 043 838 652 844 590 927 708 241 206 630 292 652 032 tzn. nějakých 6,26×1098 domén druhého řádu. Nemusíme se tedy bát, že by nám jména v tomto systému došla. Hodně krátké (do 4 znaků) nebo nějak zajímavé názvy bývají sice obsazené, ale pokud jen hledáme stabilní identifikátor, nemusí nás to trápit – vybereme si nějakou dostupnou delší doménu.
  • formát: textový řetězec; Jednotlivé části se zapisují oddělené tečkou. Např. posta.praha.example.com. Pokud se používá IDN, je to trochu komplikovanější, protože máme surový tvar např. xn--hkyrky-ptac70bc.cz a k němu tvar s diakritikou háčkyčárky.cz. Ale IDN používat nemusíme – klidně se můžeme držet malých písmen z ASCII a číslic, případně pomlčky.
  • významovost: zpravidla významový identifikátor; Slova, ze kterých se doménové jméno skládá obvykle něco znamenají, odkazují na název vlastníka nebo účel daného serveru či obecně poddomény. Ale nic nám nebrání si vytvořit bezvýznamový identifikátor – např. náhodnou posloupnost znaků nebo číselnou sekvenci. Domény vyšších řádů se někdy dokonce odvozují od IP adres nebo přidělují sekvenčně. Případně se na ně automaticky mapují identifikátory nebo číselníky nějakého jiného systému.
  • využití: Primárně slouží k tomu, abychom si nemuseli pamatovat IP adresy serverů, na které se chceme připojit (např. si z nich stáhnout stránku protokolem HTTP). Pomocí DNS si přeložíme lidsky zapamatovatelné doménové jméno (blog.frantovo.cz) na IP adresu (149.62.147.199 nebo 2a01:430:2e::199). IP adresy odpovídají fyzickému umístění v síti, protože bývají obvykle vázány na poskytovatele připojení, zatímco doménová jména představují logickou strukturu, která je nezávislá na tom, kde se který stroj nachází. Kromě toho lze ale systém DNS používat i jako distribuovanou databázi a šířit přes něj takřka libovolná data (např. DKIM klíče poštovního serveru, jiné otisky klíčů, čísla portů určitých služeb, dokonce lze přes DNS i tunelovat síťový provoz jako přes VPN… dále pomocí DNS záznamů můžeme deklarovat, komu daná doména patří a propojit ji s nějakým jiným identifikátorem atd.). Kromě toho se ale doménová jména často využívají právě pro odvozování jmenných prostorů – jsou totiž globálně unikátní, hierarchická a zároveň je tento systém velmi rozšířený a dostupný. Pokud patříme k těm, kdo mají potřebu vytvářet nějaký jmenný prostor, pravděpodobně už nějakou internetovou doménu vlastníme – takže dost možná odvodíme svůj jmenný prostor právě od ní. To se běžně používá např. v Javě pro názvy balíčků a následně pak i v OSGi – na prvním místě je doména prvního řádu – např. cz.frantovo.program123.modul456. V Mavenu se podobným způsobem odvozují groupId, pod kterými jsou pak jednotlivé artefakty identifikované pomocí lokálního názvu: artifactId (artefaktem zde myslíme modul/balíček). Také na sběrnici D-Bus se názvy služeb a rozhraní odvozují od doménových jmen. Doménová jména se samozřejmě používají v URL a také v URI, URN či IRI, o kterých bude řeč později.

Dříve se zajímavé IP adresy šířily vytištěné na papíře. Dnes máme DNS.

Vyhledávat v DNS můžeme jednoduše pomocí příkazu host, např. host blog.frantovo.cz. Poznámka: tečka není součástí příkladu, ale pokud ji tam necháme, nic se nestane. Tečka značí absolutní cestu resp. FQDN. Pokud bychom měli v /etc/resolv.conf nastaveno domain frantovo.cz (výchozí doménu, kde se má hledat), tak by nám host blog našlo totéž, jako host blog.frantovo.czhost blog.frantovo.cz. – ale host blog. by nenašlo nic.

Object identifier (OID) a Private Enterprise Number (PEN)

Někoho to možná překvapí, ale internet a jeho doménová jména nejsou středem vesmíru – ani toho počítačového. Na mnoha místech se používá spíše OID, což je hierarchický systém pro pojmenovávání objektů. Standardizovala ho společně Mezinárodní telekomunikační unie (ITU) a ISO/IEC. Setkáme se s ním často v oboru telekomunikací, ale i v počítačové bezpečnosti nebo ve zdravotnictví. Dá se říct, že tento systém využíváme všichni, akorát o tom většina lidí neví.

OID jsou tvořené posloupností čísel, která se zapisují oddělená tečkou, např. 1.3.6.1.4.1.41821. Začínají jedním ze tří čísel: 0 (ITU-T), 1 (ISO), 2 (joint-iso-itu-t), což je něco jako TLD u DNS (OID se tedy zapisují v opačném směru – nejvyšší úroveň je zde vlevo a směrem doprava jdeme v hierarchii hlouběji, podobně jako u adresářové struktury).

Části tohoto stromu lze delegovat na jiné organizace, takže např. o 1.3.6.1.4.1 se stará IANA. Další podstromy hlouběji v hierarchii pak patří různým firmám a organizacím, které v nich definují svoje identifikátory (opět hierarchicky, nemusí to být jen plochý seznam).

Smyslem OID je mít globálně unikátní názvy, které lze zapisovat velmi úsporně (v binární formě). Slouží primárně k identifikaci, nikoli lokalizaci (na rozdíl od DNS, kde si doménové jméno přeložíme na IP adresu, na kterou se pak můžeme připojit). OID se doporučuje přidělovat dlouhodobě existujícím objektům. Jednou přiřazené OID by se nemělo recyklovat a používat k jinému účelu. Nebudeme jimi tedy typicky označovat příchozí zprávy nebo požadavky, ale přidělíme je atributům či hodnotám číselníků. Díky globální unikátnosti pak můžeme v jedné zprávě (formátu, protokolu…) kombinovat různé atributy, struktury a hodnoty, které vznikly nezávisle na sobě, na různých místech (mohl je definovat kdokoli) a nedojde k záměně. Jde o stejný princip jako u jmenných prostorů v XML. Za určitých okolností by mohlo dávat smysl přidělovat OID i zprávám či požadavkům – pokud bychom s nimi chtěli pracovat dlouhodobě, vracet se k nim a mít možnost je adresovat. Můžeme mít např. distribuovaný systém, ve kterém na jednotlivé uzly (servery, instance) delegujeme části našeho podstromu – a tyto části pak budou požadavkům či zprávám přidělovat OID ve svém jmenném prostoru. To by se tedy netýkalo požadavků v technickém slova smyslu (např. HTTP) nebo zpráv, ale obchodních požadavků v nějaké distribuované podatelně, které budeme chtít navěky archivovat a mít možnost na ně odkazovat. Může to být efektivnější (úspornější) alternativa k UUID nebo URI.

  • vydávající autorita: PEN vydává IANA (Internet Assigned Numbers Authority). O standard OID jako celek se stará ITU a ISO/IEC. Každý, kdo má OID, je zároveň autoritou, která může přidělovat ID ve svém podstromu a delegovat jeho části na někoho dalšího.
  • cena: zdarma; Kdokoli může požádat a číslo (PEN) dostane. Tím získá svoji část OID stromu v 1.3.6.1.4.1.… Jiné části stromu mohou být přidělovány z úplatu nebo spojeny s členstvím v nějaké organizaci (ISO, ANSI, BSI atd.).
  • počet jmen: nekonečno
  • formát: posloupnost celých čísel; V lidsky čitelné podobě se jednotlivé části zapisují oddělené tečkou. Jinak většinou binárně, jako posloupnost VLQ čísel. V případě PEN se někdy předpokládá, že se vejde do 4 bajtů – ale zatím se mi nepodařilo najít autoritativní zdroj, který by garantoval, že nikdy nevznikne PEN vyšší nebo rovno 24×8.
  • významovost: bezvýznamový identifikátor
  • využití: OID se používají hlavně v ASN.1 a formátech a protokolech na něm postavených. Obsah tohoto blogu – stejně jako většina webu – je dostupný pomocí protokolu HTTPS a v něm (resp. obecně v SSL/TLS, kterým je zabezpečený třeba i e-mail: IMAP4, POP3) se používají X.509 certifikáty, ve kterých jsou jednotlivé atributy nebo hodnoty číselníků identifikovány pomocí OID (např. commonName je 2.5.4.3). Kromě X.509 se OID používají i v souvisejících S/MIMEPKCS standardech. Pokud se v nějaké firmě nebo třeba ve škole přihlašujeme jménem a heslem, tyto údaje se obvykle ověřují vůči LDAP serveru (např. OpenLDAP). Případně vůči SAML IdP (který je typicky napojený zase na LDAP). Protokol LDAP používá OID k identifikaci atributů – a to jak těch standardních (např. jméno, příjmení, heslo), tak uživatelsky definovaných (protokol lze rozšiřovat a přidávat si do něj vlastní atributy a struktury). Hardwarové komponenty (např. směrovače či tiskárny) nebo software (např. aplikační server či operační systém) zase hlásí svůj stav pomocí protokolu SNMP nebo přes něj mohou přijímat příkazy. A i tento protokol staví na OID. Když připojíme počítač k síti s dynamicky přidělovanými adresami (což je obvyklé), dostaneme IPv4 adresu od DHCP serveru. A v něm se používají PEN pro tzv. Vendor-Specific Suboption. Na ASN.1 a OID se hodně staví v mobilních telekomunikacích (3GPP, UMTS, LTE…). Na OID narazíme i v oboru zdravotnictví (HL7, DICOM). A v neposlední řadě můžeme OID použít i ve formě URI/URN všude tam, kde je URI přijímáno jako globálně unikátní identifikátor (např. jmenné prostory v XML).

Např. moje PEN je 41821, celé OID potom: 1.3.6.1.4.1.41821
a z něj odvozené URN a URI: urn:oid:1.3.6.1.4.1.41821.

Obsah šifrovacích certifikátů ve formátu DER resp. obecně jakákoli ASN.1 data v tomto formátu můžeme zkoumat pomocí nástroje dumpasn1 na příkazové řádce nebo v GUI pomocí Wiresharku. V obou případech uvidíme OID jednotlivých atributů a hodnot:

certifikát v DER kódování (ASN.1) otevřený ve Wiresharku; jsou zde vidět OID

Seznam PEN najdeme na stránkách IANA: enterprise numbers (pozor, přes 4 MB velký textový soubor). K procházení stromu OID a vyhledávání v něm slouží různé neoficiální registry, např. oid-info.com. Směrodatné informace poskytne vždy vlastník příslušného uzlu v OID stromu – např. ve formě LDAP schématu či MIB souboru pro SNMP.

MAC adresy a Organizationally unique identifier (OUI)

Každá síťová karta (rozhraní) má tzv. MAC adresu (media access control address). Tato adresa by měla být globálně unikátní, protože nikdy nevíme, jaké dvě karty se potkají na jedné síti. Jenže jak to zařídit, když tyto karty vyrábí mnoho nezávislých výrobců v mnoha továrnách? Řešení spočívá v tom, že jednotliví výrobci mají přidělené tzv. OUI, které pak tvoří první tři bajty MAC adresy.

Máme tu tedy jmenný prostor čísel výrobců (OUI). A pod každým z nich se nachází jmenný prostor čísel karet vyrobených daným výrobcem.

  • vydávající autorita: IEEE (Institute of Electrical and Electronics Engineers)
  • cena: IEEE prodává bloky MAC adres, největší MA-L (odpovídá jednomu OUI tzn. více než 16 milionům adres) stojí v přepočtu jednorázově cca 66 000 Kč. Za 4 500 Kč si lze přikoupit potvrzení na orazítkovaném papíře. Nebo si připlatit 76 000 Kč, ovšem ročně, za důvěrnost (název naší společnosti a adresa se pak neobjeví na veřejném seznamu). Menší rozsah MA-M pořídíme za 40 000 Kč a získáme tak nárok na přibližně jeden milion (20 bitů) MAC adres (EUI-48). Nejmenší rozsah MA-S pořídíme za cca 16 600 Kč, což nám dá 4 096 adres (12 bitů). Pokud nám stačí jednotky adres na nějaké experimenty, vyjde nejlevněji koupit bazarovou kartu (třeba za 50 Kč), tu sešrotovat nebo uložit do trezoru a její MAC adresu zrecyklovat. Není to úplně OK, protože používáme OUI někoho jiného, ale globální unikátnost tím nebude narušena – na žádné síti bychom tedy neměli potkat kartu se stejnou MAC adresou. Případně se můžeme s někým domluvit, aby nám přidělil adresy ze svého rozsahu.
  • počet jmen: OUI je tvořeno třemi bajty, tzn. 23×8 = 16 777 216. Teoreticky v tomto systému může být až 16 milionů výrobců (to by mělo bohatě stačit). A každý z nich může vyrobit až 16 milionů karet (to často nestačí a výrobce si pak musí koupit další OUI resp. blok MAC adres). To jsou EUI-48 (dříve MAC-48). Kromě toho existují i 64bitové EUI-64 adresy.
  • formát: MAC adresa je pole šesti bajtů, z nichž první tři jsou OUI. V lidsky čitelné formě se toto pole většinou zapisuje hexadeximálně oddělené dvojtečkami, např. 52:54:9b:ab:5e:b9. Někdy se jako oddělovač bajtů používají pomlčky a někdy tečky, kterými se pak oddělují dvojice bajtů. V síťových protokolech MAC adresy putují samozřejmě v binárním tvaru.
  • významovost: bezvýznamový identifikátor; Z prvních tří bajtů MAC adresy lze obvykle vyčíst výrobce.
  • využití: primárně Ethernet (drátové sítě), Wi-Fi a Bluetooth (bezdrátové sítě); Kromě toho se MAC adresa někdy používá pro odvození unikátního identifikátoru počítače – např. se zahashuje nebo zkombinují ještě s dalšími čísly. MAC adresy také vstupují do výpočtu některých UUID (dá se říct, že tam MAC adresa slouží jako jmenný prostor).

MAC adresa je tedy něco jako sériové číslo síťové karty a systém OUI zajišťuje, aby tato čísla byla unikátní napříč výrobci. Adresy můžeme vyhledávat na stránkách IEEE nebo třeba na hwaddress.com.

Stinnou stránkou globální unikátnosti MAC adres je to, že přes ně lze sledovat pohyb lidí resp. jejich zařízení (mobilních telefonů, notebooků atd.), což představuje zásah do soukromí.

PCI Vendor ID

Přídavné karty (grafické, zvukové, síťové, telefonní atd.), které si dáváme do počítače, je potřeba nějak identifikovat, aby operační systém věděl, jak má s danou kartou komunikovat a jaký ovladač pro ni načíst. Podobně jako u MAC adres tu máme dvouúrovňový systém, ve kterém nejprve nějaká centrální autorita přiřazuje ID výrobcům a ti si pak následně už definují ID pro jednotlivá svoje zařízení dle svého uvážení (a decentralizovaně). Na rozdíl od MAC adres, zde ale není cílem identifikovat jednotlivé vyrobené kusy, nýbrž produkty.

  • vydávající autorita: PCI-SIG (Peripheral Component Interconnect Special Interest Group)
  • cena: Členství v této organizaci stojí v přepočtu cca 90 000 Kč ročně.
  • počet jmen: ID výrobce má dva bajty, tzn. výrobců může být až 65 536. ID zařízení jsou taky dva bajty. Na rozdíl od MAC adres, ale nemá každý kus unikátní ID, takže i 65 536 ID na jednoho výrobce by mělo bohatě stačit.
  • formát: dvojice bajtů resp. 16 bitů; Zapisují se hexadeximálně s dvojtečkou oddělující ID výrobce a ID zařízení, např. 1002:aa90.
  • významovost: bezvýznamový identifikátor
  • využití: identifikace PCI, PCI-X a PCI Express (PCIe) karet a jejich výrobců

Seznam výrobců karet najdeme na stránkách PCI-SIG. Jednotliví výrobci pak přidělují ID svým zařízením. Na adrese pci-ids.ucw.cz najdeme jejich neoficiální databázi. Měli bychom ji mít i ve svém počítači v souboru: /usr/share/misc/pci.ids – ten bývá součástí balíčku pciutils stejně jako nástroj lspci.

USB Vendor ID

Pro externí zařízení se dnes používá převážně sběrnice USB. A zde je potřeba řešit stejný problém jako u PCI tzn. identifikovat zařízení resp. produkty. A stejně jako u PCI se i zde používá dvouúrovňový systém číselných identifikátorů: VID (Vendor ID) a PID (Product ID). Ovšem v obou případech se jedná o jiné VID – pokud tedy bude jedna firma vyrábět PCI i USB zařízení, tak bude mít dvě různá VID.

  • vydávající autorita: USB-IF (USB Implementers Forum)
  • cena: Členství v USB-IF stojí v přepočtu cca 111 000 Kč ročně. Bez členství si lze pořídit USB VID za 133 000 Kč. Za právo používat logo USB se potom platí cca 78 000 Kč jednou za dva roky. Pro menší výrobce nebo nějaké experimenty je to tedy dost drahé. Možným řešením v takovém případě je získat jen PID v rámci VID někoho jiného. Tuto možnost nabízejí někteří výrobci čipů (FTDI, Mircochip, ST, TI atd.). Poptáme se tedy u svého dodavatele. Nebo se také můžeme domluvit s nějakou organizací (např. Openmoko) a dostat PID od nich.
  • počet jmen: jak VID, tak PID jsou 16bitová čísla (dva bajty), takže v tomto systému může být až 65 536 výrobců a každý může mít až 65 536 různých produktů (a od každého může vyrobit libovolné množství kusů).
  • formát: dvojice bajtů resp. 16 bitů; VID a PID se zapisují hexadecimálně s dvojtečkou oddělující ID výrobce a ID zařízení, např. 1d6b:0003.
  • významovost: bezvýznamový identifikátor
  • využití: USB zařízení

Kromě toho mají USB zařízení i sériová čísla, pomocí kterých lze rozlišit více zařízení stejného typu. Hodí se to např. když k počítači připojíme několik sériových adaptérů nebo několik stejných jednočipů. Lepší čipy dovolují nastavit si vlastní VID, PID a sériové číslo. Ty levné v sobě mají tato čísla natvrdo vypálená. A v nejhorším případě je sériové číslo všech kusů nula nebo jiné stejné číslo, takže od sebe jednotlivá zařízení nepoznáme.

Oficiální seznam členů najdeme na stránkách USB-IF. Neoficiální seznam výrobců a zařízení na: linux-usb.org a měli bychom ho mít i na svém počítači v /usr/share/misc/usb.ids.

MIDI Manufacturer SysEx ID

MIDI (musical instrument digital interface) je standardní protokol pro propojování hudebních zařízení (klávesy, syntezátory, ovladače, softwarové moduly atd.). Většina komunikace probíhá dle standardu a je nezávislá na výrobci, můžeme tak připojit klávesy od Yamahy k syntezátoru od Rolandu atd. Některá zařízení ale umí přijímat či vysílat zprávy, které jsou specifické pro dané zařízení nebo výrobce. Může jít např. o zobrazení zprávy nebo obrázku na displeji zařízení či o nahrání nějakých dat. Těmto zprávám se říká SysEx (system exclusive) a MIDI protokol je díky nim rozšiřitelný a velice univerzální.

Aby se tyto zprávy nemíchaly mezi standardní MIDI zprávy a aby nedošlo k chybné interpretaci při záměně s podobně vypadající zprávou pro jiné zařízení, musí být nějak označeny. Protože je MIDI binární protokol optimalizovaný pro práci v reálném čase, musí být i označení těchto zpráv dostatečně úsporné. Používají se proto číselné identifikátory přidělené jednotlivým výrobcům, tzv. Manufacturer SysEx ID. Firma Roland má přiděleno 41H, Korg 42H, Yamaha, 43H, Casio 44H, Moog 04H atd. Identifikátory můžou být i delší, např. Gravis00H 00H 02H. V MIDI se používají celá čísla s proměnlivou délkou (VLQ).

  • vydávající autorita: The MIDI Manufacturers Association (MMA)
  • cena: Manufacturer SysEx ID se přidělují pouze členům asociace, nejlevnější členství stojí v přepočtu cca 5 400 Kč ročně nebo 13 500 Kč s hlasovacím právem. Nejdražší členství (pro výrobce s nejvyšším obratem) stojí 450 000 Kč ročně.
  • počet jmen: nekonečno
  • formát: celé číslo
  • významovost: bezvýznamový identifikátor
  • využití: identifikace MIDI SysEx zpráv

Nevím o tom, že by ID nějakého bývalého člena bylo opětovně přiděleno někomu jinému, nicméně tyto identifikátory (a z nich odvozené jmenné prostory) nelze považovat doživotní/nekonečné (na rozdíl od PEN, které jsou bezplatné, a nemohou tudíž nezaplacením propadnout). Člen, který přestal platit, by se měl zdržet užívání daného ID.

Pod ID jednotlivých výrobců vznikají jmenné prostory, ve kterých si už daný výrobce vládne sám – např. si definuje vlastní device IDmodel ID, formát zpráv, kontrolní součty atd. Zprávy pak jsou globálně unikátně identifikovány pomocí MIDI protokolu, Manufacturer SysEx ID a následně třeba model IDcommand ID.

UUID, Hashe, otisky klíče, SSH, Tor, kryptoměny

Všechny dosud zmíněné cesty k dosažení globálně unikátních ID se opírají o nějakou centrální autoritu, která koordinuje rozdělování identifikátorů na té nejvyšší úrovni. Ať už šlo o hierarchický systém, jako DNS nebo OID, kde se postupně delegují podstromy na další subjekty, nebo o dvouúrovňový systém, jako v případě MAC, PCI, USB či MIDI, vždy zde byl nějaký jeden subjekt s výhradním postavením, na kterém ostatní záviseli. Tím vzniká úzké hrdlo – většinou nikoli v technickém slova smyslu, ale v tom organizačním a mocenském ano. Nabízí se otázka, zda by to nešlo jinak. A pokud šlo, jak potom zajistit, aby ID byla stále globálně jedinečná?

Odpověď zní ano a trik spočívá v tom, že identifikátory budeme volit náhodně a jmenný prostor bude tak velký, aby se pravděpodobnost kolize blížila nule. Fakt, že pravděpodobnost se jen blíží nule, ale není prokazatelně nulová, je poněkud znepokojující. Nicméně můžeme to udělat tak, aby ta pravděpodobnost byla výrazně nižší než třeba pravděpodobnost, že zahyneme pod koly tramvaje… A pokud jsme ochotní vyjít každý den na ulici navzdory tomu, že nás může přejet tramvaj, tak snad dokážeme žít s tím, že ani pravděpodobnost vzniku duplicitního ID není, striktně vzato, nulová.

Tímto způsobem jsme schopni dosáhnout plné decentralizace a úplné nezávislosti. Má to tedy ještě jednu nevýhodu: můžeme rovnou zapomenout na významové a snadno zapamatovatelné identifikátory. Ale pak už nás čekají jen samá pozitiva.

  • vydávající autorita: nikdo resp. my; Identifikátor si totiž vygenerujeme sami, aniž bychom se museli někoho ptát nebo to někomu oznamovat.
  • cena: zdarma; V některých případech může generování identifikátoru vyžadovat nějaký netriviální výpočetní výkon, který lze přepočítat na spotřebovanou elektrickou energii a amortizaci hardwaru, takže cena nulová nebude. Ale to jsou spíš výjimky – zpravidla bude cena skutečně nulová.
  • počet jmen: velmi mnoho nebo nekonečno
  • formát: pole bajtů typicky zapsané hexadecimálně jako textový řetězec
  • významovost: bezvýznamový identifikátor; Nicméně je možné generovat náhodná ID tak dlouho, dokud nám nevyjde něco, co se nám bude líbit (např. prvních pár znaků bude naše jméno nebo spíš nějaká zkratka). Tento postup je ale výpočetně velice náročný.
  • využití: Distribuované systémy, kde nechceme mít SPoF ani čekat na žádné zámky (autoritu, která přiděluje identifikátory). Zejména pak systémy, kde dynamicky přibývají a ubývají uzly. Nebo dokonce různé organické systémy, kde nikdo nikomu nevěří a každý hraje sám za sebe. Běžné je také použití tam, kde se předpokládá slučování dat vzniklých nezávisle na sobě.

Nejjednodušším běžným příkladem tohoto přístupu je UUID (Universally unique identifier). Jde o 128bitové číslo (16 bajtů) se standardizovaným postupem výpočtu a standardizovaným formátem zápisu. UUID vypadá např. takto: c59a49e9-19cb-4724-b84f-86dc402ca5cd a vygenerujeme ho pomocí příkazu uuidgen nebo příslušné funkce ve svém programovacím jazyce. Délka 128 bitů znamená, že může vzniknout až 216×8 tzn. 340 282 366 920 938 463 463 374 607 431 768 211 456 unikátních ID, což je přibližně 3,4×1038. Není to úplně moc, k nekonečnu to má daleko, ale je to dost na to, abychom takovému systému věřili tam, kde nepředpokládáme zlý úmysl (útok). Pravděpodobnost, že by někomu uuidgen vrátil stejné UUID jako nám, je pro většinu případů užití přijatelně nízká.

Pomocí UUID se např. označují diskové oddíly. Formátování disků je proces, který probíhá nekoordinovaně na mnoha místech a často offline. Zde opravdu nechceme záviset na nějaké centrální autoritě, která by přidělovala identifikátory. Nevyhovuje ani hierarchický systém typu DNS či OID, protože možnost formátovat disk má mít kdokoli, ne jen vlastník internetové domény nebo OID. Navíc není vždy žádoucí, aby informace o tom, kdo disk naformátoval, prosakovala ven a putovala všude s daným diskem. Přesto chceme mít možnost disky resp. diskové oddíly jednoznačně identifikovat. A to i v případě, že disky budeme přenášet mezi počítači (což je celkem běžné i u HDD a SSD, natož u externích USB flash disků). Díky UUID vždy spolehlivě víme, do jakého adresáře se má který oddíl připojit, přestože jsme skupinu flash disků zastrkali do USB portů zcela náhodně a u HDD změnili nastavení master/slave nebo je připojili k jinému SATA portu či jinému SCSI řadiči.

UUID lze použít i třeba pro označování kapitol nebo částí dokumentu. I když pak dokument přeorganizujeme, přejmenujeme kapitoly, sloučíme několik dokumentů dohromady atd., tak ID jednotlivých částí zůstanou nezměněné. Hodí se i pro označení celých dokumentů či požadavků, které vznikají na více místech, a pak různě obíhají, upravují se a procházejí různými systémy. Sice by se nabízelo použít hash první verze, ale to nemusí být dostatečné – pokud dokumenty (či jiné objekty) vznikají ze šablony nebo dle nějakého předepsaného postupu, je velká pravděpodobnost, že první verze budou stejné a lišit se začnou až později. Proto UUID dává mnohem větší šanci na jedinečnost identifikátoru. UUID se někdy používá i v databázích místo sekvenčních číselných ID – a to zejména v případech, kdy čekáme, že budeme slučovat záznamy z více databází.

Námi vygenerované UUID také můžeme prohlásit za název jmenného prostoru a následně v něm začít vytvářet názvy atributů nebo něčeho jiného:

c59a49e9-19cb-4724-b84f-86dc402ca5cd/color
c59a49e9-19cb-4724-b84f-86dc402ca5cd/size
c59a49e9-19cb-4724-b84f-86dc402ca5cd/weight

Takový složený identifikátor je pak čitelný a nese nějakou užitečnou informaci. A zároveň můžeme celkem věřit tomu, že bude globálně unikátní. Navíc jsme k vytvoření takového identifikátoru nepotřebovali vlastnit internetovou doménu ani nic podobného. (v následující kapitole si ukážeme, jak těmto identifikátorům dát standardnější formu)

UUID je naopak obecně nevhodné používat jako bezpečností token, pro řízení přístupu, nebo kdekoli, kde by někdo mohl mít zájem na dosažení kolize. RFC 4122 od tohoto užití výslovně odrazuje:

Do not assume that UUIDs are hard to guess; they should not be used as security capabilities (identifiers whose mere possession grants access), for example. A predictable random number source will exacerbate the situation.

Pokud nám jde o bezpečnost, měli bychom volit dostatečnou délku tokenu, používat kvalitní generátor náhodných čísel a tokeny generovat čistě náhodné tzn. nemělo by do nich vstupovat nic dalšího (adresy, čas, jiné identifikátory atd.), co se dá uhodnout a co pouze snižuje entropii.

Existuje několik metod generování UUID a tyto metody se označují jako verze. Informace o verzi je obsažena v UUID, takže tyto identifikátory lze rozkódovat a vytáhnout z nich některé informace. Nejde tedy o prostou náhodnou posloupnost bajtů v hexadeximálním kódování.

Vložení verze dovnitř UUID znamená, že nemámé k dispozici všech 128 bitů (verze se nachází za druhou pomlčkou a není to jediný faktor, který snižuje entropii, viz popis jednotlivých verzí níže a RFC). Také ne každá posloupnost 128 bajtů a ne každý textový řetězec, který vypadá jako UUID, jsou platným UUID.

UUID Verze 1 vychází z MAC adresy hlavní síťové karty počítače, na kterém se generuje, a z aktuálního času, který se měří s přesností na 100 nanosekund. Vzhledem k tomu, že MAC adresa by měla být unikátní a čas běží stále vpřed, měla by i tato UUID být zcela unikátní. Vygenerovat jich můžeme až 10 000 000 za vteřinu, což by většinou mělo bohatě stačit. Výhoda je, že nezáleží na kvalitě generátoru náhodných čísel (ve skutečnosti nepotřebujeme žádný zdroj entropie), takže můžeme UUID přidělovat třeba i na nějakém malém zařízení např. jednočipu, nebo třeba v nějakém simulátoru či emulátoru, kde by dostatek entropie mohl být problém. Musíme si ohlídat dvě věci: MAC adresa musí být skutečně unikátní (pozor při kopírování virtuálních strojů) a čas nesmíme nikdy posouvat dozadu (pozn. střídání letního a zimního času je sice bolševismus a přežitek, ale v tomto případě nás neohrožuje, protože zde se naštěstí pracuje s UTC časem). K přetečení pole pro čas dojde v roce 3 400, takže to nás moc trápit nemusí. Reálnou nevýhodou ale je, že z UUID lze vyčíst MAC adresu, což je zásah do soukromí, a čas generování, což zase umožňuje hádat UUID. Zároveň jde o postranní kanál, kterým mohou unikat informace – např. když budeme uživatelům přidělovat takováto UUID a ta se budou někde vypisovat, půjde z nich poznat, kdy se který uživatel u nás registroval (z čehož vyplývá, že v tu dobu, zřejmě seděl u počítače…). Také to může odhalit (neoprávněnou) manipulaci s daty – pokud se např. někdo pokusí antedatovat vznik nějakého dokumentu, ale zachová v něm UUID tohoto typu, bude zřejmé, že s vysokou pravděpodobností k nějaké manipulaci došlo.

# Vygenerujeme si UUID Verze 1
$ uuidgen -t
# 9afa9eac-d645-11ea-b678-525417002fb8

# Dekódujeme zpět:
$ uuid -d 9afa9eac-d645-11ea-b678-525417002fb8
# encode: STR:     9afa9eac-d645-11ea-b678-525417002fb8
#         SIV:     206002403879785373344949886906127101880
# decode: variant: DCE 1.1, ISO/IEC 11578:1996
#         version: 1 (time and node based)
#         content: time:  2020-08-04 11:28:22.942481.2 UTC
#                  clock: 13944 (usually random)
#                  node:  52:54:17:00:2f:b8 (local unicast)

Pokud by někdo tento typ UUID použil jako bezpečnostní token, z jediného UUID by útočník zjistil MAC adresu, a pak už by velice snadno trefoval další tokeny. Tato UUID rozhodně nejsou náhodná.

UUID Verze 2 je tzv. „DCE security version“, v RFC ani není specifikovaná a moc se nepoužívá. Stejně jako u verze 1 zde do výpočtu vstupuje MAC adresa a čas.

UUID Verze 3 a 5 obsahují zahashované jméno. Liší se jen použitým algoritmem – verze 3 používá MD-5 a verze 5 používá SHA-1. Oním jménem může být internetová doména, OID, URL nebo X.500 DN (distinguished name známé z LDAPu). Společně se jménem se hashuje i jeho typ (jmenný prostor). Není tu žádný náhodný prvek a tato UUID jsou plně reprodukovatelná – pokud známe jméno a typ, jsme schopní vypočítat to samé UUID. (což může být výhoda i nevýhoda)

$ uuid -d $(uuidgen --md5 --namespace @url --name "https://blog.frantovo.cz/c/386/")
# encode: STR:     7c4ae745-4b2f-367f-9e69-6a70b80bcc68
#         SIV:     165213192171491255116754669783132916840
# decode: variant: DCE 1.1, ISO/IEC 11578:1996
#         version: 3 (name based, MD5)
#         content: 7C:4A:E7:45:4B:2F:06:7F:1E:69:6A:70:B8:0B:CC:68
#                  (not decipherable: MD5 message digest only)

$ uuid -d $(uuidgen --sha1 --namespace @url --name "https://blog.frantovo.cz/c/386/")
# encode: STR:     e2a68063-1b28-5caf-86ce-d6e3c04a4b9d
#         SIV:     301270052326330014982151621672069385117
# decode: variant: DCE 1.1, ISO/IEC 11578:1996
#         version: 5 (name based, SHA-1)
#         content: E2:A6:80:63:1B:28:0C:AF:06:CE:D6:E3:C0:4A:4B:9D
#                  (not decipherable: truncated SHA-1 message digest only)

Hrubou silou pak můžeme i tato UUID „rozkódovat“ resp. uhodnout z nich původní jméno. Pokud známe základ URL, OID, DN nebo DNS, ze kterého bylo UUID generované, prostor je poměrně malý, stačí postupně projít všechny možnosti a hledat shodný hash. Je zde sice riziko kolize, protože dvě různá jména můžou vést na jeden hash, ale pokud víme, že jména např. odpovídají regulárnímu výrazu https://blog.frantovo.cz/c/[0-9]+/, tak je riziko kolize (nalezení nesprávného jména) prakticky nulové.

#!/bin/bash

hledane="e2a68063-1b28-5caf-86ce-d6e3c04a4b9d";

for n in {0..1000}; do
	url="https://blog.frantovo.cz/c/$n/";
	uuid=$(uuidgen --sha1 --namespace @url --name "$url");
	if [[ "$uuid" == "$hledane" ]]; then
		echo "$hledane = $url";
		exit 0;
	fi
done

echo "nenalezeno" >&2;
exit 1;

Reálný kód by byl samozřejmě vícevláknový, ale takto snadné hledání lze provést i pomocí jednoduchého skriptu v Bashi.

UUID Verze 4 jsou náhodná a kromě šesti (případně sedmi) bitů, které padnou na signalizaci verze a varianty, neobsahují žádná předvídatelná data, jako byl čas a MAC adresa v UUIDv1 nebo jméno v UUIDv3 či v5. Za předpokladu, že máme kvalitní generátor náhodných čísel, vytvářejí UUIDv4 prostor 2122 tzn. přibližně 5,3×1036 globálně unikátních identifikátorů, který by měl zajistit, že pravděpodobnost vygenerování duplicitních ID bude dostatečně blízko nule.

Pro vytváření identifikátorů, kde nepředpokládáme zlý úmysl (zájem na kolizi), jsou tato UUID dobrá. Zda je použít i pro zabezpečení, to už je diskutabilní. Např. OWASP doporučuje pro ID relace:

The session ID length must be at least 128 bits (16 bytes).

a dále pak:

The session ID value must provide at least 64 bits of entropy (if a good PRNG is used, this value is estimated to be half the length of the session ID).

Nicméně, i kdybychom délku UUID shledali přijatelnou, tak je poněkud zbytečné se vázat na tento formát. Lepší je se na bezpečnostní token dívat čistě jako na pole bajtů (které typicky naformátujeme jako text v hexadecimálním kódování). Jeho délku pak můžeme měnit dle potřeby a aktuálních bezpečnostních doporučení.

Výhodou UUID je to, že má standardizovaný postup výpočtu a standardizovaný formát. Takže např. databáze, jako PostgreSQL, pro něj mají připravený datový typ a běžné programovací jazyky, jako např. Java, pro něj mají podporu ve standardní knihovně. A když např. zákazníkovi či dodavateli řekneme, ať dokumentům, které nám posílá, přiděluje UUID, bude to většinou jednodušší domluva, než kdybychom mu měli vysvětlovat, jak a kolik bajtů náhodných dat má vygenerovat a jak je potom naformátovat.

Kromě toho mohou mít UUID ještě jedno, poněkud netypické, využití: steganografie. Do každého UUID můžeme uložit až 16 bajtů dat. Ta budou navenek vypadat jako náhodná, ale my budeme vědět svoje… Pokud se omezíme na validní UUID a použijeme verzi 4, tak sice místo 128 bitů uložíme jen 122, ale naše činnost bude pak těžko odhalitelná a naše podvržená UUID budou vypadat jako úplně normální a platná, která mohla vypadnout z legitimního generátoru. Těch 16 bajtů nebo 122 bitů sice vypadá jako málo, ale když si s někým budeme vyměňovat dokumenty, ve kterých je pomocí UUID označeno kde co, tak už těch dat můžeme ukrýt docela dost. To, co je pro jednoho příležitost, je pro druhého hrozba. Takže když jsme my v roli toho, kdo nechce, aby nějaká data unikla, musíme kontrolovat i takové věci, jako jsou UUID. Přes jediné nevinně vypadající UUID by totiž někdo mohl vynést ven např. heslo nebo postupně třeba šifrovací klíč či jiná data. Nicméně stejně tak mohou být data zakódována např. do mezer na koncích řádků či jiných nevýznamných a na první pohled neviditelných bajtů.

UUID se také někdy používají při zveřejňování či poskytování dat, u kterých zároveň chceme zabránit vyzrazení jiných skutečností a souvislostí. Pokud bychom entitám klasicky přidělovali číselná sekvenční ID, tak příjemce dat z těchto ID dokáže vyvodit: kolik entit v systému máme, jak rychle přibývají a která ze dvou entit je starší a která novější. Často to ničemu nevadí, ale někdy jsou situace, kdy tyto informace nechceme s ostatními sdílet. To se řeší buď různou obfuskací těch číselných ID (nezačínáme na 1, přírůstek není 1, předgenerujeme si seznam ID a pak z něj přidělujeme v náhodném pořadí…) nebo právě pomocí UUID. Číselná ID pak zůstanou uvnitř naší databáze jako primární klíč, ale vedle něj přidáme ještě jeden unikátní klíč s náhodnými UUID a přes vnější rozhraní našeho systému pustíme jen tato UUID.

Na stejné obecné principy, na kterých stojí UUID, narazíme i jinde. Např. distribuované verzovací systémy (Mercurial, Git, Monotone, Fossil a další) používají jako identifikátor hash dat. V předchozích generacích verzovacích systémů (SVN, CVS atd.) jsme měli vždy nějakou centrální autoritu (server), která koordinovala práci a přidělovala čísla verzí tzn. mohla to být prostá lineární posloupnost čísel. V distribuovaných systémech toto není možné, protože nové verze vznikají na mnoha různých místech, typicky na počítačích jednotlivých vývojářů, často offline a předem se ani neví, zda se nově vzniklá verze stane či nestane součástí naší historie (pokud nedojde na push či pull, tak bude existovat jen ve svém vlastním izolovaném světě). Hash se pak považuje za dostatečně unikátní název verze. Obvykle se hash nepočítá jen z dat, ale i z metadat jako je hash předchozí verze, na kterou navazujeme. Tím vzniká tzv. Merklův strom (Merkle tree, hashový strom). Tato myšlenka pochází z přelomu 70. a 80. let a dnes na ní stojí mj. kryptoměny (Bitcoin, Ethereum atd.) nebo ty distribuované verzovací systémy či různé protokoly pro decentralizované sdílení dat. Hash určitého uzlu tak není jen jménem daného výsledného stavu, ale představuje jméno celé cesty od kořene až k tomuto stavu. Kdyby téhož výsledku (např. stejného obsahu souborů nebo stejného zůstatku) bylo dosaženo jinou cestou, bylo by jméno jiné (jiný hash). Pokud např. dva programátoři napíší stejný kód, budou to dvě různé verze s různými hashi – dva různé uzly stromu.

Ať už jako jméno používáme hash nebo posloupnost náhodných bajtů, máme problém prokázat, že jsme to právě my, kdo toto jméno (potažmo jmenný prostor) vytvořil. Pokud by např. někdo tvrdil, že 0f8ec76c-e5ef-4890-8af9-6caa061e8d18, které jsem právě vygeneroval programem uuidgen, je jeho UUID, nemá nás kdo rozsoudit a nelze rozhodnout, komu dané UUID patří a kdo ho vygeneroval. V případě hashování je situace trochu lepší, protože by šlo ukázat původní data. Nicméně hashovací funkce (z principu) trpí kolizemi a hlavně tu může existovat (často oprávněný) zájem původní data neposkytnout. Takže ani tudy cesta k prokazatelnému vlastnictví jména nevede (byť UUIDv5 odvozené z veřejně známého URL je v tomto smyslu relativně použitelné – ale to už můžeme jako jmenný prostor použít rovnou původní URL).

Řešení přináší asymetrická kryptografie, ve které se používají páry klíčů. Svůj soukromý klíč držíme v tajnosti a používáme ho k podepisování a dešifrování. Zatímco svůj veřejný klíč můžeme poskytnout komukoli a ostatní ho použijí k tomu, aby mohli ověřit naše podpisy nebo aby pro nás mohli zašifrovat data. Veřejný klíč (nebo častěji jeho hash) pak můžeme považovat za globálně unikátní identifikátor. A jako vlastník příslušného soukromého klíče jsme schopní prokázat, že nám tento identifikátor patří – soukromým klíčem podepíšeme nebo dešifrujeme nějaká data.

Celá asymetrická kryptografie stojí na tom, že nikdo není schopen z veřejného klíče vypočítat příslušný soukromý. V průběhu času mohou jednotlivé algoritmy zastarat (např. nás čeká přechod na tzv. post-kvantovou kryptografii), ale princip zůstává stejný. Na tomto předpokladu závisí dnes např. internetové bankovnictví, elektronický obchod, komunikace s úřady a státem uznávané elektronické podpisy, ochrana osobních údajů, zabezpečení komunikace armády a policie atd. Pokud tedy věříme asymetrické kryptografii v tolika důležitých oblastech, můžeme věřit i tomu, že si dva lidé náhodnou nevygenerují stejný pár klíčů se stejným hashem.

Soukromé a veřejné klíče používá řada technologií – SSL/TLS/X.509, S/MIME, SSH, GPG, WireGuard a další VPN, kryptoměny, Tor, I2P a další. Veřejný klíč (nebo jeho hash) z kterékoli této technologie bychom mohli použít jako globálně jedinečný identifikátor. Ukážeme si to na příkladu Toru, který je pro nás z několika důvodů zajímavý.

Tor bývá dostupný jako balíček ve většině distribucí. Např. v Debianu nebo Ubuntu si ho nainstalujeme příkazem:

apt install tor

A do souboru /etc/tor/torrc si přidáme řádky podobné těmto:

HiddenServiceDir /var/lib/tor/blog.frantovo.cz/
HiddenServicePort 443 blog.frantovo.cz:443
HiddenServiceVersion 3

A restartujeme Tor:

service tor restart

Tím dojde k vytvoření tzv. skryté služby a vygenerování soukromého a veřejného klíče – ty najdeme společně s naší novou adresou (odvozenou z veřejného klíče) v adresáři, který jsme nastavili pomocí parametru HiddenServiceDir:

$ ls /var/lib/tor/blog.frantovo.cz/
hostname  hs_ed25519_public_key  hs_ed25519_secret_key

$ cat /var/lib/tor/blog.frantovo.cz/hostname 
yu7j43yjaykpbwiwj2gog2k2behuitjy7f7qgegclh23ysgurllssxid.onion

Tor démon běžící na našem počítači pak funguje jako proxy – přijímá požadavky přicházející na tuto adresu z Tor sítě a přeposílá je pomocí klasického TCP/IP cílovému serveru. Oboje často běží na jednom počítači, ale pokud chceme službu provozovat skutečně anonymně, je potřeba mít dva (virtuální) počítače. Na jednom běží Tor démon, jedno jeho síťové rozhraní vede do internetu a druhé do privátní sítě. Druhý počítač je připojen pouze k této privátní síti, přímé připojení k internetu nemá (takže z něj nemůžou prosakovat žádné informace) a běží na něm nějaká užitečná služba (typicky SSH, HTTP či SMTP server).

Pokud nám šlo jen o vytvoření globálně unikátního identifikátoru, Tor démona můžeme klidně zase vypnout nebo i odinstalovat. Vygenerované klíče a adresu si samozřejmě zazálohujeme. Adresu (obsah souboru hostname) teď můžeme používat pro konstrukci jmenných prostorů, např. balíčků v Javě nebo xmlns v XML. Naše adresa se nachází v doméně .onion a to není oficiální TLD, což je trochu problém, protože teoreticky by se z .onion mohla časem stát běžná doména, ve které si lidé jména kupují a překládají je pomocí DNS (se standardními kořenovými servery) tzn. někdo jiný by si mohl námi vygenerovanou doménu koupit a tím by došlo ke kolizi jmen. Nicméně doména .onion je poměrně široce používána pro Tor a i když není oficiální, dá se říct, že je uznávána. Pro definici jmenných prostorů bychom měli použít nejlépe URI schéma tag:, které obsahuje časovou složku

tag:yu7j43yjaykpbwiwj2gog2k2behuitjy7f7qgegclh23ysgurllssxid.onion,2020:ahoj

Vzhledem k tomu, že k 1. lednu 2020 bylo vygenerování si páru klíčů jediným známým (byť neoficiálním) způsobem získání domény .onion, můžeme se považovat za výhradního a legitimního vlastníka tohoto jmenného prostoru. A můžeme to kdykoli prokázat tím, že pomocí soukromého klíče dešifrujeme či podepíšeme nějaká data nebo jednoduše tím, že spustíme Tor démona a na dané adrese vyvěsíme – třeba pomocí HTTP – zprávu, že tento prostor patří nám.

Tento postup je zajímavý a užitečný z několika důvodů:

  • jména jsou globálně unikátní v čase a prostoru
  • není tu žádná centrální autorita ani SPoF
  • adresu máme pořád stejnou, i když změníme poskytovatele připojení
  • můžeme zůstat v anonymitě
  • nemusíme za jméno platit
  • můžeme prokázat vlastnictví tohoto jména

Nevýhodou je to, že jde o bezvýznamový a poměrně dlouhý identifikátor (ve verzi 2, viz HiddenServiceVersion, byly adresy kratší, ale dnes se doporučuje používat verzi 3). Nicméně i kratší a významové identifikátory a jmenné prostory (běžná URI) většina lidí kopíruje a málokdo je píše zpaměti, takže si z toho nemusíme dělat zase tak těžkou hlavu.

Díky Toru a tag: URI můžeme např. definovat vlastní XML schémata (XSD), webové služby či RDF subjekty, objekty a predikáty, aniž bychom byli na někom závislí a aniž bychom vystoupili z anonymity.

URI, IRI, URN, URL a jejich schémata

Teď to začne být trochu metafyzické… nicméně v praxi jde o běžnou věc, kterou všichni každý den používáme. Zatím jsme si říkali o jednotlivých systémech (internetové domény, OID, UUID atd.). Každý z nich tvoří svůj vlastní svět a má vlastní kořen resp. množinu jmen. Otázka je, jestli existuje ještě něco nad nimi. Co když budeme chtít praktikovat polymorfismus a pracovat s různými druhy identifikátorů jednotným způsobem? Co když textová reprezentace nějakého OID bude náhodou shodná s textovou reprezentací nějakého DNS jména? Zrovna tohle sice nenastane, ale obecně by k takové kolizi jmen dojít mohlo. Řešením je přidat ke jménům nějakou předponu, která bude signalizovat, z jakého systému dané jméno pochází. Mohli bychom si sice vytvořit vlastní číselník takových předpon… ale běžně uznávanou implementací jsou URI schémata definovaná organizací IANA, takže bude lepší se držet jich. Schémata jsou vlastně takový jmenný prostor jmenných prostorů, ve kterých vznikají jmenné prostory.

  • vydávající autorita: jednotlivé identifikátory si vytváříme sami, aniž bychom museli někoho žádat o svolení nebo je někde hlásit; Seznam schémat spravuje IANA.
  • cena: zdarma; Zpoplatněno může být získání jiného identifikátoru, ze kterého je URI odvozeno – např. internetová doména – ale samotné URI je zdarma, vytvoříme si ho sami a dokonce můžeme vytvářet URI, která jsou odvozena z bezplatných identifikátorů (např. PEN/OID nebo UUID)
  • počet jmen: nekonečno; Např. HTTP doporučuje, aby klienti a servery podporovali URL dlouhá až 8 000 bajtů. Praxe je taková, že řada programů má problém s URL delšími než 2 000 bajtů. Nicméně i to dává obrovské množství adres, řádově 22000×8, což můžeme považovat za nekonečno.
  • formát: textový řetězec s vnitřní strukturou
  • významovost: typicky významový identifikátor
  • využití: jmenné prostory v XML a ve formátech, které jsou na XML postavené (XHTML, SVG, DocBook, DITA, OpenDocument a spousty dalších), RDF, odkazy, web, e-mail, SIP, XMPP atd.

URI (Uniform Resource Identifier) je obecně identifikátorem, který ukazuje na nějaký zdroj, což je dost abstraktní pojem a zdroj může být prakticky cokoli. URI existují v mnoha schématech.

IRI (Internationalized Resource Identifier) vychází z URI a rozšiřuje ho o mezinárodní znaky (např. diakritiku v češtině). Díky tomu není potřeba se omezovat na ASCII a zapisovat Unicode znaky pomocí procentového kódování. URI a IRI sdílejí stejný seznam schémat. U jednotlivých formátů a protokolů by mělo být definováno, zda pracují s URI nebo IRI. Např. RDF používá od verze 1.1 IRI. Pro potřeby tohoto článku ale budeme URI a IRI považovat za synonyma, protože rozdíl zde není podstatný – pokud zde tedy mluvíme o URI, může to být i IRI.

URN (Uniform Resource Name) je způsob, jak do systému URI integrovat identifikátory z jiných, již existujících, systémů. Jde o URI schéma urn, za kterým následuje tzv. namespace identifier, což je vlastně druhá úroveň schématu, a za ní následuje již konkrétní identifikátor. Díky tomu můžeme ve formě URI zapsat odkaz např. na knihy (ISBN), časopisy (ISSN), OID, UUID či RFC. Příklady URN:

urn:uuid:e2a68063-1b28-5caf-86ce-d6e3c04a4b9d
urn:oid:1.3.6.1.4.1.41821
urn:isbn:0-646-39832-6
urn:ietf:rfc:2648

URL (Uniform Resource Locator) je druh URI, které umožňuje daný zdroj přímo kontaktovat nebo stáhnout.

V této kapitole jsme zmínili jen nejběžnější identifikátory používané v našem oboru. Stejným způsobem by šlo k odvozování jmenných prostorů použít i třeba čísla autonomních systémů (AS), Mobile Network Code (MNC) či identifikátory používané v jiných oborech (DOI, ISBN, ISSN, VIAF, ISNI, mezinárodní desetinné třídění atd.).

URI schéma tag:

Internetové domény jsou jedním z nejoblíbenějších způsobů odvození názvu jmenného prostoru. Jsou globálně unikátní, levné, snadno zapamatovatelné a už na první pohled z nich můžeme vytušit, co je obsahem (není to jen nicneříkající číslo nebo kód). Má to však jeden háček a tím je čas. Vlastník domény se může v průběhu času měnit a ta globální unikátnost tudíž platí jen k jednomu konkrétnímu okamžiku. Pouze na základě znalosti názvu jmenného prostoru resp. domény proto nejsme schopni říct, kdo je jeho vlastníkem – kdo je oprávněný vytvářet v tomto jmenném prostoru jména a definovat jejich význam. Totéž platí pro atributy, subjekty, predikáty či objekty (viz kapitola RDF níže). Pravděpodobně budeme schopní zjistit aktuálního vlastníka domény, možná i předchozí vlastníky, ale nebudeme schopni říct, kterému z nich patří daný jmenný prostor. Řečeno slovy relační algebry: máme tu relaci (tabulku) domén a relaci vlastníků, mezi kterými je vztah m:n, záznamy ve vazební tabulce mají časovou platnost od/do, ale protože nevíme, kdy jmenný prostor vznikl, nedokážeme v relaci vlastníků vybrat ten správný záznam.

Když už víme, v čem je problém, řešení je zřejmé – přidat do názvu jmenného prostoru vedle domény i čas. A právě to dělá URI schéma tag:, které bylo definované v říjnu 2005 jako RFC 4151. V tomto schématu můžeme vytvářet identifikátory, které jsou unikátní nejen v prostoru, ale i v čase.

Přesná ABNF syntaxe tohoto schématu je uvedena v RFC. Zde si ukážeme jen pár příkladů:

tag:example.com,2020-01-01:abc/def
tag:example.com,2020-01:abc/def
tag:example.com,2020:abc/def#xyz
tag:example.com,2020:abc:def#a123
tag:joe.sixpack@example.com,2020:abc/def
tag:globalcode.info,2018:relpipe
tag:globalcode.info,2018:sqldk

Po názvu schématu tag: následuje doménové jméno nebo e-mailová adresa. Což je, mimochodem, další výhoda tohoto schématu – nemusíme být vlastníky internetové domény, abychom mohli definovat URI nebo jmenný prostor. Stačí, že disponujeme e-mailovou adresou.

Dále tu máme datum. Tím ukážeme na konkrétního vlastníka domény či e-mailu. Můžeme uvést i měsíc a den. Pokud je neuvedeme, bere se to jako první den v měsíci resp. 1. ledna daného roku. Doména nebo e-mail můžou změnit vlastníka několikrát do roka, takže je dobře, že tu tato možnost je, ale moc často se to neděje, takže většinou si vystačíme s uvedením roku. Není důvod dělat identifikátor zbytečně delším. Pokud vlastníme doménu třeba už deset let, je úplně jedno, který rok si vybereme – vlastník se za celou dobu nezměnil, takže výsledek je stejný. Ale když si nějaký rok vybereme, tak už se ho – pro dané URI – musíme držet. Jinak by se jednalo o různá URI. Totéž platí pro zkrácený zápis data: tag:example.com,2020-01-01:abc bude sice ukazovat na stejného vlastníka jako tag:example.com,2020:abc, ale jedná se o dvě různá URI. Většinou asi použijeme aktuální rok. Případně se můžeme chtít pochlubit svoji dlouhou historií a uvést tam rok založení naší firmy či organizace (což lze, i když jsme k 1. lednu daného roku tuto doménu nevlastnili – za předpokladu, že jsme její první majitel a předtím ji neměl registrovanou nikdo). Když budeme v dalších letech vytvářet nová URI, tak je otázka, zda použít zase aktuální rok. Spíš bych doporučoval se držet toho původního, protože pak je už při pohledu na URI zřejmé, že je vytvořil tentýž subjekt (není nutné zkoumat, zda se vlastník domény v průběhu těch let nezměnil).

Za dvojtečkou následuje specifická část a případně fragment – zde si o názvech, hierarchii a oddělovačích rozhodujeme sami. Na začátek pravděpodobně dáme název projektu, produktu nebo organizační jednotky a zbytek bude zase specifický pro ně.

Schéma tag: elegantně řeší problém nejednoznačnosti identifikátorů, která se v průběhu času může vyskytnout. Někdo by teď mohl přispěchat s hraběcí radou, že si máme platnost domény hlídat a nenechat ji propadnout. To je sice pravda, ale v minulosti jsme mohli být svědky toho, že o doménu přišly i celkem významné projekty nebo organizace, takže je to věc, která se reálně děje. Pokud je expirovaná doména alespoň trochu zajímavá (např. na ni vedou na webu nějaké odkazy), okamžitě po ní skočí různí podvodníci, weboví spammeři, SEO optimalizátoři nebo spekulanti. Poté, co se potenciál (např. těch zpětných odkazů) vyčerpá, tak se často doména dostane do dražby a často najde nového vlastníka (což už nemusí být jen spekulant – může mít s doménou dobré úmysly a může ji mj. chtít používat pro definici jmenných prostorů). Takže místo toho, abychom doufali, že nám se to stát nemůže, je lepší použít technologii (schéma), která problému předchází. Kromě toho se může stát, že původní autor ukončí činnost a doménu nechá propadnout vědomě. Ukončení jeho činnosti ale neznamená, že by všechny instalace daného systému přestaly ze dne na den existovat. Tím pádem jsou v oběhu i původní identifikátory, které se mohou nacházet v nepřeberném množství dokumentů (souborů a záznamů na počítačích lidí, které ani neznáme). S těmi je často potřeba nadále nějak pracovat (a třeba je i vkládat do jiných dokumentů nebo míchat s jinými daty v databázi), ale protože se jedná o archivní data, nechceme do nich zasahovat a konvertovat např. na nový formát a převádět do jiných jmenných prostorů. Také můžeme mít spoustu různých dotazů a šablon, kterými z těch dokumentů generujeme nějaké výstupy. Pokud jmenný prostor v dokumentech změníme, rozbijeme si všechny dotazy a šablony (tady může být obtížné už vůbec zjistit, zda nebo kde všude je máme) a musíme je přepisovat, což stojí čas a peníze. A pokud jmenný prostor nezměníme, máme tu riziko kolidujících názvů.

Tenhle problém nemá dobré řešení. Ale lze mu předejít tím, že už na začátku použijeme identifikátory, které jsou unikátní nejen v prostoru, ale i v čase.

Resource Description Framework (RDF)

Když už umíme věci jednoznačně pojmenovat, můžeme u nich evidovat různé vlastnosti nebo atributy. Třeba řekneme, že nějaká věc má modrou barvu. Jenže co je to barva? Tady bychom se asi na nějaké definici tohoto slova shodli… i když taky by to mohlo znamenat, že ta věc je třeba pobočka a „mít barvu“ znamená mít plechovku dané barvy na skladě. Nebo to taky může být barva tónu. A u jiných atributů to bude zpravidla ještě složitější a každý si bude jejich význam vykládat trochu jinak. Komu to slovo – např. „barva“ – patří? Kdo může definovat jeho význam? Tato úvaha nás vede k závěru, že slova přirozeného jazyka nejsou pro tento účel vhodná a že i tyto vlastnosti jsou „věc“ a zaslouží si mít vlastní globálně jedinečný název. Tento název se bude nacházet v nějakém jmenném prostoru. A vlastník tohoto prostoru bude tím, kdo definuje význam dané vlastnosti. Díky tomu nebude docházet ke kolizím a nejasnostem a ve chvíli, kdy použijeme globálně jedinečný název vlastnosti, bude zřejmé, jakou definici máme na mysli. Máme tedy jednoznačně určenou věc, jednoznačně určenou vlastnost a teď nám zbývá popsat hodnotu této vlastnosti. Tou hodnotu může být buď ukazatel na jinou věc (např. když budeme chtít vyjádřit příbuzenský vztah mezi dvěma osobami nebo to, že jedna firma vlastní jinou) nebo to může být literál – nějaká data sama o sobě, která vyjádříme jako text nebo číslo (např. „28“ bude hodnota vlastnosti, která je definovaná jako „teplota ve ° C“). U ukazatelů na jiné věci je to jednodušší – tam jde o globálně unikátní název dané věci. V případě hodnot je potřeba, aby jejich syntaxe byla obsažena v definici daného atributu. Např. tu barvu bychom mohli definovat jako text „RRGGBB“ kde jednotlivé dvojice budou vyjadřovat hexadecimálně hodnotu barevných složek, takže třeba „0000FF“ bude modrá. Tato syntaxe bude zákonitě specifická pro daný atribut, takže zatímco „0000FF“ bude v jednom případě znamenat modrou, v jiném případě to budou prostě nějaké tři bajty a ve třetím to bude třeba kód výrobku. Stejně tak „28“ může být jednou teplota ve ° C a jindy to může být třeba délka v centimetrech nebo věk. Z hodnoty samotné tedy nic vyvozovat nemůžeme – jedná se o surová data. Abychom je mohli interpretovat a stala se z nich informace, potřebujeme znát definici daného atributu. Zatím jsme mluvili o vlastnostech či atributech. Ale posuneme to ještě o kousek dál – budeme tomu říkat predikát. Když atribut byl „barva“, tak predikát bude „má barvu“. Zde vidíme, že posunem k predikátům o nic nepřijdeme – všechny atributy či vlastnosti lze převést na predikát. Pouze získáme o něco abstraktnější a univerzálnější nástroj.

Obecný koncept, který jsme si popsali v předchozím odstavci, je formalizován jako Resource Description Framework (RDF). Ty „věci“ nazývá slovem subjekt, predikátům říká predikát a tomu třetímu říká objekt. Subjekty a predikáty jsou identifikované pomocí IRI (ve starších verzích URI). Objekty jsou buď také IRI (URI) nebo jsou to textové řetězce (Unicode). Trojice (subjekt + predikát + objekt) se dohromady nazývá výrok.

Výroky můžeme zapisovat (serializovat) různými způsoby, např. jako XML či Turtle. Ale jedná se jen o odlišnou syntaxi – RDF je abstraktní model – význam popisovaných dat či metadat je stejný a jednotlivé syntaxe lze mezi sebou navzájem převádět.

Zatím to dost připomíná návrhový vzor EAV (entity-attribute-value), který bývá často považován za anti-vzor (když je implementovaný nad relační databází naivním způsobem bez optimalizací a podpory dotazování). Jsou tu ale podstatné rozdíly. EAV pracuje s atributy zatímco RDF s predikáty. Málokdo při implementaci EAV používá globálně unikátní názvy. A pro RDF existuje dotazovací jazyk SPARQL a existují pro něj implementace databází, které jsou optimalizované pro ukládání výroků a efektivní provádění dotazů nad nimi. Těmto databázím se říká triplestore a nejznámější implementace jsou JenaVirtuosoRDF4J (vše svobodný software). Další rozměr tomu pak přidávají ontologie, ze kterých se můžou odvozovat různé další vztahy jako dědičnost nebo synonyma. Tím už se dostáváme daleko za hranice nejen EAV ale i relačních databází.

Poznámka: I když k sobě má RDF a XML celkem blízko a i když je XML klasickým serializačním formátem pro předávání RDF dat, tak pokud se bavíme o ukládání a dotazování jsou to dost odlišné světy – nelze automaticky říct, že by XML databáze (např. eXist-db nebo BaseX) či relační databáze s podporou XML (např. PostgreSQL) byla vhodná pro ukládání RDF. Jednak ty RDF výroky (trojice) nemají s XML dokumenty moc společného a jednak se pro ně hodí jiný dotazovací jazyk (SPARQL). Mohli bychom sice psát dotazy v XPath nebo XQuery, ale protože to jsou univerzální jazyky pro psaní dotazů nad libovolným XML, není to moc efektivní. (tohle je asi zřejmé, ale v pár diskusích jsem už viděl, jak se někdo ptal na ukládání RDF a lidé mu odpovídali, že ho může nacpat do XML sloupce… ano, může, ale tudy cesta nevede)

Jak jsme si již řekli, k identifikaci subjektů, predikátů a objektů používáme IRI. Nicméně vypisovat všude vždy celý globální identifikátor by bylo nešikovné a duplicitní. Proto se – stejně jako v XML – používá tzv. QName neboli kvalifikované jméno, které se skládá z prefixu a lokálního jména. Když máme tedy následující atributy (IRI):

tag:example.com,2020:foo/color
tag:example.com,2020:foo/size
tag:example.com,2020:foo/weight

tak si definujeme prefix f pro jmenný prostor tag:example.com,2020:foo/:

PREFIX f: <tag:example.com,2020:foo/>

a následně používáme kratší kvalifikovaná jména:

f:color
f:size
f:weight

Dobře se to mapuje i na XML a jeho xmlns a názvy elementů či atributů. Mimochodem: tohle je obecný princip, který můžeme uplatnit i jinde, ne jen tam, kde pracujeme s XML či RDF. Jednoznačné a zároveň stručné názvy se hodí prakticky všude.

Původní IRI subjektu, predikátu či objektu získáme prostým připojením lokálního názvu ke jmennému prostoru prefixu. Ten proto zpravidla končí nějakým oddělovačem, jako je / nebo # či dvojtečka.

Prefix může být celkem libovolná zkratka, kterou pak můžeme používat v daném dokumentu nebo dotazu. Ale existují určité konvence a zažité zkratky. Najdeme je na webu Prefix.cc. Příklady obvyklých zkratek: rdf, rdfs, foaf, xsd.

Jazyk SPARQL nám umožňuje psát podobné dotazy jako SQL, ale nad jinak strukturovanými daty. Např. si můžeme vyhledat filmy, kde si spolu zahráli Winona Ryderová a Dennis Quaid:

#!/usr/bin/env rdf-sparql-interpreter.sh
# endpoint: https://dbpedia.org/sparql
# relation: winona_dennis

PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX dbo:     <http://dbpedia.org/ontology/>
PREFIX dbp:     <http://dbpedia.org/property/>
SELECT
	?nazev_filmu
	(?rok AS ?rok_vydani)
WHERE {
	?herec1 foaf:name "Winona Ryder"@en .
	?herec2 foaf:name "Dennis Quaid"@en .
	?film dbo:starring ?herec1 .
	?film dbo:starring ?herec2 .
	?film foaf:name ?nazev_filmu .
	?film dbp:recorded ?rok .
}
ORDER BY ?rok

A dostaneme:

winona_dennis:
 ╭──────────────────────┬─────────────────────╮
 │ nazev_filmu (string) │ rok_vydani (string) │
 ├──────────────────────┼─────────────────────┤
 │ Great Balls of Fire! │ 1988                │
 ╰──────────────────────┴─────────────────────╯
Record count: 1

Data v RDF můžou být vícejazyčná, proto v dotazech (případně i výsledcích) vidíme kód jazyka, např. @en. Jazyk je zde vlastností hodnoty, nikoli predikátu. A pokud by zde bylo více jazykových verzí foaf:name, vrátil by nám tento dotaz kartézský součin.

Tématu RDF se věnuje i příklad v dokumentaci Relačních rour: Querying an RDF triplestore using SPARQL, kde najdeme více podrobností, ukázek a návod, jak SPARQL dotazy spouštět (jak nad vzdálenou databází, tak nad vlastní) nebo jak zapisovat strukturovaná data v úsporném formátu Turtle.

RDF je dost rozsáhlá a zajímavá oblast informatiky, dá se studovat roky a je to skvělé téma pro diplomky a disertace. Nicméně začít se dá s málem – pro začátek potřebujeme tři věci: 1) software, např. Jena, Virtuoso či RDF4J, viz výše 2) ontologii 3) strukturovaná data.

Ontologie je jednak samostatný vědní obor resp. filosofická disciplína. A jednak tímto slovem označujeme výstup analytické činnosti – formalizovaný popis určité oblasti. V příkladech výše jsme pracovali s predikáty jako foaf:name nebo dbo:starring, které jsou součástí ontologie a říkají, že se někdo či něco nějak jmenuje nebo někdo v něčem hraje. I když to zatím mohlo vypadat jako nějaká chaotická bez-schémová databáze, v RDF máme typy a třídy a definujeme, k jakým subjektům a objektům (hodnotám) se predikát může vztahovat. Vzdáleně se to dá přirovnat k definici tabulek v relačních databázích.

Doporučuje se používat již existující ontologie a identifikátory (IRI), aby bylo možné data z různých zdrojů kombinovat a vzájemně se na ně odkazovat. Nicméně i když si vymyslíme vlastní ontologii, není problém data při importu a exportu konvertovat, přejmenovat predikáty, upravit hodnoty atd. Samozřejmě, čím podobnější struktury budou, tím méně práce si přiděláme. Katalog existujících slovníků najdeme např. zde: Linked Open Vocabularies.

Stále to ale vypadá moc jednoduše, že? Tak to trochu zkomplikujeme. Zda někdo hrál nebo nehrál v nějakém filmu vypadá jako celkem zřejmý fakt, o kterém většinou nebude sporu. Takový výrok ale popisuje skutečnost k nějakému časovému okamžiku. Záznamy v životopise herců jen přibývají, nemohou mizet a moc nás nezajímá, kdy záznam vznikl (resp. víme, že vznikl ve stejnou dobu jako daný film). Je ale mnoho jiných dat, která se v čase mění. Např. v kapitole o tag: URI jsme si říkali o tom, že internetová doména může mít postupně více vlastníků. Jak bychom tuto skutečnost modelovali v RDF? Predikát „je vlastníkem“ sám o sobě nestačí, protože tím bychom popsali jen současný stav, ale nevěděli bychom, od kdy je dotyčný vlastníkem a komu doména patřila dřív. Další komplikace je pravdivost výroku. Na první pohled zní dost nepochopitelně, proč bychom ve své databázi chtěli ukládat nepravdivé výroky… ale někdy nemusíme být schopni pravdivost či nepravdivost vyhodnotit a přesto je pro nás ten výrok zajímavý – např. si o něm myslíme, že je na 80 % pravdivý. Pak tu jsou výroky, které řekl někdo jiný, my o nich můžeme pochybovat nebo je považujeme vyloženě za nepravdivé, ale přesto jde o informaci, kterou chceme uchovávat: „někdo někdy něco řekl o něčem“.

Existují různá řešení. Jedním z nich je tzv. zhmotnění neboli reifikace. Jeden původní výrok převedeme na čtyři a více výroků – jednak mu přiřadíme typ rdf:Statement a jednak na něj navážeme rdf:subject, rdf:predicate, rdf:object. Z původního výroku se tak stane adresovatelná entita, kterou můžeme použít jako subjekt (případně objekt) a navázat na ni další predikáty (např. tu časovou platnost nebo pravdivost). Potřebujeme ale software, který s takovými zhmotněnými výroky umí pracovat.

Další možnost je udělat něco jako vazební tabulku v relačních databázích. Výše jsme zmínili problém vlastníka domény, který se může v čase měnit. Možným řešením pak je místo predikátu „je vlastníkem“ vytvořit subjekt „Vlastnictví“, na který navážeme několik predikátů: vlastníka, doménu, platnost od/do a další věci.

Při řešení problému pravděpodobnosti (pravdivosti) výroků je jednou z možností využít dědičnost a míru pravdivosti „zakódovat“ do ontologie.

Nicméně, když se podobnými otázkami začneme zabývat, komplexita řešení narůstá poměrně vysokým tempem… a pak je na zvážení, zda jsou vyšší přínosy nebo naopak náklady spojené s touto komplexitou. Měli bychom postupovat podle podobných zásad jako při návrhu relačních databází. Cílem návrhu a datového modelování totiž není vytvořit v počítači dokonalý obraz reality, ale nalezení vhodné podmnožiny či dokonce pouhé aproximace tohoto obrazu, která bude užitečná pro naši aplikaci, pro daný případ užití.

Obecné doporučení

Prvním a zásadním krokem je uvědomit si, že nějaké jmenné prostory vůbec existují a začít nad jmény (názvy, identifikátory) uvažovat tímto způsobem. Jmenné prostory (ve smyslu: množina jmen) totiž existují, i když si je explicitně nepojmenujeme.

Druhým krokem je logický návrh a rozhodnutí, kdo bude moci jména vytvářet a jak budou strukturovaná. Budeme identifikátory spravovat jen my sami a pouze tento číselník někde zveřejníme? Nebo je budou moci vytvářet členové nějakého konsorcia? (tzn. více subjektů, ale stále uzavřená skupina) Nebo je bude moci vytvářet kdokoli, aniž by se někoho ptal a s někým se koordinoval? Půjde o plochý seznam? Nebo to bude hierarchická struktura, kde bude možné části stromu delegovat na jiné subjekty?

A až třetím krokem je výběr konkrétní technologie resp. schématu. Ve většině případů asi odvodíme identifikátor jmenného prostoru od internetových domén. Nicméně neměli bychom toto řešení předjímat a pod slovy „jmenný prostor“ si automaticky představovat něco jako com.example.abc.def (nebo http://abc.example.com/def/). Pokud např. pracujeme s omezenými zdroji a snažíme se minimalizovat počet bajtů, které se ukládají a přenášejí, tak dost možná použijeme raději nějaké číselné identifikátory místo libovolně dlouhých textových řetězců. Zde přijdou vhod PEN a OID a můžeme podporovat i použití více schémat souběžně. Když se budeme držet internetových domén, je potřeba se rozhodnout, zda budeme pracovat čistě s doménou a zápisem typu com.example.abc.def nebo zda použijeme URI, ve kterém bude doména obsažena, např. tag:abc.example.com,2020:def. V obou případech jde o textový řetězec a identifikátory může vytvářet kdokoli, kdo vlastní nějakou internetovou doménu. V prvním případě lze název jednoduše mapovat na adresářovou strukturu (což může a nemusí být relevantní argument). URI nám ale dává mnohem větší flexibilitu a nejsme omezeni jen na internetové domény – názvy můžeme odvozovat např. i od těch OID, UUID, hashů, zeměpisných souřadnic, telefonních čísel atd. A i když to nemusí být hezké, URI lze na adresářovou strukturu mapovat také: název souboru totiž bývá typicky implementován jako pole bajtů (případně řetězec v Unicode) a může obsahovat libovolné znaky kromě lomítka a nulového bajtu. Nulový bajt se ani v URI nebude vyskytovat a lomítka z URI se převedou na podadresáře.

Do úvah bychom měli zahrnout i následující otázky:

Identifikátor nebo lokátor? Název jmenného prostoru nemusí sloužit jen k identifikaci (URI), ale může i ukazovat (URL) na místo, kde lze nalézt další informace. Teoreticky se na daném URL může nacházet dokumentace daného protokolu, formátu či atributu a uživatel se k ní může dostat jedním kliknutím resp. překopírováním adresy do prohlížeče. Bohužel je to jen konvence a není jednoznačně dané, co by se na dané adrese mělo nacházet – má to být XHTML stránka? PDF dokument? XSD schéma? – takže to stejně není strojově zpracovatelné a vyžaduje to lidskou ruční práci. Fungovat to může s RDF, takže pokud ho používáte, mají lokátory smysl. V praxi se ale málokdy jedná o funkční odkaz, na kterém by bylo něco užitečného. A často jsou tyto zdánlivé lokátory spíše matoucí. Pracovníka podpory nebo začínajícího programátora, který při řešení chyby našel URL někde v logu, to mnohdy svede na špatnou cestu a začne se zaobírat tím, proč daný odkaz „nefunguje“ (jmenný prostor nemusí být funkčním odkazem, ale když je na začátku http://, tak si řada lidí myslí opak) nebo zda by se nemělo něco povolit na firewallu. Tím klidně stráví den práce a zaměstná další lidi. Někteří zase v dobré víře přepíší http:// na https:// – „aby to bylo bezpečnější“ – čímž systém úplně znefunkční, protože najednou jde o úplně jiné jmenné prostory. A aby toho nebylo málo, některé programy se automaticky snaží připojovat na URL, která jim přišla pod ruku, což generuje další zavádějící chybové hlášky nebo způsobuje záhadné prodlevy (čekání na síťový timeout). Lokátory nás navíc připraví o časový rozměr (který je obsažen v tag: URI). Na základě zkušeností bych tedy doporučil se lokátorům ve jmenných prostorech spíše vyhýbat. Pokud dokumentace existuje, snadno ji najdeme i bez toho – z domény obsažené v URI nebo z OID zjistíme, kdo je autorem. V případě UUID nebo různých hashů sice lidsky čitelný název nemáme, ale full-textové vyhledávání by si s těmito identifikátory mělo poradit.

Ať už se rozhodneme pro identifikátor nebo lokátor, tak pokud chceme používat jmenný prostor zároveň jako prefix v RDF, mělo by toto URI/URL končit oddělovačem – připojením lokálního názvu subjektu, predikátu nebo objektu pak vznikne nové URI či URL (ono by vzniklo i bez oddělovače, ale nebylo by to hezké). Viz kapitola RDF.

Prokazatelné vlastnictví a technologicky tvrdé či lidsky měkké řešení? Pokud identifikátor obsahuje veřejný klíč nebo jeho otisk, má se za to, že vlastník příslušného soukromého klíče je i vlastníkem daného identifikátoru resp. jmenného prostoru. Proces ověření lze navíc automatizovat a nejsme závislí na žádných registrech nebo autoritách – systém je plně decentralizovaný, může pracovat offline, není tu žádný SPoF a věřit musíme pouze použitému algoritmu. Na druhou stranu, pokud bychom soukromý klíč ztratili nebo došlo k jeho vyzrazení či dokonce prolomení algoritmu, máme smůlu – technologie je tvrdá a chyby neodpouští – budeme si muset vymyslet nový identifikátor a přesvědčit ostatní, aby ho začali používat a že to jsme pořád my, nebo si necháme ten původní, budeme ho brát jako bezvýznamový náhodný řetězec znaků a otisk ztraceného klíče v něm bude strašit navěky. Analogií tohoto měkkého a tvrdého přístupu jsou např. klasické bankovní transakce a Bitcoin (obecně kryptoměny). Když pošleme peníze na špatné číslo účtu, můžeme požádat banku, aby transakci zrušila nebo pak chtít po příjemci, aby toto neoprávněné obohacení vrátil, případně se s ním i soudit. Pokud si ale spleteme adresu v nějakém kryptoměnovém systému, pravděpodobně se nedovoláme ničeho a záleží jen na poctivosti příjemce, jestli nám mince vrátí. Pokud je fyzická identita příjemce neznámá, což často je, není se s kým soudit. A pokud byl soukromý klíč k dané adrese ztracen, není na světě nikdo, kdo by nám mohl pomoci. Systém transakci zpracoval a tím to končí. Oba přístupy mají své výhody a nevýhody. V tom tvrdém-technologickém nemůže nikdo zneužívat svoji funkci, nemůže selhat lidský faktor (resp. pokud selže, tak dotyčný poškodí jen sám sebe). Měkký-lidský přístup je zase tolerantnější k chybám a umožňuje některé věci vracet zpět nebo řešit problémy ad-hoc. Záleží na potřebách konkrétní aplikace či projektu, kterou cestou se vydáme.

Otevřený nebo uzavřený systém? V minulosti vznikla řada systémů, které byly pod kontrolou jedné centrální autority. Byť za tím mohla být dobře míněná snaha „dělat věci jednoduše“ (nekomplikovat je nějakými jmennými prostory) a „udržet v tom pořádek“, často to vedlo ke vzniku úzkého hrdla a paradoxně většího nepořádku, protože centrální autorita buď kontrolovala systém příliš a ten stagnoval, nebo na kontrolu rezignovala a dovolila ostatním, aby ten jeden jediný nehierarchický jmenný prostor zaneřádili. Z toho plyne ponaučení, že většinou je lepší jen ukázat lidem cestu, vytvořit systém, a pak už nechat věci, ať se dějí samy – nesnažit se mít nad vším kontrolu a do všeho mluvit. Takové systémy navrhovat lze a jejich předpokladem jsou právě jmenné prostory a hierarchie, ve kterých lze části stromu delegovat na někoho jiného. V takto navrženém systému mohou vznikat nové identifikátory paralelně na mnoha místech, aniž by bylo potřeba se s ostatními koordinovat a synchronizovat. Dá se to přirovnat k programu, který běží na víceprocesorovém stroji a je navržený tak, že jednotlivé procesy či vlákna nemusí čekat na žádný centrální zámek a přesto nedochází k nežádoucím kolizím. Nicméně uzavřené systémy jednu výhodu mají – pokud je přidělení identifikátoru podmíněno členstvím v nějakém konsorciu, můžou členské příspěvky sloužit jako zdroj financování pro danou organizaci, která pak může pečovat o daný formát, systém či protokol a vyvíjet jeho další verze, aniž by byla závislá na nějakých dotacích zvenčí.

Stručně shrnuto: pro vlastní jmenné prostory použijeme URI schéma tag:, pokud nemáme dobrý důvod použít něco jiného. A pokud má náš systém pracovat se jmennými prostory (či predikáty, subjekty atd.) definovanými někým jiným, umožníme použití libovolného URI – pro nás je to pořád jen textový řetězec a ostatním to umožňuje odvodit svůj jmenný prostor od toho, co mají a preferují (pro někoho to třeba bude OID nebo otisk veřejného klíče).

Závěr

Názvy a jmenné prostory jsou na první pohled banální záležitost, která se často řeší tzv. za pochodu. Ve skutečnosti jde ale o téma, kterému stojí za to věnovat pozornost a vyčlenit mu odpovídající čas v rámci projektu. Nedomyšlený návrh jmen a jmenných prostorů je většinou obtížné dodatečně opravit. Zároveň jsme si snad ukázali, že i toto téma může být docela zajímavé a zábavné.

Témata: [softwarové inženýrství] [softwarová architektura] [XML] [Java] [RDF]

Komentáře čtenářů


jiwopene, 12. 8. 2020 19:47, OID [odpovědět]

Termín OID (Object Identifier) a odpovídající datový typ používá i PostgreSQL, ale v jiném významu. Tam jde o 32bitové číslo jedinečné v rámci databáze a navíc s nedostatečným rozsahem pro databáze s velkým počtem záznamů. Některá OID tam jsou pevně daná (ve zdrojovém kódu serveru) – např. u datových typů.


Franta, 12. 8. 2020 20:36, Re: OID [odpovědět]

Ano, to je zrovna hezký příklad toho, jak jedno jméno/zkratka může mít v různých jmenných prostorech různý význam.


IS4, 15. 10. 2020 12:40 [odpovědět]

Hodně pěkný článek; nečekal bych, že najdu tolik technologií pohromadě. Jen dvě poznámky: píše se 128bitový a bezvýznamový, ne 128-bitový a bez-významový. A trojice v RDF lze rozšířit na čtveřice subjekt, predikát, objekt, graf, kde to čtvrté třeba může představovat kontext nebo zdroj, takže i podle toho poté lze seskupovat informace.


Franta, 15. 10. 2020 17:54, čeština [odpovědět]

Díky. Číslovky jsem opravil, to mi nějak ujelo. Nad tím „bez-významově“ jsem v době článku přemýšlel a přišlo mi to tak lepší, ale je fakt, že gramaticky je to správně dohromady.

Přidat komentář

reagujete na jiný komentář (zrušit)
jméno nebo přezdívka
název příspěvku
webová stránka, blog
e-mailová adresa
nápověda: možnosti formátování
ochrana proti spamu a špatným trollům

Náhled komentáře