2006 06 RSA w PHP chronimy nasze dane przy użyciu kryptografii asymetrycznej [Kryptografia](1)

background image

Bezpieczeństwo

www.phpsolmag.org

32

PHP Solutions Nr 6/2006

RSA w PHP

Bezpieczeństwo

www.phpsolmag.org

33

PHP Solutions Nr 6/2006

N

ieodłączną częścią każdego me-
chanizmu logowania użytkowni-
ków jest przesyłanie hasła wpi-

sanego na komputerze klienta (w przy-
padku aplikacji webowych – w przeglą-
darce internetowej) na serwer, na którym
(przeważnie w bazie danych) przechowy-
wane są skróty MD5 haseł (zob. Ramka
Podstawy MD5). Ponieważ te skróty są
jednokierunkowe i odtworzenie haseł na
ich podstawie nie jest możliwe, więc kra-
dzież bazy nie da sprawcy wielu możli-
wości włamania. Poważnym problemem
jest natomiast wspomniane już przesyła-
nie hasła jako czystego tekstu: wystarczy,
aby intruz podsłuchał transmisję pomiędzy
klientem a serwerem (np. za pomocą snif-
fera), a będzie mógł bez problemu doko-
nać agresji.

W poprzednim numerze PHP So-

lutions, w artykule Kryptografia w PHP
prezentowaliśmy rozwiązanie tego pro-
blemu przy użyciu algorytmu HMAC-
MD5 po stronie klienta na wpisywanym

Zabezpieczenie aplikacji PHP przed włamaniami

to nie wsystko: jeżeli przesyłamy dane czystym

tekstem, zawsze może się znależć ktoś,

kto je przechwyci podsłuchując transmisję

w Internecie. Aby zadbać o bezpieczeństwo

danych, musimy więc sięgnąc po kryptografię

asymetryczną RSA, która daje obecnie

największą pewność jego ochrony i zastosować

ją zarówno po stronie serwera, jak i klienta.

haśle. Algorytm ten (w naszym przy-
padku zaimplementowany w języku Ja-
vaScript i działający na przeglądarce
internetowej) zamienia hasło na spe-
cjalny hash, podczas generowania któ-
rego używany jest również tajny klucz.
Następnie, otrzymany skrót jest wysy-
łany do serwera, gdzie – podobnie jak
przy sprawdzaniu hasła przesyłanego
czystym tekstem – jest porównywany
z hashami zapisanymi w bazie danych.
Korzystając z tej metody wyeliminuje-
my ryzyko podsłuchu (nie przesyłamy

RSA w PHP: chronimy nasze

dane przy użyciu kryptografii

asymetrycznej

Kamil Karczmarczyk

W SIECI

1. http://pear.php.net/package/

Crypt_RSA/ – klasa

Crypt_RSA (PHP)

2. http://pear.php.net/package/

Crypt_Blowfish/ – klasa

Crypt_Blowfish (PHP)

3. http://ohdave.com/rsa/ – Im-

plementacja RSA (JS)

4. http://en.wikipedia.org/wiki/

RSA – Opis algorytmu RSA

5. http://en.wikipedia.org/wiki/

Blowfish_(cipher) – Opis

algorytmu Blowfish

6. http://advajax.anakin.us/

– Obiekt advancedAJAX

Stopień trudności: ll

l

Co należy wiedzieć...

Należy znać podstawy programowania

w PHP oraz AJAX. Przydatna będzie też

podstawowa wiedza na temat kryptografii.

Co obiecujemy...

Pokażemy zasadę działania algorytmu

asymetrycznego RSA i zademonstruje-

my, jak przy jego użyciu stworzyć system

bezpiecznego logowania.

background image

Bezpieczeństwo

www.phpsolmag.org

32

PHP Solutions Nr 6/2006

RSA w PHP

Bezpieczeństwo

www.phpsolmag.org

33

PHP Solutions Nr 6/2006

samego hasła, lecz jego skrót), ale mo-
żemy jej użyć wyłącznie wobec już ist-
niejących haseł, których skróty zostały
utworzone i zapisane w bazie na ser-
werze. W jaki sposób więc przeprowa-
dzimy proces rejestracji nowego kon-
ta na serwerze? Musimy w końcu prze-
słać na serwer informacje o nowym ha-
śle: z oczywistych powodów nie chce-
my tego robić przy użyciu czystego
tekstu; przesyłanie skrótu takiego ha-
sła również nie uchroni nas przed nie-
bezpieczeństwem podsłuchu: ktoś, kto
w tym momencie przechwyci ten skrót
(rozpozna, że chodzi o dodawanie no-
wego konta np. po danych wysyłanych
z formularza), będzie mógł go potem
zwyczajnie wykorzystać przy logowa-
niu się na serwerze. Szyfrowanie da-
nych za pomocą klucza symetryczne-
go (np.3DES lub twofish) również nie
wchodzi w grę, gdyż taki klucz musiał-
by być znany zarówno klientowi, jak i
serwerowi, co oznacza konieczność je-
go transmisji przez Internet oraz czy-
ni go podatnym na podsłuch. Jedy-
nym sensownym rozwiązaniem proble-
mu zabezpieczenia hasła będzie uży-
cie asymetrycznego algorytmu szy-
frującego RSA. Algorytm ten działa w
oparciu o dwa klucze: publiczny (który
jest ogólnie dostępny) i prywatny (do-
stępny wyłącznie na serwerze). Wię-
cej informacji na temat algorytmu RSA
zamieściliśmy w Ramce RSA: Zasada
działania
.

