Volba identifikátoru: UUID, krátká ID a ta, která prozrazují informace
Pro cokoli interního použijte UUID v4, v7 tam, kde je identifikátor primárním klíčem velké tabulky, a krátký kód z omezené abecedy tam, kde ho člověk musí přečíst nahlas. Sekvenční celá čísla jsou volba, které je na čemkoli veřejném lepší se vyhnout.
Verze UUID, na kterých záleží
UUID má 128 bitů. Čtyři nesou verzi a dva variantu, takže žádná verze nemá k dispozici celých 128.
| Verze | Co obsahuje | Kdy ji použít |
|---|---|---|
| v1 | 60bitové časové razítko, 14bitová sekvence hodin, 48bitové ID uzlu (MAC adresa) | Jen u starších dat |
| v3 / v5 | Hash MD5 nebo SHA-1 ze jmenného prostoru a jména | Když jsou potřeba deterministická ID |
| v4 | 122 náhodných bitů, nic víc | Výchozí volba, když se nemá dát nic odvodit |
| v7 | 48bitové časové razítko v milisekundách, pak 74 náhodných bitů | Klíče, kde záleží na pořadí vkládání |
v1 je ta varovná. Zabudovává čas vytvoření a ve většině implementací i MAC adresu stroje, který ji vyrobil, což je způsob, jakým takové identifikátory v roce 1999 pomohly vystopovat autora viru Melissa. v7, standardizovaná v RFC 9562 v roce 2024, čas vytvoření zveřejňuje záměrně: je to zároveň její přednost i její cena.
Otázka kolizí
UUID v4 má 122 náhodných bitů, takže jich existuje 2^122, zhruba 5,3 x 10^36. Podstatná je narozeninová mez, ne velikost prostoru: pravděpodobnost, že se shodnou libovolné dvě z n hodnot, je zhruba n na druhou děleno 2^123. Bilion vygenerovaných UUID nese asi jednu šanci k deseti bilionům, že vznikne duplicita, a na pravděpodobnost hodu mincí je potřeba asi 2,7 x 10^18 hodnot, tedy zhruba 85 let při miliardě za sekundu.
„Není to praktický problém“ pořád ještě není „nemožné“ a ten rozdíl nikdy nedělá aritmetika. Duplicity vznikají v generátoru: pevný seed, virtuální stroj naklonovaný i s poolem entropie, obraz kontejneru, který s sebou nese uložený stav PRNG. Jedinečnost patří zdroji náhodnosti, ne formátu, takže si nad sloupcem nechte unikátní omezení.
Řazení, lokalita indexu a únik informací
Náhodné identifikátory se rozptylují. V indexu typu B-strom padne každý vklad do náhodné listové stránky, takže pracovní množinou je celý index místo jeho pravého okraje, klesá úspěšnost cache a stránky se štěpí. Klíč, který v čase roste, se připojuje na jednom místě a udržuje horkých stále několik stejných stránek. Právě proto existují v7 a ULID; ULID je 48 bitů časového razítka v milisekundách plus 80 náhodných bitů, zapsaných jako 26 seřaditelných znaků Crockfordovy base32.
Cenou je předvídatelnost: časově řazené ID zveřejňuje, kdy jeho záznam vznikl, takže hrstka takových ID prozradí tempo registrací i hodiny, kdy je klid. Pokud na tom záleží, použijte v4 a zaplaťte cenu v indexu.
Sekvenční celá čísla jdou dál. /invoices/1041 říká, že jste vystavili zhruba tisíc faktur, a dvě ID s týdenním odstupem prozradí tempo vašeho růstu. Horší je, že útočník si může vyžádat 1040. Pokud server ten záznam vrátí jen proto, že existuje a volající je přihlášený, aniž by ověřil, komu patří, jde o selhání řízení přístupu, katalogizované jako nezabezpečený přímý odkaz na objekt. Neuhodnutelné ID není kontrola oprávnění, ale zabrání tomu, aby si někdo procházel tabulku řádek po řádku.
Slugy jsou také identifikátory a při správném sestavení neprozrazují nic o objemu: diakritika odstraněná, písmena převedená na malá, interpunkce sloučená do spojovníků, jak to dělá Slug Generator. Po publikaci ho nechte beze změny; jeho úprava rozbije příchozí odkazy.
Krátká ID, abecedy a délka
Každý znak náhodného kódu má hodnotu log2 velikosti abecedy: 5,95 bitu pro base62, 5 pro base32 a 4 pro hexadecimální zápis. Délka a abeceda určují pravděpodobnost kolize při daném objemu.
| Délka (base62) | Různých hodnot | Bitů | Pravděpodobnost kolize v rámci 1 miliardy ID |
|---|---|---|---|
| 8 | 2,2 x 10^14 | 43,7 | Jistá |
| 10 | 8,4 x 10^17 | 59,5 | Zhruba 45 % |
| 12 | 3,2 x 10^21 | 71,5 | Zhruba 1 ku 6 500 |
| 16 | 4,8 x 10^28 | 95,3 | Zhruba 1 ku 100 miliardám |
To předpokládá, že každý znak je nezávisle náhodný; prefix jako inv_ přidává nula bitů.
Pro cokoli, co čte člověk, je base62 špatná abeceda. 0 a O, 1, l a I jsou chyby při přepisu, které na sebe nenechají čekat, a kód rozlišující velikost písmen nepřežije telefonát. Crockfordova base32 vypouští I, L, O a U a na vstupu přijímá obě velikosti; ten znak navíc za to stojí.
Odkud se berou náhodné bity
Math.random() není kryptografický zdroj. V8 ho implementuje pomocí xorshift128+, jehož vnitřní stav lze zrekonstruovat z krátké série výstupů, načež je každá budoucí hodnota předvídatelná. Pro ukázkové zamíchání nebo zástupnou hodnotu to stačí. Pro identifikátor relace, API klíč, odkaz na reset hesla nebo token je to špatně.
// Browsers, Node 19+, Deno and Bun
const id = crypto.randomUUID();
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
Jinde: crypto.randomBytes v Node, secrets.token_urlsafe v Pythonu, crypto/rand v Go, SecureRandom v Javě, random_bytes v PHP. UUID Generator vytváří kryptograficky náhodné hodnoty v4 a Password Generator používá stejné API prohlížeče; Random Numbers slouží ke vzorkování, ne k tajemstvím.
Jedna past, když si to píšete sami: mapování náhodného bajtu na 62znakovou abecedu pomocí % 62 vychýlí výsledek k prvním osmi znakům; použijte odmítací vzorkování.
Zástupná a ukázková data
Lorem ipsum je zkomolený Cicero a přežívá právě proto, že je nečitelný: text, který vypadá jako jazyk, aniž by jazykem byl, umožňuje posoudit sazbu podle tvaru a délky řádků místo podle vět, a přesně to Lorem Ipsum generator vytváří. Před finálním schválením ho nahraďte realistickým textem, protože zástupná latina zakrývá přetečení, které skutečný titulek způsobí.
Pro vymyšlená data platí jediné pravidlo: nikdy se nesmí dát zaměnit za skutečná.
- Čísla karet berte ze zveřejněného testovacího rozsahu platebního poskytovatele, nebo ať rovnou neprojdou Luhnovou kontrolou. Náhodné 16místné číslo, které Luhnovou kontrolou projde, někomu patří.
- Národní identifikátory berte z vyhrazených rozsahů. Americká čísla sociálního pojištění začínající na 000, 666 nebo 900 až 999 se nikdy nevydávají.
- Používejte
example.coma její sourozence vyhrazené v RFC 2606 a dokumentační blok 192.0.2.0/24.
Testovací data se do produkce dostanou častěji, než by člověk čekal: seed skript namířený na špatnou databázi, zástupný text zapomenutý v e-mailové šabloně rozeslané celému seznamu. Falešné záznamy mají vypadat očividně falešně, aby si jich člověk všiml dřív, než podle nich začne podpora jednat.
QR kódy ve zkratce
QR kód je mřížka modulů ve verzích 1 až 40, od 21x21 až po 177x177. Verzi určuje délka dat a při pevné tištěné velikosti znamená vyšší verze menší moduly, což vyžaduje kvalitnější tisk a bližší sken. Než URL předáte nástroji QR Code Generator, zkraťte ji, a počítejte s tím, že alfanumerický režim zná jen velká písmena, takže HTTPS://EXAMPLE.COM se zakóduje úsporněji než podoba s malými písmeny.
Oprava chyb má čtyři úrovně a obnoví zhruba 7 % (L), 15 % (M), 25 % (Q) a 30 % (H) poškozeného kódu. Redundance stojí kapacitu, takže vyšší úroveň natlačí stejná data do hustší verze. Obvyklou výchozí volbou je M; Q nebo H zvolte pro malý tisk, zakřivené povrchy nebo logo přes střed, což funguje právě proto, že to redundance pohltí.
O tom, jestli se kód načte, rozhodují dva fyzické požadavky. Klidová zóna je volný okraj široký čtyři moduly na každé straně, podle kterého dekodér najde hranici kódu, takže kód přiražený k rámečku nebo fotografii často selže. Kontrast musí být opravdu tmavá barva na opravdu světlé: světle modrá na bílé je běžná chyba a mnoho dekodérů invertované kódy odmítá.