Textová 3D CAPTCHA
Klasické textové CAPTCHAs už jednoznačně přestaly plnit svůj účel. V tomto případě ne kvůli spamerům, ale kvůli komerčním OCR, které dosáhly bodu, kdy jsou schopny číst text líp než člověk. Protiopatření? Opustit oblast OCR. Udělat obrázek, který čtečky nemají důvod umět číst.
Jako typický příklad zoufalství jmenujme Rapidshare.

Roztomilé.
Věřte nebo ne, baterie programů Symseek (odstraňuje zvlnění), CAP (rozlišuje kočičky od pejsků) a komerční FineReader 8 (OCR) zde dosahuje ve čtení skoro stoprocentní úspěšnosti - výrazně vyšší, než jaké dosahují lidé.
Nejsofistikovanější článek řetězu, FineReader, je zároveň tím nejslabším. Jediným, jehož vývoj nemají útočníci pod kontrolou.
Jak dál? Že pokračovat v linii deformování textu nemá cenu, už začínají provozovatelé chápat. Experimentuje se s fotkami nebo piktogramy, které nestačí jen přečíst, ale je potřeba je pochopit a pojmenovat.
To je ale cesta, která zvyšuje předpoklady ohledně intelektu návštěvníka. Je reálné očekávat, že návštěvník psaného webu umí číst. Je ale stejně reálné očekávat, že umí rozlišit kočku od aligátora? Nebo že ví, jak se řekne anglicky koule?
3D text
Faktu, že mozek je schopen snadno rozeznat prostorové objekty i ve značně neúplném dvojrozměrném průmětu, se dá využít právě proti robotům. Pokud nakreslíme text jako neúplný reliéf, půjde stále velmi snadno přečíst, ale OCR čtečky si s ním neporadí.
Zobrazit 3D text:
Generování 3D reliéfu v PHP
Vygenerování takového obrázku nemusí být nikterak složité. Jediné co potřebujeme, je vzorec pro projekci 3D prostoru do 2D plochy. V našem případě je to lineární perspektiva, kterou jsem vzal z minulého článku o perspektivě ve Flashi.
Jako matrici si předgenerujeme klasický obrázek s textem:
![]()
Ve 3D zobrazení pak bude každý bod reprezentovat jeden pixel z matrice. Výška reliéfu pak bude určena světlostí barvy pixelu.
# inicializace require './func/imagelightnessat.func.php'; require './class/linear_perspective.class.php'; $perspective = new linear_perspective(); # konfigurace rozměrů a pozic $matrix_dim = array('x' => 80, 'y' => 30); $captcha_dim = array('x' => 450, 'y' => 120); $distance = array('x' => 1, 'y' => 1, 'z' => 1); $metric = array('x' => 10, 'y' => 20, 'z' => 5); $offset = array('x' => 0, 'y' => -60); # matrice $matrix = imagecreatetruecolor($matrix_dim['x'], $matrix_dim['y']); $black = imagecolorexact($matrix, 0, 0, 0); $white = imagecolorexact($matrix, 255, 255, 255); imagefill($matrix, 0, 0, $white); # font calibri neni kvůli licenčním podmínkám připojen, použijte jakýkoliv svůj imagefttext($matrix, 20, 0, 2, 25, $black, './resources/calibri.ttf', 'ABCDE'); # výpočet bodů ve 3d $point = array(); for ($x = 0; $x < $matrix_dim['x']; $x++) { for ($y = 0; $y < $matrix_dim['y']; $y++) { $lightness = imagelightnessat($matrix, $x, $y); $point[$x][$y] = $perspective->get_projection(array('x' => $x * $metric['x'] + $distance['x'], 'y' => $lightness * $metric['y'] + $distance['y'], 'z' => ($matrix_dim['y'] - $y) * $metric['z'] + $distance['z'])); } } imagedestroy($matrix);
Zde je tedy vytvořen obrázek s černým textem ABCD na bílém pozadí. Poté je zjištěn jas každého pixelu (zjednodušeným výpočtem L složky z RGB barev pixelu, zjištěným funkcí imagecolorat()).
Projekce je situována tak, aby obrázek ležel na ploše „xz“ a složka jasu stoupala v ose „y“. Kladné vektory os chápané GD funkcemi se liší od obecného matematického modelu, takže například souřadnice „z“ odpovídá převrácené hodnotě pozice pixelu v ose „y“.
Nakonec jsou určeny pozice všech bodů v projekci lineární perspektivy a zapsány do pole. Všimněte si, že vstupní prostorové souřadnice jsou ještě upravovány vektorem vzdálenosti od počátku ($distance) a násobeny metrikou ($metric). Takto pak lze měnit pozice a rozměry výsledného objektu.
Postupme dále.
# obrázek captcha $captcha = imagecreatetruecolor($captcha_dim['x'], $captcha_dim['y']); # antialiasing čar - pro menší zátěž lze vypnout imageantialias($captcha, true); $black = imagecolorexact($captcha, 0, 0, 0); $white = imagecolorexact($captcha, 255, 255, 255); imagefill($captcha, 0, 0, $white); # vykreslení vrstevnic for ($x = 1; $x < $matrix_dim['x']; $x++) { for ($y = 1; $y < $matrix_dim['y']; $y++) { imageline($captcha, -$point[$x - 1][$y - 1]['x'] + $offset['x'], -$point[$x - 1][$y - 1]['y'] + $offset['y'], -$point[$x][$y]['x'] + $offset['x'], -$point[$x][$y]['y'] + $offset['y'], $black); } } # výstup header('Content-type: image/png'); imagepng($captcha);
Tohle už je hračka. Je vytvořen finální obrázek a mezi jednotlivými diagonálně sousedícími body jsou nakresleny úsečky pomocí funkce imageline().
Povšimněte si ještě funkce imageantialias(). Tuto je možné nepoužít a čáry pak nebudou vyhlazeny, což sníží datovou velikost obrázku i výpočetní nároky na jeho sestavení.
Implementace
Ukázkový obrázek je v té nejzákladnější formě. Reliéf je tvořen velkým množstvím bodů a je tak dost zřetelně čitelný. Pro výrazné zvýšení ochrany by určitě šlo zmenšit počet bodů, vybrat jiný font, přesunout kameru (viz třída linear_perspective) do ostřejšího úhlu, zvětšit metriku v ose „z“, nebo doplnit do matrice šum, který se pak projeví jako nerovnost plochy. Možností je mnoho.
Závěr
Řekl bych, že jako ochrana proti běžnému komentářovému spamu je (jakákoliv) obrázková CAPTCHA zbytečné obtěžování uživatelů. Na to zatím pořád bohatě stačí ochrany na bázi javascriptu. Ale na zabezpečení například autentizace nebo registrace, tedy tam, kde už reálně hrozí cílený útok, může být 3D text velmi účinný a minimálně obtěžující.
Na konec bych rád dodal, že ideu trojrozměrného textového reliéfu jsem rozhodně nevymyslel já. Nápad je to už poměrně starý. Viz třeba www.graphcomp.com/captcha/. Tento článek spíš přibližuje programovou realizaci.
- Autor: Martin Hozík
- Kategorie: PHP
- Vytvořeno: 7. června 2008
- Poslední úprava: 7. června 2008
- trvalý odkaz
Salko
Vážne fajn nápad, normálne uvažujem že tento 3D štýl zaradím do svojho kódu pri generovaní captcha obrázkov...Nejaký odkaz našiel aj Google: http://code.google.com/p/3dcaptcha/