Tworzymy system

bezpiecznego logowania

dla aplikacji „Notatki

osobiste”

Pokażemy teraz, jak wykorzystać algorytm
szyfrujący RSA w PHP, tworząc system
bezpiecznego logowania dla aplikacji
Notatki osobiste, która będzie służyła jako
nasz osobisty notatnik online.

Założenia

Chcemy, aby nasza aplikacja posiadała
system logowania poszczególnych użyt-
kowników oraz możliwość dodawania no-
wych kont. Każdy posiadacz konta będzie
mógł wyświetlać swoje notatki, a także do-
dawać nowe. Cała komunikacja pomiędzy
klientem a serwerem będzie szyfrowana.

Przygotowania

Tworząc nasz system bezpiecznego
logowania skorzystamy z gotowych
implementacji algorytmów szyfrowania,
zarówno tych działających po stronie
serwera (w PHP), jak i klienta (w języku

JavaScript). W pierwszym przypadku,
do szyfrowania za pomocą RSA posłuży
nam klasa Crypt_RSA z repozytorium
PEAR (pear.php.net). Po stronie klienta
użyjemy natomiast implementacji algo-
rytmu RSA w języku JavaScript umiesz-
czonej na stronie http://ohdave.com/rsa/.
Musimy z niej pobrać pliki: BigInt.js, Bar-
rett.js
oraz RSA.js. Wymianę danych
będziemy obsługiwać przy pomocy
technologii AJAX, a konkretnie projektu
advAJAX (zarówno o tym projekcie, jak
i o technologii AJAX pisaliśmy w nume-
rze 1/2006). Pobieramy więc plik adva-
jax.js
ze strony http://advajax.anakin.us
i zabieramy się do pracy.

Rejestracja kont

Obsługą procesu rejestracji nowych kont
zajmą się trzy pliki:

Ÿ

register.php – będzie odpowiadał za

wyświetlenie formularza zakładania
konta wraz z wygenerowanym wcze-
śniej kluczem publicznym,

Podstawy MD5

MD5 jest algorytmem haszującym, zwa-

nym również jednokierunkową funkcją

skrótu. W wyniku jego działania, w

oparciu o podstawione dane powstaje

unikalny 128-bitowy skrót. Odtworze-

nie danych na jego podstawie nie jest

możliwe. Unikalność i jednokierunko-

wość działania MD5 umożliwia jego za-

stosowanie np. przy sprawdzaniu haseł

(na serwerze zamieszczane są jedynie

skróty haseł, aby uniemożliwić prze-

chwycenie samych haseł w razie kra-

dzieży danych), podpisywaniu plików

– umieszczanym w wielu repozytoriach

plikom towarzyszą skróty MD5: oblicza-

jąc skrót pobranego pliku i porównując

go z tym zamieszczonym na serwerze

możemy sprawdzić, czy archiwum nie

jest uszkodzone (to samo da się zasto-

sować np. przy porównywaniu zawar-

tości wypalonej płyty CD lub DVD z jej

obrazem, choć trwa to dość długo).

RSA: Zasada działania

RSA to pierwszy (wynaleziony w 1977 roku) i obecnie najpopularniejszy algorytm szyfro-

wania asymetrycznego, używany powszechnie np. w handlu elektronicznym czy w celu

podpisywania emaili. Zasadę działania algorytmu RSA przedstawiamy na Rysunku 1. Je-

