Apr 29, 2011

Digitális aláírás PHP használatával

A digitális aláírásról bizonyára már mindenki hallott és talán már a gyakorlatban is találkozott vele - nem összekeverendő az elektronikus aláírással. A digitális aláíráshoz tartozó elméleti résszel (nyilvános kulcsú titkosítás) most nem foglalkozom - érdemes utánaolvasni -, jelenleg kizárólag a digitális aláírásra és annak gyakorlati megvalósítására koncentrálunk PHP alól.

Mi is az a digitális aláírás?

Tfh hogy van egy doksink amit, mint feladó el szeretnénk küldeni egy címzettnek. Eddig könnyűnek is tűnik a feladat. Viszont mi mindezt úgy szeretnénk megtenni, hogy a címzett biztos lehessen abban, hogy a dokumentum tőlünk származik és nem módosította senki más.

Aláírás és ellenőrzés folyamata - Wiki-től kölcsönözve - a következő:



Aláírás:
A doksiból képzünk egy hash-t (pl sha1_file()), melyet aztán titkosítunk a privát kulcsunkkal. A dokumentumhoz valamilyen formában hozzácsapjuk az aláírást (attached/detached) és a tanusítványt, majd küldhetjük is a címzetteknek.

Ellenőrzés:
Megkaptuk a dokumentumot az aláírással és a tanusítvánnyal együtt. Elolvasás előtt meg szeretnénk bizonyosodni arról, hogy valóban a megfelelő feladó készítette a dokumentumot. Szóval a két körös forduló első részében fogjuk az aláírást és feloldjuk a tanusítványban található publikus kulccsal. Ekkor rendelkezésre áll a küldő által biztosított hash. Ezt össze kell hasonlítanunk a dokumentum hash-ével. Így a második körben mi is - akár csak a küldő - hasheljük a dokumentumot és ha megegyezik az aláírásból feloldott hash-el, nyert ügyünk van.

Azt hogy a küldő milyen hashelő algoritmust használt, az aláírásból deríthetjük ki ill. annak egy meta infojából. Tehát az aláírás a titkosított hash-en kívül tartalmazza a hashelő algoritmust és tartalmazhat egyéb információkat is (pl verziószám).

A tanusítványról pedig tudjuk, hogy a publikus kulcson kívül a szabványának megfelelően még sokféle adatot tartalmaz. Az x.509-es tanusítvány felépítése: link.

Ennyit a digitális aláírás elméleti részéről és most nézzük meg mindezt, hogyan ültethetjük át a gyakorlatba. Először privát kulcsot és tanusítványt kell készítenünk, majd PHP-val aláírást készítő és ellenőrző szkriptet. Mindkét esetben az OpenSSL-t fogjuk használni.

Privát kulcs generálás:
openssl genrsa -out private.key 1024



Tanusítvány kérelem:
openssl req -new -nodes -key private.key -out cert_request.csr


Tanusítvány:
openssl x509 -req -days 100 -in cert_request.csr -signkey private.key -out cert.pem



PHP-ban az OpenSSL modult fogjuk használni a digitális aláírás készítéséhez és annak ellenőrzéséhez. Akár magunk is végigjárhatjuk ezt a két folyamatot végighaladva egyesével az alfeladatokon:

Aláírás:
  • privát kulcs kiolvasása
  • file-ról hash készítés
  • hash titkosítása a privát kulccsal
Ellenőrzés:
  • tanusítványból a publikus kulcs kiolvasása
  • az aláírás titkosított részének feloldása a nyilvános kulccsal
  • hash készítése a file-ról
  • a kapott hash ellenőrzése a az aláírásban már feloldottal
Az OpenSSL viszont biztosít számunkra egy-egy függvényt az előbbi két feladatra: sign, verify. Mielőtt azonban a kódolásra térnék találjunk ki egy struktúrát az aláírásnak: Vegyük alapul a PGP inline (attached) aláírási módját (amit egyébként az email-ek aláírásánál is használatos). Ez a módszer plain text-nél megfelelő de binárisnál már jobban járunk ha külön file-t (detached signature file) készítünk az aláírásnak.

-----BEGIN SIGNED MESSAGE----- 
Hash: -Algoritmus- (pl md5, sha1)
-Tartalom-
-----BEGIN SIGNATURE----- 
Version: -Verziószám-
-Titkosított hash-
-----END SIGNATURE-----

Kész a struktúránk, nézzük az aláíró kódot:



Lefuttatva az aláírást az alábbi eredményhez hasonlót kapunk:
-----BEGIN SIGNED MESSAGE----- 
Hash: sha1
This is a simple document, digitally signed with PHP[OpenSSL] by b3ha
-----BEGIN SIGNATURE----- 
Version: 1.0
G1qngHs3HJmkZLyNz8AkatvCdvx00Svf+bhWCKUwauL6af/bxlh/xrxBiOCG0bFee/Iv6VG
F+L1gWd74f8HCccnQ64lGpfsCCKlyfV4g3iqAJndp4a7KG3ieZd0Qa4UjIkajUpSLXRPocJ
dx4InDTIFhYHEvZu0NzBraQmkePEU=
-----END SIGNATURE-----


Majd az ellenőrzést végző szkript:


Hasznos, érdekes linkek:

