Czy stronę WWW można zabezpieczyć przed ciekawskimi w taki sposób, by podejrzenie źródła, czyli kodu HTML, było niemożliwe? To pytanie nurtuje wielu użytkowników internetu. Próbując udzielić na nie odpowiedzi przeanalizujemy techniki, jakie mogą być zastosowane do zaszyfrowania witryny.
Ukrycie źródła strony
Chyba wszystkie przeglądarki internetowe mają opcję Pokaż źródło, po wykonaniu której na ekranie jest wyświetlany kod HTML oglądanej witryny. Internauci odwiedzający witrynę mogą przeanalizować jej zawartość. Co zrobić, jeśli nie chcemy ujawniać kodu HTML swojej strony?
Naszym zadaniem jest przygotowanie witryny, która będzie wyświetlana w przeglądarce internetowej w zwyczajny sposób, bez żadnego zabezpieczenia hasłem. Po wpisaniu adresu witryny w przeglądarce użytkownik powinien ujrzeć treść strony. Natomiast źródło strony ma być zaszyfrowane tak, by wykonanie operacji Pokaż źródło (lub zapisanie witryny na dysku i otworzenie jej edytorem) nie ujawniło kodu HTML.
Stosowana technika
Szyfrowanie źródła strony przypomina nieco tworzenie samorozpakowujących się archiwów. Zwykłe archiwum po spakowaniu jest wzbogacane o procedurę dekompresującą. Podobnie jest w przypadku szyfrowania witryny. Kod HTML najpierw szyfrujemy, a potem wzbogacamy o procedurę deszyfrującą. Tak przygotowaną stronę przekazujemy do przeglądarki. Przeglądarka otrzymaną witrynę automatycznie deszyfruje (bez wiedzy użytkownika) i przedstawia na ekranie w rozszyfrowanej postaci.
Za działanie to odpowiada przeglądarka, która po pobraniu strony, przed jej wyświetleniem, wykonuje wszystkie skrypty JavaScript zawarte na stronie. Jeśli zatem procedurę deszyfrującą napiszemy w JavaScript, to przeglądarka sama ją wykona bez udziału i wiedzy użytkownika.
Automatyczna deszyfracja strony WWW opiera się o dwie funkcje JavaScript: {stala}write(){/stala} oraz {stala}eval(){/stala}. Pierwsza z nich służy do umieszczenia w kodzie witryny napisu zadanego jako parametr. Wywołanie:
var napis = \"Hello World!\";
document.write(napis);
spowoduje umieszczenie w kodzie strony napisu Hello world!. Druga, eval(), powoduje interpretację kodu JavaScript przekazanego jako napis. Poniższy przykład:
var napis = \"function drukuj(){document.write(\'Tra la la la...\');};drukuj();\";
eval(napis);
jest równoważny zdefiniowaniu i wywołaniu funkcji {stala}drukuj(){/stala} (w dokumencie HTML pojawi się tekst Tra la la la…).
Powyższe funkcje mogą być użyte do ukrycia kodu strony, ponieważ posiadają parametr będący napisem, na podstawie którego generowana jest zawartość strony. Wystarczy zatem napis ten poddać jakiemukolwiek dwukierunkowemu przekształceniu, które powoduje, że zawartość napisu jest nieczytelna (przynajmniej dla człowieka).
Przykładem takiego przekształcenia jest zamiana znaków ASCII napisu na kod postaci %HH, gdzie HH oznacza szesnastkowy kod litery. Oto kilka przykładowych wartości:
a - %61
e - %65
H - %48
Pozostałe wartości znajdziemy w tabelce ASCII zawierającej kody szesnastkowe.
Przekształceniem odwrotnym do podanego jest oczywiście zamiana kodów %HH na znak ASCII.
Transformacje takie są wykonywane w JavaScripcie przez funkcje escape() oraz unescape(), zaś w PHP przez {stala}urlencode(){/stala}, {stala}urldecode(){/stala} i bliźniacze (różniące się kodowaniem spacji) {stala}rawurlencode(){/stala} i {stala}rawurldecode(){/stala}. Wszystkie wymienione funkcje kodujące, czyli {stala}escape(){/stala}, {stala}urlencode(){/stala} i {stala}rawurlencode(){/stala}, przekształcają wyłącznie znaki uznawane za niebezpieczne w adresach URL (np. *, ?, /, # itd.), pozostawiając litery niezmienione. Listing 1 przedstawia funkcję escape() napisaną w PHP, która koduje wszystkie znaki napisu w postaci kodów %HH.
function escape($AStr)
{
$wynik = \'\';
$ile = strlen($AStr);
for ($i = 0; $i < $ile; $i++) {
$wynik .= \'%\' . strtoupper(bin2hex($AStr[$i]));
}
return $wynik;
}
Stosując taki kod napis Hello world! przyjmie postać:
%48%65%6C%6C%6F%20%57%6F%72%6C%64%21
\"zaszyfrowany\" tekst %48%65... w napis oryginalny Hello world!) otrzymamy \"zaszyfrowaną\" stronę:
var napis = \"%48%65%6C%6C%6F%20%57%6F%72%6C%64%21\";
document.write(unescape(napis));
W podanym przykładzie na stronie WWW pojawi się tekst Hello world!, który nie jest widoczny w kodzie źródłowym strony.
Szyfrowanie witryny
Od rozwiązania opisanego w poprzednim punkcie tylko krok do zaszyfrowania całej strony WWW. Wystarczy do zmiennej {stala}$napis{/stala} wczytać zawartość pliku .html i usunąć wszelki kod HTML ze skryptu PHP. Rozwiązanie takie jest zawarte w przykładzie 8-1.
Zwróćmy uwagę na fakt, że w przeglądarce WWW możemy wywoływać funkcje JavaScript. Wpisując podczas oglądania przykładu 8-1 w polu Adres przeglądarki napis:
javascript:alert(unescape(napis))
ujrzymy kompletny kod HTML zaszyfrowanej strony! Nie ma możliwości zablokowania adresów URL o prefiksie javascript: w przeglądarce użytkownika, zatem musimy w inny sposób utrudnić wywołania rozpoczynające się od javascript:.
Jednym z rozwiązań jest dodanie na końcu skryptu JavaScript instrukcji:
napis = \'\';
Druga metoda, zawarta w przykładzie 8-2, polega na usunięciu zmiennych klucz, szyfr oraz napis w skrypcie JavaScript. Powoduje to, że nie mamy jak wkleić w pole adres przeglądarki wywołania funkcji. Próba skopiowania całego napisu rozpoczynającego się od:
document.writeln(unescape(des(integersToString(new Array(0x6b6c7563, 0x7a796b20)), ...
zakończy się niepowodzeniem, gdyż napis ten jest zbyt długi. (Oczywiście możemy kod strony zapisać na dysku i ręcznie wprowadzić zmienne.)
Jeszcze innym sposobem jest użycie wspomnianej funkcji {stala}eval(){/stala}. W przykładzie 8-3 w PHP dodajemy zmienną $dok, zawierającą kod JavaScript zakodowany funkcją {stala}escape(){/stala}:
$dok = \'document.writeln(unescape(des(integersToString(new Array(\' .
tablicadoJS($klucz) .
\')), integersToString(new Array(\' .
tablicadoJS($szyfr) .
\')), 0, 0)));\';
$docescape = escape($dok);
W JavaScripcie pojawia się wywołanie funkcji {stala}eval(){/stala} w połączeniu z funkcją {stala}unescape(){/stala} i przygotowaną zmienną {stala}$doescape{/stala}:
eval(unescape(\'\'));
W tak przygotowanym skrypcie po podejrzeniu źródła strony zobaczymy jedynie wywołanie funkcji {stala}eval(){/stala}.
Trzy przykłady oznaczone numerami 8-1, 8-2 oraz 8-3 możemy nazwać zaszyfrowanymi w pełnym tego słowa znaczeniu.
Sztuczki JavaScriptu
Powszechnie stosowanymi zabezpieczeniami kodu HTML są również różnego rodzaju sztuczki napisane w JavaScripcie. Do najpopularniejszych należą:
- blokada prawego klawisza myszki,
- blokada menu kontekstowego,
- pytanie o hasło dostępu do strony,
- sprawdzenie czy dostęp do pliku jest lokalny, czy zdalny,
- sprawdzenie rodzaju przeglądarki, ciasteczek i miejsca, z jakiego nadeszło odwołanie (pole referer zapytania HTTP).
Wszystkie te zabezpieczenia utrudniają w pewnym stopniu zajrzenie do źródła strony i w połączeniu z zaszyfrowaniem mogą skutecznie zniechęcić potencjalnych ciekawskich.
Przykłady demonstrujące wymienione sztuczki są opatrzone numerami od 9-1 do 9-5, zaś przykład 10-1 stanowi wzbogacenie szyfrowania strony algorytmem DES o powyższe blokady.
Obfuskacja kodu
Kolejnym popularnym chwytem utrudniającym analizę źródła strony jest \"zanieczyszczenie\" kodu HTML. Termin obfuskacja, pochodzący od angielskiego słowa obfuscate (zanieczyszczanie i ściemnianie), oznacza w żargonie informatycznym taki zapis kodu programu, by jego analiza była utrudniona. Innymi słowy należy wykonać wszystko przeciwnie do zaleceń notacji węgierskiej oraz technik formatowania kodu. Zmienne nazywamy idiotycznymi wyrazami, które trudno powtórzyć, instrukcje pętli organizujemy tak, by licznik nie obracał się od 1 do 5 ze skokiem o 1, a od -105 do -80, ze skokiem o -5, wprowadzamy instrukcje niczemu nie służące, a powodujące jedynie zamęt, i tak dalej... Oczywiście ręczne wykonywanie tego typu operacji byłoby bardzo podatne na błędy. Dlatego stosuje się do tego programy nazywane potocznie obfuskatorami.
Oprócz obfuskacji samego kodu JavaScript, niemal wszystkie programy ukrywające kod stron WWW wstawiają ogromne ilości białych znaków na początku i na końcu strony. Dodatkowo wszelkie linijki zawierające jakikolwiek tekst są poprzedzone ogromną ilością spacji lub tabulatorów. W ten sposób zaglądając do źródła mamy wrażenie, że plik jest pusty.
Ukrycie źródła strony: możliwe czy nie?
Czy źródło strony może być zabezpieczone w sposób pewny przed możliwością podejrzenia? Odpowiedź jest negatywna. Nie da się zabezpieczyć źródła strony WWW. Fakt, że przeglądarka wyświetla witrynę na ekranie użytkownika oznacza, że kod witryny jest dostępny dla przeglądarki. Potrzebna jest jedynie wiedza, w jaki sposób do niego dotrzeć.
Najprostszym sposobem złamania zabezpieczeń stosowanych przez wszystkie programy zawarte w tabeli 2 jest wykonanie operacji Zapisz jako w przeglądarce Firefox lub Netscape (najnowsza wersja). Przeglądarki Firefox i Netscape najpierw ściągają kod strony z serwera, następnie interpretują wszystkie zawarte w nich skrypty, tworząc drzewo elementów HTML odpowiadające bieżącej zawartości okna przeglądarki.
Podczas wykonywania operacji Zapisz jako zapisowi podlega nie oryginalny kod pobrany z serwera, a kod otrzymany po interpretacji skryptów. Przeglądarka najpierw deszyfruje witrynę, a dopiero później ją zapisuje. Utworzony plik zawiera oprócz żmudnie ukrytego kodu, także jego rozszyfrowaną postać. (Ciekawym efektem ubocznym takiego postępowania jest powielenie dwu-, a czasami i trzykrotne treści strony, wynikające z tego, że dokument zawiera tekst rozszyfrowany oraz procedurę rozszyfrowującą, która dopisuje kopię treści.)
Ponieważ na działanie przeglądarek nie mamy wpływu, można powiedzieć, że taki sposób wykonania operacji Zapisz jako skazuje na niepowodzenie wszelkie techniki ukrywania kodu strony w oparciu o JavaScript.
Jednak odszyfrowanie zabezpieczonej witryny, choć możliwe, nie musi być łatwe. Na pewno wymaga umiejętności programistycznych i dobrej znajomości JavaScript. Oznacza to, że zabezpieczenie będzie skuteczne w odniesieniu do dużej liczby internautów.
Tabela 4 przedstawia wyniki szyfrowania strony WWW siedmioma popularnymi programami. W tabeli zawarto zaszyfrowaną postać witryny, witrynę otrzymaną po wykonaniu operacji Zapisz jako w Firefoksie oraz ręcznie przeanalizowaną witrynę wzbogaconą o instrukcje JavaScript powodujące wyświetlenie okienek informacyjnych zawierających kod źródłowy witryny.
W identyczny sposób, po wykorzystaniu funkcji {stala}eval(){/stala} oraz {stala}unescape(){/stala} otrzymamy zaszyfrowaną stronę:
var napis = \'%66%75%6E%63%74%69%6F%6E%20%64...\';
eval(unescape(napis));
Podsumowując, procedura ukrycia kodu strony jest następująca:
- przygotowujemy witrynę, która ma zostać ukryta,
- witrynę tę kodujemy (na przykład stosując funkcję escape()),
- tworzymy stronę, która zawiera zakodowaną witrynę oraz procedurę rozszyfrowującą (np. funkcję {stala}unescape(){/stala}).
Po zajrzeniu do źródła witryny ujrzymy w nim - zamiast znaczników strony - zakodowaną treść witryny oraz procedurę odkodowującą. Oczywiście procedura odkodowująca, która jest napisana w JavaScripcie, musi być umieszczona pomiędzy odpowiednimi znacznikami HTML, na przykład:
Przekształcenie znaków ASCII w ich kody szesnastkowe nie ma nic wspólnego z szyfrowaniem. Jednak stosując opisaną strategię, możemy przygotować witryny, które będą zaszyfrowane w pełnym tego słowa znaczeniu.
Permutacja liter
Poznawszy główny sekret ukrywania zawartości witryny spróbujmy nieco skomplikować stosowany \"szyfr\". Pozamieniajmy litery w napisie.
Przygotowanie witryny \"zaszyfrowanej\" taką metodą opiera się o funkcje przekształcającą litery napisu. Poniższy fragment funkcji {stala}ZakodujLitere(){/stala} odpowiada za wzajemną zamianę liter parami, na przykład \"A\" w \"f\" oraz \"f\" w \"A\":
function ZakodujLitere($AChar)
{
switch ($AChar) {
case \"A\" : return \"f\";
case \"a\" : return \"F\";
case \"F\" : return \"a\";
case \"f\" : return \"A\";
...
default : return $AChar;
}
}
Przygotowując funkcję {stala}ZakodujLitere(){/stala} należy również przygotować funkcję odwrotną, {stala}DekodujLitere(){/stala}. Funkcję {stala}ZakodujLitere(){/stala} przygotowujemy w PHP, zaś {stala}DekodujLitere(){/stala} w JavaScripcie.
Na bazie funkcji {stala}ZakodujLitere(){/stala} oraz {stala}DekodujLitere(){/stala} implementujemy funkcje {stala}ZakodujNapis(){/stala} oraz {stala}DekodujNapis(){/stala}. Będą one odpowiedzialne za przekształcenie dowolnego napisu w szyfrogram (będący również napisem) oraz ponowne jego odkodowanie. Funkcja {stala}ZakodujNapis(){/stala} jest napisana w PHP, zaś {stala}DekodujNapis(){/stala}, podobnie jak {stala}DekodujLitere(){/stala} w JavaScripcie.
$zm = file_get_contents(\'przyslowia.html\');
$zakodowana = ZakodujNapis($zm);
W otrzymanej witrynie pewne litery zostały zamienione parami, zgodnie z definicją funkcji permutującej {stala}ZakodujLitere(){/stala}. Tak otrzymaną zmienną przesyłamy do skryptu JavaScript jako zmienną napis, poddajemy ją deszyfracji (wywołana w poniższym kodzie JavaScript funkcja {stala}DekodujNapis(){/stala}) i wstawiamy do dokumentu, wywołując funkcję write():
Działanie skryptu wymaga jedynie dołączenia kodu procedur deszyfrujących. Są one zapisane w pliku skrypty.js.
Oczywiście szyfr otrzymany przez permutowanie liter nie jest znacznie bezpieczniejszy od funkcji {stala}escape(){/stala} oraz {stala}unescape(){/stala}. Zanim jednak przejdziemy do faktycznego zaszyfrowania strony, rozwiążemy problem polskich znaków diakrytycznych, które w przykładzie 2-9 nie są wyświetlane poprawnie.
Polskie ogonki a funkcje escape() i unescape()
Funkcje JavaScript {stala}escape(){/stala} i {stala}unescape(){/stala} konwertują, oprócz znaków zabronionych w adresach URL, również polskie znaki diakrytyczne. Litery z ogonkami są konwertowane przez funkcję escape() do postaci %uhhhh, gdzie hhhh oznacza cyfry systemu szesnastkowego. Na przykład litera \"Ź\" jest zakodowana jako %u0179, zaś \"ą\" jako %u0105. Kod ten to szesnastobitowy unikod. Jeśli chcemy polskie znaki diakrytyczne umieszczać w treści szyfrowanych stron, to musimy przed dokonaniem szyfrowania przekształcić litery z ogonkami do unikodu.
Funkcja {stala}rawurlencode(){/stala} dostępna w PHP koduje polskie znaki diakrytyczne w standardowej postaci %HH, na przykład literę \"ą\" jako %B9. Zatem po zakodowaniu napisu w PHP funkcją {stala}rawurlencode(){/stala} (lub przedstawioną na listingu 1 {stala}escape(){/stala}), musimy dokonać konwersji kodów polskich liter z %HH na unikod %uhhhh.
Za konwersję taką są odpowiedzialne funkcje {stala}hex2unicodeWIN(){/stala} oraz hex2unicodeISO() zawarte w pliku hex2unicode.inc.php (przykłady oznaczone numerem 3 w tabeli 1).
Korzystając z powyższych funkcji należy stronę poddawaną szyfrowaniu przekształcić tak, by polskie literki z ogonkami były kodowane unikodem. Dzięki temu napisy odkodowane funkcją {stala}unescape(){/stala} (w JavaScripcie) będą zawierały poprawne polskie znaki diakrytyczne. W zależności od stosowanego kodowania strony wejściowej stosujemy funkcję {stala}hex2unicodeWIN(){/stala} lub {stala}hex2unicodeISO(){/stala}.
Strony z permutacjami liter w języku polskim
Łącząc opisane rozwiązania, czyli przykład 2-9 stosujący permutację liter oraz funkcje {stala}hex2unicodeISO(){/stala} i {stala}hex2unicodeWIN(){/stala}, przygotowujemy witrynę, która będzie zawierała polskie znaki.
Treść witryny zapisanej jako przykład 4-2 stanowi listing 2
Po odczytaniu pliku przyslowia.html oraz permutacji liter (funkcja {stala}ZakodujNapis(){/stala}) przekształcamy polskie znaki na unikod (funkcje {stala}rawurlencode(){/stala} oraz {stala}hex2unicodeISO(){/stala}):
$s = file_get_contents(\'przyslowia.html\');
$s = ZakodujNapis($s);
$s = hex2unicodeISO(rawurlencode($s));
Tak otrzymany napis przesyłamy do skryptu JavaScript w celu odkodowania:
echo \"kod = \\"$s\\";\";
Odkodowanie w języku JavaScript polega na wywołaniu funkcji {stala}unescape(){/stala} (zajmującej się między innymi konwersją polskich znaków z unikodu w znaki ASCII) oraz funkcji {stala}DekodujNapis(){/stala}.
Biblioteka mcrypt
Biblioteka mcrypt jest wieloplatformowym zestawem podprogramów realizujących szyfrowanie i deszyfrowanie danych. Funkcje zawarte w mcrypt umożliwiają między innymi operowanie szyframi DES, TripleDES, Blowfish oraz RIJNDAEL. Bibliotekę mcrypt, dostępną na platformę Windows w postaci plików .dll, instalujemy w PHP, dodając w pliku php.ini wpis:
extension=php_mcrypt.dll
oraz kopiując plik libmcrypt.dll do folderu systemowego C:\\Windows, zaś php_mcrypt.dll do folderu zawierającego rozszerzenia PHP (np. C:\\php\\extensions).
Szyfrowanie danych przy użyciu podprogramów zawartych w bibliotece mcrypt rozpoczynamy od ustalenia stosowanego algorytmu szyfrowania. Do tego stosujemy funkcje {stala}mcrypt_module_open (){/stala}, {stala}mcrypt_enc_get_iv_size(){/stala} oraz {stala}mcrypt_create_iv(){/stala}.
Poniższy przykład przygotowuje w zmiennej $td deskryptor, który jest później przekazywany do procedur szyfrujących i deszyfrujących dane. Zwróćmy uwagę, że klucz szyfrujący jest przekazany jako parametr do funkcji {stala}mcrypt_generic_init(){/stala}, zaś nazwa algorytmu szyfrowania (w przykładzie jest to tripledes) stanowi pierwszy parametr funkcji {stala}mcrypt_module_open (){/stala}:
$td = mcrypt_module_open(\'tripledes\', \'\', \'ecb\', \'\');
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
mcrypt_generic_init($td, $klucz, $iv);
Korzystając z utworzonego deskryptora {stala}$td{/stala} (poprawność tworzenia deskryptora możemy sprawdzić instrukcją if; w przypadku błędów funkcja {stala}mcrypt_generic_init(){/stala} zwraca wartość false) szyfrujemy i deszyfrujemy dane funkcjami {stala}mcrypt_generic(){/stala} oraz {stala}mdecrypt_generic(){/stala}:
$tekst_zaszyfrowany = mcrypt_generic($td, $tekst);
$tekst_rozszyfrowany = mdecrypt_generic($td, $tekst_zaszyfrowany);
Po zakończeniu użycia funkcji z biblioteki mcrypt zwalniamy zaalokowane zasoby:
mcrypt_module_close($td);
Szyfrowanie zawartości strony WWW algorytmem DES
Stosując bibliotekę mcrypt oraz implementację algorytmu DES napisaną w JavaScripcie i dostępną pod adresem http://www.laynetworks.com/des.htm możemy przystąpić do faktycznego zaszyfrowania treści witryny WWW.
Pracę rozpoczniemy od zaszyfrowania pojedynczego napisu. Kompletny skrypt zawierający takie rozwiązanie jest oznaczony numerem 7-1 w tabeli 1. W skrypcie PHP definiujemy dwie zmienne $klucz oraz $napis. Pierwsza z nich będzie kluczem szyfrowania, a druga szyfrowaną wiadomością. Wiadomość ta ma się pojawić w przeglądarce użytkownika odwiedzającego stronę WWW w rozszyfrowanej postaci, podczas gdy w kodzie HTML generowanej strony tekst wiadomości będzie zaszyfrowany. Oto definicje zmiennych:
$klucz = \"kluczyk \";
$napis = \" ... tajna wiadomosc...\";
$napis = hex2unicodeISO(rawurlencode($napis));
Oczywiście dzięki użyciu unikodu i funkcji {stala}rawurlencode(){/stala} oraz hex2unicodeISO() w kodowanej wiadomości mogą wystąpić polskie ogonki. Następnie tworzymy deskryptor {stala}$td{/stala} umożliwiający szyfrowanie i deszyfrowanie danych algorytmem DES za pomocą klucza {stala}$klucz{/stala}:
$td = mcrypt_module_open(MCRYPT_DES, \'\', \'ecb\', \'\');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $klucz, $iv);
Korzystając z deskryptora {stala}$td{/stala} oraz funkcji {stala}mcrypt_generic(){/stala} szyfrujemy zmienną {stala}$napis{/stala}:
$szyfr = mcrypt_generic($td, $napis);
To kończy działanie po stronie PHP. Pozostało przekazanie zmiennej $szyfr do JavaScriptu. Ponieważ implementacja algorytmu DES zawarta pod adresem http://www.laynetworks.com/des.htm operuje danymi w postaci tablic 32 bitowych liczb całkowitych, musimy zmienną {stala}$szyrf{/stala} oraz klucz $klucz przekształcić do takiej postaci. Za zadanie to odpowiada funkcja o nazwie {stala}tablicadoJS(){/stala}. Jej działanie możemy prześledzić analizując przykłady 6-1 oraz 6-2.
Kod JavaScript odpowiedzialny za deszyfrowanie strony zawiera jedynie definicje dwóch zmiennych - klucz oraz szyfr. Zmienne te są tablicami 32-bajtowych liczb całkowitych kodujących napisy będące kluczem oraz szyfrogramem:
var klucz = integersToString(new Array());
var szyfr = integersToString(new Array());
Zmienne te przekazujemy do funkcji {stala}des(){/stala} (funkcja ta stanowi sedno implementacji algorytmu DES z rozwiązania dostępnego na stronie http://www.laynetworks.com/des.htm). Po zdeszyfrowaniu wiadomość jest umieszczana na stronie funkcją {stala}write(){/stala}:
var napis = des(klucz, szyfr, 0, 0);
document.writeln(unescape(napis));
Przykład 7-1 stanowi szkielet faktycznego szyfrowania kodu HTML.