go idea (jak każdego szyfru asymetrycznego) polega na użyciu dwóch k luczy: publiczne-

go i prywatnego. Oba z nich są generowane przez odbiorcę wiadomości, po czym klucz

publiczny jest jawnie przesyłany nadawcy wiadomości, może też być zamieszczony np. na

stronie WWW do pobrania. Nadawca szyfruje tekst za pomocą klucza publicznego i wysy-

ła go odbiorcy. Zaszyfrowany tekst można z kolei odszyfrować tylko kluczem prywatnym,

który posiada odbiorca. Nie wnikając w teorię matematyczną, która leży u podstaw RSA,

warto zapamiętać, że klucz publiczny składa się z dwóch części: wykładnika publicznego

(ang. public exponent) i modułu (ang. modulus), a klucz prywatny – z wykładnika prywat-

nego (ang. private exponent) i tego samego modułu – te informacje będą nam potrzebne

później, gdy będziemy korzystali z klas PEAR-owych do obsługi RSA.

Rysunek 1.

Schemat działania RSA

background image

RSA w PHP

Bezpieczeństwo

www.phpsolmag.org

34

PHP Solutions Nr 6/2006

Ÿ

register.js – będzie w nim następo-

wało szyfrowanie danych zawartych
w formularzu oraz ich wysyłanie na
serwer,

Ÿ

register2.php – w tym pliku nastą-

pi odszyfrowanie danych i założenie
konta.

Generowanie kluczy

Spójrzmy na Listing 1, na którym za-
mieściliśmy plik register.php. Zacznie-
my od wygenerowania pary kluczy
(publicznego i prywatnego) poprzez
utworzenie obiektu

$key_pair

klasy

Crypt_RSA_KeyPair

oraz użycie jej me-

tod

getPublicKey()

i

getPrivateKey()

.

Oba wygenerowane klucze stanowią
osobne obiekty, z których następnie
wydobywamy oba wspomniane wcze-
śniej (zob. Ramka RSA: zasada dzia-
łania
) wykładniki (

getExponent()

) oraz

moduł (

getModulus()

). Następnie se-

rializujemy (serialize()) i zapisujemy w
sesji obiekt

$key_pair

do późniejszego

wykorzystania oraz konwertujemy klucz
publiczny (a właściwie jego wykładnik i
moduł) z postaci binarnej na wartość
szesnastkową (

bin2hex()

), ponieważ

algorytm RSA, z którego będziemy ko-
rzystać po stronie przeglądarki, wyma-
ga podania danych dotyczących klucza
właśnie w takim formacie. Po wykona-
niu tych operacji przechodzimy do ge-
nerowania formularza dodawania kon-
ta (kod HTML). Jedynym dynamicznym
elementem, który umieścimy w tym ko-
dzie, będzie osadzony w prezentowa-
nym pliku fragment skryptu JavaScript,
który odpowiada za dołączenie plików:
advajax.js, BigInt.js, Barrett.js i RSA.js
oraz utworzenie zmiennych JavaScript

enc_exp

i

modulus

, przechowujących

wartość wykładnika publicznego (szy-
frującego) i modułu.

Szyfrowanie

Spójrzmy teraz na Listing 2, na którym
przedstawiamy napisany w języku Ja-
vaScript obiekt

updateObjects()

(pa-

miętajmy, że w JavaScript nie ma klas,
tylko pojedyncze obiekty, definiowane
analogicznie, jak funkcje). Będzie on
wywoływany przy wystąpieniu zdarze-
nia

onload

zdefiniowanego w znacz-

niku

<body>

, czyli po każdym załado-

waniu strony WWW umieszczonej po-
między

<body>

a

</body>

. Wewnątrz

updateObjects()

tworzymy parę kluczy

RSA, czyli obiekt

RSAKeyPair

, na pod-

Listing 1.

Plik register.php – generowanie kluczy i wyswietlenie formularza

<?

php

session_start

()

;

// generowanie pary kluczy

require_once

'Crypt/RSA.php'

;

$key_pair

=

new

Crypt_RSA_KeyPair

(

512

)

;

$public_key

=

$key_pair

-

>

getPublicKey

()

;

$private_key

=

$key_pair

-

>

getPrivateKey

()

;

$enc_exp

=

$public_key

-

>

getExponent

()

;

$dec_exp

=

$private_key

-

>

getExponent

()

;

$modulus

=

$public_key

-

>

getModulus

()

;

