PkYubikey
Na předchozí článek, který vás seznámil s Yubikey, navazuji druhým textem, kterým už se pomalu blížíme k praktickým záležitostem: představuji vám knihovnu PkYubikey, kterou budu používat v dalších aplikacích (připraven mám FTP server, chystám se podívat na VNC, postupně třeba přijdou i další projekty). V tuto chvíli slouží hlavně dvěma účelům: předvést, jak jednoduché je implementovat podporu Yubikey do vašich aplikací, a provést vám základním nastavením, které budou používat všechny mé další implementace.
libYubikey
Knihovna PkYubikey je napsána v jazyce Pascal (konkrétně v implementaci Delphi, ale lze ji zkompilovat i FreePascalem) a tvoří ji několik částí. Jejím základem je libYubikey
, což není nic jiného než přepis výrobcem podporované Cčkové knihovny libyubikey do Pascalu. Moje invence se v tomto případě omezila na to, že jsem všechny funkce umístil do jediného souboru a mírně jsem přepsal funkce pro převod mezi hexadecimálním, modhexovým a binárním vyjádřením dat – přišlo mi hloupé mít pro hex i modhex samostatné funkce, když se obě kódování liší jen v použité abecedě. Z hlediska publikovaných funkcí a vstupů i výstupů ovšem všechno zůstalo tak, jako v původním libyubikey.
Jaké funkce tedy libyubikey nabízí:
-
procedure YubikeyModhexEncode(Dest, Src: PChar; SrcSize: integer); procedure YubikeyModhexDecode(Dest, Src: PChar; DestSize: integer); procedure YubikeyHexEncode(Dest, Src: PChar; SrcSize: integer); procedure YubikeyHexDecode(Dest, Src: PChar; DestSize: integer);
Funkce pro konverzi z hex resp. modhex řetězců do binární podoby a zpět. Fukce *Encode vezmou binární string (sekvenci bajtů) a převedou ho na ASCII string v příslušném kódování. Pokud bych například kódoval sekvenci bajtů
0x12, 0x56, 0x9a, 0xcd
, výsledkem YubikeyHexEncode by byl řetězec'12569acd'
, výsledkem YubikeyModhexEncode pak'bdghklrt'
. *Decode funkce dělají opačný převod. -
function YubikeyCRC16(Buffer: PChar; BufSize: integer): word;
Funkce pro výpočet CRC16 kontrolního součtu zadaného binárního řetězce. Používá se pro ověření platnosti dat dekódovaných z Yubikeyovského hesla.
- [pasca]procedure YubikeyAesDecrypt(State: PYubikeyToken; Key: PYubikeyKey);[/pascal]
Implementace rozšifrování dat zašifrovaných algoritmem AES s 128bitovým klíčem. Jak jsem si ověřil, jde skutečně o standardní AES; můžete ho použít na definované testovací vektory a skutečně dostanete očekávaný výsledek. Je to také evidentní důvod, proč vlastně Yubikey používá právě tak dlouhá hesla, jako používá, a obsahuje taková data, jaká obsahuje: AES pracuje na blocích o délce 128 bitů (16 bajtů), a právě jen při téhle délce dat není třeba řešit ani padding (doplnění kratších dat na danou délku), ani šifrovací režimy.
-
procedure YubikeyParse(OTP: PYubikeyOTP; Key: PYubikeyKey; Parsed: PYubikeyToken);
„Vysokoúrovňová“ funkce, jejímž účelem je převést jednorázové heslo do binární podoby (funkcí
YubikeyModhexDecode
) a následně ho dešifrovat (funkcíYubikeyAesDecrypt
). Není mi úplně jasné, proč Yubico tohle označuje za vysokoúrovňovou funkci, když to nic jiného nedělá – dokonce ani ověření, že dešifrovaná data jsou správná (a tedy vstupní heslo i tajný AES klíč jsou platné).
uYubikey
uYubikey už je můj příspěvek do rodiny Yubikey knihoven. Využívá výše zmiňovanou libYubikey pro vytvoření tří funkcí, které už za vysokoúrovňové klidně jde označit:
-
function PKYubikeyRegisterOTP(Name: PChar; UID: PYubikeyUID; Key: PYubikeyKey; OtpCounter: Longint): Longint;
Tato funkce je „inicializační“ – slouží k zaregistrování konkrétního Yubikey do systému. POtřebuje k tomu čtyři základní údaje:
Name: PChar
je řetězec, kterým bude daný Yubikey nadále identifikován. Typicky obsahuje přihlašovací jméno uživatele, který daný Yubikey používá (tedy např. „pepak“). Slouží k tomu, aby se na daný Yubikey dalo odkazovat nějakým „lidsky srozumitelným“ názvem – a konec konců, skoro každá aplikace bude kromě hesla vyžadovat i jméno, tak proč ho nepoužít. Délka je libovolná a obsah také, s výhradou, že nesmí obsahovat binární nulu (znak s ASCII kódem 0) a bylo by lepší, kdyby neobsahovalo zpětné lomítko.UID: PYubikeyUID
je ukazatel na řetězec šesti bajtů, které tvoří privátní ID tokenu (nastavuje se v personalizační aplikaci pro Yubikey). Podle něj program pozná, že zadané heslo patří k uživatelskému jménu.Key: PYubikeyKey
je ukazatel na řetězec šestnácti bajtů, které jsou použity jako AES klíč.OtpCounter: Longint
je aktuální hodnota počitadla tokenu. Rozumná počáteční hodnota je nula.
Registrační funkce udělá vlastně jedinou věc: do systémového registru do větve
HKEY_LOCAL_MACHINE\Software\Pepak\Yubikey
zapíše nový klíčName
(proto je vhodné, aby neobsahoval zpětné lomítko) a v něm založí záznamy pro ostatní tři parametry. Tyto záznamy nejsou nijak šifrovány, což může působit nebezpečně, ale vzhledem ke konstrukci tokenu nemám moc na výběr: Klíč a počitadlo potřebuji přesně v té podobě, v jaké je uživatel zadal, bez toho se vůbec nedá jednorázové heslo ověřit. UID by v zásadě mohlo být v podobě nějakého hashe, ale vzhledem k velmi malému prostoru možných UID (jen 6 bajtů, tedy 48 bitů) to nemá moc smysl – každý serioznější útočník by dokázal ve velmi krátké době prostě vyzkoušet všechny možnosti. Musel bych použít techniky z TrueCryptu a hash aplikovat mnohokrát po sobě (řádově tak milionkrát), abych vůbec dokázal UID ochránit. Což se zdá jako plýtvání s ohledem na fakt, že pokud už se útočník dostane k registru dotyčného serveru, dokáže nepochybně nahradit třeba i samotnou ověřovací knihovnu… -
function PKYubikeyRegisterOTPhex(Name, UIDHex, KeyHex: PChar; OtpCounter: Longint): Longint;
Tato funkce pracuje přesně stejně jako ta předchozí, jen očekává jinou podobu UID a klíče – zatímco výše šlo o binární stringy, zde jsou očekávány řetězce hexa znaků.
-
function PKYubikeyValidateOTP(Name, OTP: PChar): Longint;
Tato funkce řeší veškerou autentizaci. Na vstupu očekává jméno tokenu (řetězec
Name
z funkcí výše) a jednorázové heslo dodané Yubikeyem, na výstupu vrátí buď nulu (autentizace proběhla v pořádku – jde o správný token a nedošlo k opakování hesla) nebo chybový kód. Všechny potřebné operace, včetně zabránění dvojího přístupu k jedněm datům, už si funkce ohlídá sama. Vy prostě zavoláteif PKYubikeyValidateOTP('pepak', '123456...') = 0 then ...
a vůbec neřešíte, z čeho se to jednorázové heslo skládá a jak je zajištěno, že ho nikdo nebude moci opakovat – to všechno si zařídí tato funkce.
PkYubikeyDll.dll
Tato komponenta je vlastně to samé co uYubikey výše, ale v podobě DLL knihovny. Díky tomu jsou zmiňované tři funkce dostupné jakémukoliv programovacímu jazyku, který umí vytvářet programy pro Windows – stačí naimportovat DLL (k tomu má každý jazyk své prostředky) a začít používat jeho funkce. Reálné použití bude vidět ve FTP serveru, který popíšu v nejbližší budoucnosti – ten je psaný v jazyce C, nicméně používat DLL vytvořené v Delphi pro něj není nejmenší problém…
PkYubikey.exe
PkYubikey.exe se velmi podobá PkYubikeyDll.dll v tom, že jde vlastně o zasazení uYubikey do určitého interfacu. V tomto případě jde o utilitu, zpřístupňující funkce PKYubikeyRegisterOTPhex
a PKYubikeyValidateOTP
z příkazového řádku. Použití je v zásadě dvojí:
-
Registrování Yubikey do systému. Nemusíte nic vědět o tom, jak a kam vlastně PkYubikey ukládá data o tokenech, nepotřebujete vytvářet registrační okno pro svoji aplikaci. Stačí, když zavoláte
PkYubikey.exe
s příslušnými parametry (konkrétně-r jméno UID Klíč Počitadlo
) a utilita se o registraci tokenu sama postará. -
Ověření jména a hesla z programu, kterému nemůžete nebo nechcete opravit zdrojový kód, ale který je schopen si zavolat jiný program a ověřit jeho návratovou hodnotu. To je například případ OpenVPN ve verzích 2.1 a novějších, které umí pracovat i v režimu jméno/heslo; v takovém případě volají externí program a ověřují si jeho návratovou hodnotu (result code, errorlevel). Při volání použijete parametry
-a jméno jednorázové heslo
, pozitivní výsledek (platná autentizace) je signalizován návratovým kódem nula.
Download
PkYubikey v0.05 (25.10.2010, 71 KB). Pročištěn zdrojový kód. Licence explicitně uvedena jako nová BSD licence. Přidáno číslo verze a digitální podpisy do spustitelných souborů.
PkYubikey v0.03 (15.9.2009, 41 KB).
I think that’s only supported with the newer Yubikeys (version 2.2), and as I have the older revision (2.1), I couldn’t test it.
What about integrating YubiKey Challenge-Response?
Verze 0.05: Pročištěn zdrojový kód. Licence explicitně uvedena jako nová BSD licence. Přidáno číslo verze a digitální podpisy do spustitelných souborů.