http://stackoverflow.com/questions/589834/what-rsa-key-length-should-i-use-for-my-ssl-certificates
http://www.sslshopper.com/csr-decoder.html
http://www.sslshopper.com/certificate-decoder.html
http://www.w3.org/TR/xmldsig-core/

Apr 21, 2011

Rövidített URL feloldása

Tegnap az egyik hobbi projektem fejlesztése során belefutottam abba az esetbe, hogy nem elég a böngészőm címsorába bemásolni a rövidített - vélhetően izgalmas dolgokat tartalmazó - url-t, hanem programkódból is szükségem volt annak feloldására, kiterjesztésére. Nézzük is meg, hogy mire jutottam az általam kreált feladattal, milyen megoldásokat találtam (amennyiben tudtok jobb megoldást, api-t várom őket kommentekben).

A kiszemelt rövidített url, amely feloldásra vár legyen a következő: http://goo.gl/NOgUV Sebesség mérésként, pedig 5 egymás utáni futás átlagértékét veszem figyelembe.

Kezdetnek nézzünk egy nagyon egyszerű megoldást. A get_headers függvény segít nekünk úgy, hogy egy http kérést indítva a megadott url-re visszaadja nekünk a kapott válasz headerjét. A válaszból szimplán kivesszük a Location kulcs-hoz tartozó értéket és már kész is vagyunk (érdemes a függvény $format paraméterét 0-tól különböző értékre állítani, így kulcs-érték párokba szervezi a header tartalmat).
Futási idő: ~0.9s

Egy másik "brute force" módszer, hogy Curl-al lekérjük az oldalt, majd az átviteli információk-ból szűrjük le a számunkra szükséges url-t.
Futási idő: ~0.76s



Szerencsére rendelkezésre állnak különböző api-k is, melyekkel jóval gyorsabban jutunk eredményre. Ezek közül kettőre pillantunk rá: Google URL Shortener API, LongURL . Működésükről annyit, hogy egy megadott - paraméterezhetőséget biztosító - uri-ra kell ellátogatni, hogy feloldhassuk a rövidített url-t. A megfelelő url kiemenete valamilyen formában (json, xml...) a kiterjesztett url és néhány egyéb adat.
Php alól ezen adatok beolvasására lehetőségünk van például a file_get_contents vagy a fopen függvénnyel. Az említett függvényeknél viszont kreálhatunk egy gyorsabbat is, amennyiben lehetőségünk van a Curl használatára.



Végül, túllépve az adatok beolvasásán jöjjön a két api hívás:


Futási idő: ~0.26s


Futási idő: ~0.21s

A Google feloldója nyilván csak a Google által rövidített url-eket fogja tudni kiterjeszteni, ezzel szemben a LongURL API sok-sok domain-t ismer.

Apr 9, 2011

i18n class


Felkerült egy apró i18n osztály a githubos repoim közé, amit egy szerver oldali nyelvesítés példájaként készítettem. A különböző nyelvekhez tartozó fordítások beolvasásához egy property adapter osztály segítkezik - a kódból látható, hogy egyszerűen írhatunk más formátumra is beolvasót.
 Ide kapcsolódó előző posztok:


A könyvtár egyszerűbb kódokhoz a Zend_Translate vagy épp az FLP alternatívájaként szolgálhat.

Update: Valamiért lefelejtettem a legfontosabbat :) a linket

Apr 8, 2011

.properties

A főleg Java-ban használt property fájlról, ha valaki még nem hallott, akkor épp itt az ideje. Egészen hasznos a platformfüggetlen property állományokban tárolni például az i18n-hez tartozó kulcs-érték párokat.

Wiki oldalon fent lévő példa struktúra:
# You are reading the ".properties" entry.
! The exclamation mark can also mark text as comments.
website = http://en.wikipedia.org/
language = English
# The backslash below tells the application to continue reading
# the value onto the next line.
message = Welcome to \
          Wikipedia!
# Add spaces to the key
key\ with\ spaces = This is the value that could be looked up with the key "key with spaces".
# Unicode
tab : \u0009
 A kommenteket a # és ! karakterek jelölik és lehetőség van sortörésre is a \ karakterrel. Többféle formátum is támogatott a key=value mellett, például key = value vagy éppen key : value, ki melyiket preferálja.
 Nemzetköziesítésnél miután az alapértelmezett property fájl nyelvi kódját megbeszéltük magunkkal, adhatunk több helyszínt a property fájlunk mellé - úgymint en, hu stb (Természetesen lehetőség van a nyelvi kódon túl ország kód és variáns megadására is).

NetBeans-ben így nézünk ki
 PHP alól a felolvasására az előző posztban látható egy példa. Érdemes figyelni az unicode karakterek dekódolására felolvasáskor, mivel az állományok kódolása ISO-8859-1.
 Akad még egy fontos dolog a property állományoknál, ez pedig a szerkesztésük módja. NetBeans-ben például nagyon egyszerű a módosításuk ugyanis egy táblázatban látjuk a kulcsot és a különböző nyelvekhez tartozó értékeket.

NetBeans-ben szerkesztünk


Ennél többre nem is térnék ki, mivel egyszerű dologról van szó és mert hamarosan egy apró i18n osztályt is bemutatok majd.