// zapamiętanie danych do późniejszego dekodowania

$_SESSION

[

'rsa'

]

=serialize

(

$key_pair

)

;

// konwersja danych do szyfrowania na kod szesnastkowy (heksadecymalny)

$enc_exponent

= bin2hex

(

$enc_exp

)

;

$mod

= bin2hex

(

$modulus

)

;

?>
<

html

>

<

head

>

<

title

>

MyNotes - registration

<

/title

>

<

meta http-equiv=

"Content-type"

content=

"text/html; charset=utf-8"

/

>

<

script type=

"text/javascript"

src=

"advajax.js"

><

/script

>

<

script type=

"text/javascript"

src=

"BigInt.js"

><

/script

>

<

script type=

"text/javascript"

src=

"Barrett.js"

><

/script

>

<

script type=

"text/javascript"

src=

"RSA.js"

><

/script

>

<!-- skrypt obsługujący formularz za pomocą AJAX -->

<

script type=

"text/javascript"

src=

"register.js"

><

/script

>

<

script type=

"text/javascript"

>

var

enc_exp =

"<?=

$enc_exponent

?>"

;

var

modulus =

"<?=

$mod

?>"

;

<

/script

>

<

/head

>

<

body onload=

"updateObjects()"

>

<

b

>

MyNotes - Registration

<

/b

><

br/

>

<

form method=

"post"

action=

"register2.php"

id=

"registerForm"

>

<

label for=

"username"

>

Login:

<

/label

>

<

input type=

"text"

name=

"username"

id=

"username"

/

><

br/

>

<

label for=

"password"

>

Password:

<

/label

>

<

input type=

"password"

name=

"password"

id=

"password"

/

><

br/

>

<

label for=

"name"

>

e-mail:

<

/label

>

<

input type=

"text"

name=

"email"

id=

"email"

/

><

br/

>

<

label for=

"name"

>

Name:

<

/label

>

<

input type=

"text"

name=

"name"

id=

"name"

/

><

br/

>

<

label for=

"surname"

>

Surname:

<

/label

>

<

input type=

"text"

name=

"surname"

id=

"surname"

/

><

br/

>

<

input type=

"submit"

value=

"Register"

id=

"submitBtn"

/

>

<

/form

>

<

div style=

"margin-top: 10px"

id=

"response"

><

/div

>

<

/body

>

<

/html

>

background image

RSA w PHP

Bezpieczeństwo

www.phpsolmag.org

35

PHP Solutions Nr 6/2006

stawie publicznego wykładnika i modu-
łu. Prywatny wykładnik nie jest nam po-
trzebny, więc wpisujemy 0. Następnie
wdrażamy obsługę formularza za po-
mocą obiektu

advAJAX

. Metoda

assign

pobiera (jako parametr) nazwę formula-
rza oraz obiekt zawierający metody je-
go obsługi. Funkcja

OnInitialization

jest wykonywana jeszcze przed wysła-
niem formularza. To w niej następuje

Listing 2.

Plik register.js – szyfrowanie i wysyłanie danych

function

updateObjects

() {

var

key;

key =

new

RSAKeyPair

(

enc_exp,

0

,modulus

)

;

function

$

(

id

) {

return

document.getElementById

(

id

)

;

}

advAJAX.assign

(

$

(

"registerForm"

)

,

{

onInitialization :

function

(

obj

) {

// szyfrowanie danych z formularza

obj.parameters

[

"username"

]

=encryptedString

(

key,obj.parameters

[

"username"

])

;

obj.parameters

[

"password"

]

=encryptedString

(

key,obj.parameters

[

"password"

])

;

obj.parameters

[

"email"

]

=encryptedString

(

key,obj.parameters

[

"email"

])

;

obj.parameters

[

"name"

]

=encryptedString

(

key,obj.parameters

[

"name"

])

;

obj.parameters

[

"surname"

]

=encryptedString

(

key,obj.parameters

[

"surname"

])

;

}

,

onSuccess :

function

(

obj

) {

$

(

"response"

)

.innerHTML=obj.responseText;

}

,

onError :

function

() {

alert

(

"Can't connect to server."

)

;

}

})

;

}

Listing 3.

Plik register2.php – deszyfrowanie i zapisanie danych nowego usera

<?

php

session_start

()

;

require_once

'Crypt/RSA.php'

;

// odczytanie przechowywanego obiektu (kluczy)

$rsa_keys

= unserialize

(

$_SESSION

[

'rsa'

])

;

$priv

=

$rsa_keys

-

>

getPrivateKey

()

;

$rsa_obj

=

new

Crypt_RSA;

// deszyfrowanie

$username

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'username'

])

,

$priv

)

;

$password

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'password'

])

,

$priv

)

;

$email

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'email'

])

,

$priv

)

;

$name

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'name'

])

,

$priv

)

;

$surname

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'surname'

])

,

$priv

)

;

// tworzenie nowego konta

$user

=

new

user;

$result

=

$user

-

>

register

(

$username

,

$password

,

$email

,

$name

,

$surname

)

;

if

(

$result

)

{

echo

"Your account are successfully created."

;

}

else

{

echo

"error: your account can't created!"

;

}

?>

Listing 4.

Funkcja hex2bin

function

hex2bin

(

$hex

)

{

$str

=

""

;

for

(

$i

=

0

;

$i

<

strlen

(

$hex

)

;

$i

=

$i

+

2

)

{

$str

.=

chr

(

hexdec

(

substr

(

$hex

,

$i

,

2

)))

;

}

return

$str

;

}

szyfrowanie przesyłanych danych, czyli
wartości wszystkich pól formularza (na-
zwy użytkownika, hasła, adresu ema-
il, imienia i nazwiska) za pomocą al-
gorytmu RSA. Funkcja

onSuccess

wy-

świetla wewnątrz znacznika

<div>

(o

id=”response”

) dane zwrócone przez

plik register2.php, do którego wysłali-
śmy wprowadzone w formularzu war-
tości.

Deszyfrowanie i tworzenie konta

Przejdźmy do omówienia zawartości
wspomnianego już pliku register2.php
(Listing 3). Otrzymuje on przekazane za
pomocą advAJAX dane z formularza,
które musimy teraz odszyfrować. Posłu-
żymy się do tego zapisanym wcześniej
w sesji jako

rsa

obiektem

$key_pair

,

który nazwiemy

$rsa_keys

i zdeseria-

lizujemy (

unserialize()

). Następnie

wydobędziemy z tego obiektu klucz
prywatny, który także będzie obiektem
o nazwie

$priv

. Potem utworzymy nowy

obiekt

$rsa_obj

klasy

Crypt_

RSA i wy-

wołujemy jego metodę

DecryptBinary()

odpowiedzialną

za

deszyfrowanie

danych (każdego z przesłanych pól for-
mularza z osobna). Metoda ta przyjmuje
dwa parametry: zaszyfrowany tekst oraz
utworzony przez nas wcześniej klucz
prywatny

$priv

(obiekt klasy

Crypt_RSA_

KeyPair

). Ponieważ dane pochodzące

z formularza zostały po zaszyfrowaniu
przekonwertowane na system szesnast-
kowy, więc musimy je przywrócić do
formy binarnej przy użyciu funkcji he-
x2bin(), którą napiszemy sami (Listing 4),
gdyż nie została ona zaimplementowana
w PHP.

Mając odszyfrowane dane użyt-

kownika, możemy przystąpić do jego
rejestracji w serwisie. Robimy to np.
przy pomocy klasy

user

, której imple-

mentację pominęliśmy, gdyż nie jest
ona istotna dla ukazania technik kryp-
tograficznych.

Kryptografia hybrydowa

Jako kryptografia hybrydowa rozumiane
jest jednoczesne użycie kryptografii sy-
metrycznej i asymetrycznej. Dotychczas
szyfrowaliśmy dane tylko w jednym kie-
runku: od użytkownika do serwera. Aby
zrealizować nasz projekt, będziemy jed-
nak potrzebowali szyfrowania dwukierun-
kowego, gdyż w jedną stronę będziemy
wysyłali nasz login i hasło oraz dodawali
nowe notatki, a w drugą – wyświetlali ist-
niejące notatki. Zabezpieczenie danych
przy tych czynnościach za pomoca sa-
mego RSA byłoby trudne, wykorzystamy
więc dodatkowo symetryczny algorytm
blowfish.

Przygotowania

Będziemy więc potrzebowali implemen-
tacji algorytmu blowfish. W PHP posłu-
żymy się do tego klasą Crypt_Blowfish
z repozytorium PEAR. Po stronie prze-

background image

RSA w PHP

Bezpieczeństwo

www.phpsolmag.org

36

PHP Solutions Nr 6/2006

glądarki internetowej, obsługą blowfisha
zajmie się plik encrypt.js, który możemy
pobrać ze strony www.farfarfar.com lub
bezpośrednio z http://limak.blg.pl/crypto/
encrypt.js
. Cała nasza aplikacja, podob-
nie jak to było w przypadku rejestracji,
będzie się składała z trzech plików:
index.php, index.js i index2.php, których
zadanie jest analogiczne do plików z po-
przedniego przykładu.

Logowanie

Spójrzmy na Listing 5. Przedstawia-
my na nim fragment pliku index.php
– w miejscu, w którym różni się on
od register.php. Dołączamy w nim też
skrypt encrypt.js w języku JavaScript,
który odpowiada za szyfrowanie i de-
szyfrowanie algorytmem blowfish. Tym
razem zagnieździmy nasz formularz
wewnątrz znacznika

<div>

, któremu

nadamy id

html

: później będziemy dy-

namicznie zastępowali ten fragment
kodu inną treścią.

Obsługa AJAX

Różnice między plikiem index.js a regi-
ster.js
są znacznie większe, niż pomię-
dzy index.php a register.php. Na Listin-
gu 6 prezentujemy obsługę praktycznie
całej szyfrowanej wymiany pomiędzy
plikami index.php i index2.php. Tworzy-
my w nim zarówno klucz asymetrycz-
ny dla algorytmu RSA, jak i losowy ciąg
znaków będący kluczem symetrycznym
blowfish.

Następnie korzystamy ze znanego

już nam obiektu

advAJAX

, który wystę-

puje trzykrotnie. Pierwszy raz odwołu-
je się do formularza

loginForm

(

advA-

JAX.assign

) i za pomocą RSA szyfru-

je login, hasło oraz dodatkowo wyge-
nerowany klucz blowfish, a następnie
przekazuje je do pliku login2.php. Od
tej pory, po otrzymaniu klucza blow-
fish przez serwer, wymiana szyfrowa-
nych danych odbywa się przy pomo-
cy algorytmu symetrycznego. RSA było
potrzebne jedynie do przesłania syme-
trycznego klucza.

Gdy teraz będziemy chcieli wyświe-

tlić wszystkie nasze notatki, wywoła-
my funkcję

goto()

z parametrem

note

,

aby w odpowiedzi z pliku index2.php
otrzymać zaszyfrowany fragment ko-
du odpowiedzialny za ich wyświetle-
nie. To, w jaki sposób plik index2.php
szyfruje dane, widzimy na Listingu 7.
Aby odpowiednio zaszyfrować i odszy-

Listing 5.

Formularz logowania

// ...

<

script type=

"text/javascript"

src=

"encrypt.js"

><

/script

>

//...

<

body onload=

"updateObjects()"

>

<

b

>

MyNotes - Your own on-line notices

<

/b

><

br/

>

<

div id=

"html"

>

<

form method=

"post"

action=

"index2.php"

id=

"loginForm"

>

<

label for=

"username"

>

Login:

<

/label

>

<

input type=

"text"

name=

"username"

id=

"username"

/

><

br/

>

<

label for=

"password"

>

Password:

<

/label

>

<

input type=

"password"

name=

"password"

id=

"password"

/

><

br/

>

<

input type=

"hidden"

name=

"blowfish"

id=

"blowfish"

value=

""

/

>

<

input type=

"submit"

value=

"Login"

id=

"submitBtn"

/

>

<

/div

>

Listing 6.

index.js – obsługa AJAX

function

updateObjects

() {

// tworzenie klucza publicznego

var

key;

key =

new

RSAKeyPair

(

enc_exp,

0

,modulus

)

;

// tworzenie klucza symetrycznego

var

blowfishKey =

""

;

var

chars=

"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

var

i;

for

(

i=

0

; i<

25

; i++

) {

blowfishKey += chars.charAt

(

Math.floor

(

Math.random

()

*

62

))

}

document.forms

[

"loginForm"

]

.elements

[

"blowfish"

]

.value=blowfishKey;

function

$

(

id

) {

return

document.getElementById

(

id

)

;

}

advAJAX.assign

(

$

(

"loginForm"

)

,

{

onInitialization :

function

(

obj

) {

// szyfrowanie danych z formularza (RSA))

obj.parameters

[

"username"

]

= encryptedString

(

key, obj.parameters

[

"username"

])

;

obj.parameters

[

"password"

]

= encryptedString

(

key, obj.parameters

[

"password"

])

;

obj.parameters

[

"blowfish"

]

= encryptedString

(

key, blowfishKey

)

;

}

,

onSuccess :

function

(

obj

) {

// deszyfrowanie blowfish

$

(

"html"

)

.innerHTML = secureDecrypt

(

obj.responseText, blowfishKey

)

;

}

})

;

advAJAX.assign

(

$

(

"addNoteForm"

)

,

{

onInitialization :

function

(

obj

) {

// szyfrowanie blowfish

obj.parameters

[

"title"

]

= secureEncrypt

(

obj.parameters

[

"title"

]

,

blowfishKey

)

;

obj.parameters

[

"note"

]

= secureEncrypt

(

obj.parameters

[

"note"

]

,

blowfishKey

)

;

}

,

onSuccess :

function

(

obj

) {

$

(

"html"

)

.innerHTML = obj.responseText;

}

})

;

}

function goto

(

page, pageid=

0

) {

advAJAX.post

({

url :

"index2.php?page="

+page+

"&pageid="

+pageid,

onSuccess :

function

(

obj

) {

$

(

"html"

)

.innerHTML = secureDecrypt

(

obj.responseText, blowfishKey

)

;

}

})

;

}

background image

RSA w PHP

Bezpieczeństwo

www.phpsolmag.org

37

PHP Solutions Nr 6/2006

frować dane, po stronie przeglądarki
używamy w skrypcie JavaScript funk-
cji

secureEncrypt()

i

secureDecrypt()

,

natomiast w PHP wykorzystujemy PE-
AR-ową klasę

Crypt_Blowfish

, która

jest bardzo intuicyjna i prosta w uży-
ciu. Z listingów możemy wywniosko-
wać, że sam proces przesyłania nowej
notatki w formie zaszyfrowanej (obiekt
advAJAX z parametrem odwołującym
się do formularza

AddNoteForm

) oraz

jej deszyfrowanie z poziomu PHP jest
praktycznie identyczny, jak w przypad-
ku pobierania istniejącej notatki z ser-
wera, tyle że kolejność wykonywania
czynności jest odwrotna.

Podsumowanie

W przedstawionej aplikacji pokazali-
śmy, w jaki sposób można skorzystać
z dwóch metod kryptograficznych (asy-
metrycznej i symetrycznej) oraz poda-
liśmy przykładowe zastosowanie tych
technik. Potęga RSA w połączeniu z
prostotą języka PHP jak też z całkiem
niezłą funkcjonalnością JavaScrip-
tu umożliwia tworzenie naprawdę bez-
piecznych aplikacji, które będą odpor-
ne na podsłuch i przechwytywanie da-
nych.

Zachęcamy do korzystania z krypto-

grafii we własnych projektach – zwłasz-
cza tam, gdzie poufność przesyłanych i
gromadzonych danych jest szczególnie
istotna, poczynając od aplikacji do gro-
madzenia prywatnych notatek i syste-
mów przekazywania wiadomości osobi-
stych, poprzez narzędzia używane we-
wnątrz firmy (np. do zarządzania pro-
jektem, danymi księgowymi czy biz-
nesplanem), po dostępne dla tysię-
cy użytkowników jednocześnie syste-
my e-commerce, takie jak sklepy inter-
netowe czy pasaże aukcyjne. Na pohy-
bel intruzom!

n

Kamil Karczmarczyk jest uczniem Li-

ceum Ogólnokształcącego. Od kilku lat

hobbystycznie zajmuje się programowa-

niem, między innymi w PHP. Interesuje

się bezpieczeństwem sieci, kryptografią

oraz matematyką.

Kontakt z autorem:

limak@mmj.pl

Listing 7.

Zawartość pliku index2.php

<?

php

session_start

()

;

require_once

'Crypt/RSA.php'

;

require_once

'Crypt/Blowfish.php'

;

echo

"<a href=\"javascript:goto('notes')\">my notes</a> | "

;

echo

"<a href=\"javascript:goto('addnote')\">add note</a> | "

;

echo

"<a href=\"javascript:goto('logout')\">logout</a><br/><br/>"

;

if

(

!

isset

(

$_GET

[

'page'

]))

{

// logowanie

$rsa_keys

= unserialize

(

$_SESSION

[

'rsa'

])

;

$priv

=

$rsa_keys

-

>

getPrivateKey

()

;

$rsa_obj

=

new

Crypt_RSA;

$username

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'username'

])

,

$priv

)

;

$password

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'password'

])

,

$priv

)

;

$blowfishKey

=

$rsa_obj

-

>

decryptBinary

(

hex2bin

(

$_POST

[

'blowfish'

])

,

$priv

)

;

$_SESSION

[

'username'

]

=

$username

;

$_SESSION

[

'password'

]

=

$password

;

$_SESSION

[

'blowfishKey'

]

=

$blowfishKey

;

$user

=

new

user

(

$username

,

$password

)

;

$notes

=

$user

-

>

getNotes

()

;

$html

=

""

;

foreach

(

$notes

as

$note

)

{

$html

.="

<

a href=\

"javascript:goto('note','"

.$note[

'id'

].

"')\"

>

";

$html

.=

$note

[

'title'

]

."

<

/a

><

br/

>

";

}

$blowfish

=

new

Crypt_Blowfish

(

$blowfishKey

)

;

echo

(

base64_encode

(

$blowfish

-

>

Encrypt

(

$html

)))

;

}

else

if

(

$_GET

[

'page'

]

==

"addnote"

)

{

// wyświetlanie formularza

$html

=

<<<

heredochtml

<

form method=

"post"

action=

"index2.php=addnote2"

id=

"addNoteForm"

>

<

label for=

"title"

>

title:

<

/label

>

<

input type=

"text"

name=

"title"

id=

"title"

/

><

br/

>

<

textarea name=

"note"

id=

"note"

><

/textarea

><

br/

>

<

input type=

"submit"

value=

"add"

id=

"submitBtn"

/

>

<

/form

>

heredochtml;

$blowfish

=

new

Crypt_Blowfish

(

$_SESSION

[

'blowfishKey'

])

;

echo

(

base64_encode

(

$blowfish

-

>

Encrypt

(

$html

)))

;

}

else

if

(

$_GET

[

'page'

]

==

"addnote2"

)

{

// dodawanie notatki

$user

=

new

user

(

$_SESSION

[

'username'

]

,

$_SESSION

[

'password'

])

;

// ustawienie klucza blowfish

$blowfish

=

new

Crypt_Blowfish

(

$_SESSION

[

'blowfishKey'

])

;

//deszyfrowanie blowfish

$title

=

$blowfish

-

>

decrypt

(

base64_decode

(

$_POST

[

'title'

]))

;

$noteText

=

$blowfish

-

>

decrypt

(

base64_decode

(

$_POST

[

'note'

]))

;

//dodawanie notki

$user

-

>

addNote

(

$title

,

$noteText

)

;

echo

"new note added"

;

}

else

if

((

$_GET

[

'page'

]

==

"note"

)

&&

(

isset

(

$_GET

[

'pageid'

])))

{

// wyświetlanie notki

$user

=

new

user

(

$_SESSION

[

'username'

]

,

$_SESSION

[

'password'

])

;

$note

=

$user

-

>

getNoteById

(

$_GET

[

'pageid'

])

;

$html

= "

<

b

>

".$note['title']."

<

/b

><

br/

>

";

$html

.= "

<

p

>

".$note['text']."

<

/p

>

";

$blowfish

=

new

Crypt_Blowfish

(

$_SESSION

[

'blowfishKey'

])

;

echo

(

base64_encode

(

$blowfish

-

>

Encrypt

(

$html

)))

;

}
?>

O autorze


Wyszukiwarka

Podobne podstrony:
2006 06 Wstęp do Scrum [Inzynieria Oprogramowania]
2006 06 nowotwory slinianek trzustki
PN EN 12697 7 2006 06 30
2006 06 23 053139 Set28 Verbal
2006 06 23 052914 Set25 Math
2006 06 23 053021 Set27 Verbal
hajn glosa do Mangold eps 2006 06 036
2006 06 Raport Wizerunek Sopotu wxrxd mieszkaxcxw Bad jakoxciowe
2006 06 23 053849 Set31 Verbal
mat fiz 2006 06 05
pg 2006 06 22
CMS Lab 06 Podstawy PHP
06-Zasady bezp.pracy z prep.chemicznymi przy pracach porząd~2, Instrukcje BHP, XXVIII - SPRZĄTANIE
2006 06 05 matematyka finansowaid 25460
2006 06 08 Techn frezowania - zadanie, AGH, Semestr 8, Technologia wybranych elementów maszyn, cnc
Egzamin 2006.06.05, rozwiazania zadań aktuarialnych matematyka finansowa
2006 06 07 123001 Set23 Verbal
2006 06 23 052945 Set26 Verbal
2006 06 05 prawdopodobie stwo i statystykaid 25461

więcej podobnych podstron