In dit artikel zal ik uitleggen hoe je een PHP Class maakt die alle gegevens met een bepaald wachtwoord versleutelt en decodeert. Het is objectgeprogrammeerd en gebruikt bestaande PHP-algoritmen.
Denk je eens aan waar we zo'n les voor nodig hebben? We willen belangrijke gegevens versleutelen met een wachtwoord om veiligheidsredenen. We willen ook, zoals eerder vermeld, in staat zijn om die gegevens te ontsleutelen wanneer dat nodig is. Waarom zou u symmetrische algoritmen gebruiken? Het is makkelijk; wanneer u een wachtwoord aanbiedt dat via e-mail is verzonden of iets dergelijks, moet u het wachtwoord in leesbare vorm verzenden. De hash-algoritmen zijn niet omkeerbaar. Als je eenmaal een string hebt gehashed, kun je de originele tekst van de hash niet ontcijferen.
Misschien heb je al gehoord van MD5? Het is niet echt de beste optie meer omdat het vaak onveilig is. Er zijn databases op het web - die ik niet wil vermelden - die kunnen worden gebruikt om de leesbare tekst van een hash op te halen door simpelweg de hash in een zoekvak in te typen. U moet dus zoiets als SHA gebruiken dat is ontwikkeld door de NSA (National Security Agency). SHA is de afkorting voor Secure Hash Algorithm en is een van de meest veilige hash-algoritmen. Er zijn ook enkele andere, zoals WHIRLPOOL, PANAMA en RIPEMD, maar SHA is momenteel de veilige standaard voor hashes en wordt in talloze toepassingen gebruikt.
Ik denk dat het belangrijk is om een interface te maken. Dit komt omdat we altijd de methoden kunnen gebruiken die in de interface zijn gedefinieerd zonder na te denken, bij het instancing van een object van een klasse, die die interface implementeert.
Wanneer een klasse een interface implementeert, moet deze de methoden implementeren die in die interface worden gegeven, anders zal er een fout optreden! Dus hier is een voorbeeld:
interface ICrypter public function Encrypt ($ data); openbare functie Decrypt ($ data); class Crypter implementeert ICrypter public function Encrypt ($ data) ... public function Decrypt ($ data) ...
Zoals u kunt zien, geeft de interface instructies voor de klassen die worden geïmplementeerd ICrypter
om de openbare functie Versleutelen met één parameter te hebben $ data
. De openbare functie Decrypt heeft ook de parameter $gegevens
. Je kunt het uitproberen; als de klasse een van de gegeven methoden in de interface mist, krijg je een fatale fout. Hier is een voorbeeld:
Fatale fout: Class Crypter bevat 1 abstracte methode en moet daarom abstract worden verklaard of de resterende methoden implementeren (ICrypter :: Decrypt) in C: \ www \ Nettuts \ Crypter \ crypter.php op regel 32.
Leuke fout toch? Dus je kunt er zeker van zijn dat de klassen echt de methoden hebben!
Zoals ik al eerder zei, willen we een specifiek wachtwoord kunnen gebruiken voor codering en decodering. Dit wachtwoord moet toegankelijk zijn voor de codeer- en decoderingsfunctie, dus we zullen een instantievariabele definiëren, de zogenaamde sleutel, die wordt doorgegeven aan de constructor. De definitie van $ Key
is alleen nodig in de Crypter
Klasse:
privé $ sleutel;
De definitie van de constructor moet zich echter in de interface bevinden. Daarom is het ook nodig in de klas, omdat we alles moeten implementeren dat we in de interface hebben gedefinieerd. De interface zal bevatten:
publieke functie __construct ($ Key);
en de klas:
openbare functie __construct ($ Key) ...
Nu we weten dat we een sleutel krijgen, kunnen we deze gebruiken om te coderen en decoderen!
In de constructor moeten we de sleutel instellen en een algoritme kiezen. We gebruiken het Blowfish-algoritme voor dit voorbeeld en gebruiken het als standaardwaarde. Ik zal later in de tekst wat meer uitleggen over de symmetrische algoritmen, maar voor de eenvoud zullen we Blowfish gebruiken. U kunt dit later wijzigen als u dat wilt. Dus we hebben een andere instantievariabele genaamd Algo nodig:
privé $ Algo;
en de constructeur ...
openbare functie __construct ($ Key, $ Algo = MCRYPT_BLOWFISH) $ this-> Key = substr ($ Key, 0, mcrypt_get_key_size ($ Algo, MCRYPT_MODE_ECB)); $ this-> Algo = $ Algo;
De lengte van de sleutel is afhankelijk van het algoritme en de versleutelingsmodus. In dit voorbeeld gebruiken we de ECB-modus. U kunt deze variabele maken zoals we al hebben gedaan met het algoritme. We gebruiken de substring van de gegeven sleutel met de maximaal toegestane lengte. Je kunt deze lengte krijgen met de mcrypt_get_key_size
functie die het algoritme en de versleutelingsmodus als parameters vereist.
Nu geven we onze instantievariabele Key de juiste sleutel voor het algoritme en wijzen we onze instantievariabele Algo toe.
Dus nu hebben we de constructor. Zoals ik eerder al zei, kunt u de standaardwaarde van Algo wijzigen in een ander algoritme dat wordt ondersteund door MCrypt.
Lijst met ondersteunde algoritmen van php.net:
Dus welke moeten we gebruiken als we de Crypter Class in onze producten willen gebruiken? Op dit moment is AES de standaard van de symmetrische algoritmen. Het wordt in veel toepassingen gebruikt, maar waar is AES? AES werd oorspronkelijk gepubliceerd als Rijndael die wordt vermeld. Het is een echt snel, maar veilig algoritme en is zelfs snel met 256-bits sleutelgrootte. Mijn advies is om MCRYPT_RIJNDAEL_256 te gebruiken voor uw toepassingen. Net als een voorbeeld wordt AES gebruikt in WPA2, een beveiligingsstandaard voor WLAN.
Het eerste wat je moet controleren: zijn er gegevens om te coderen? Als dat niet het geval is, kunt u doorgaan en de codering verbreken. Als u andere coderingsmodi wilt gebruiken, moet u de volgende code toevoegen.
$ iv_size = mcrypt_get_iv_size ($ this-> Algo, MCRYPT_MODE_ECB); $ iv = mcrypt_create_iv ($ iv_size, MCRYPT_RAND);
Deze $ iv
wordt bijvoorbeeld gebruikt in CBC, CFB, OFB en in sommige algoritmen in STREAM-versleutelingsmodus. Als de parameter in deze modi niet wordt doorgegeven, zorgt de $ iv
zal worden ingesteld op '\ 0'
. De volgende stap is om de gegevens te coderen met de eenvoudige functie mcrypt_encrypt. Hier hebben we ons algoritme, de sleutel, de gegevens en een coderingsmodus nodig. $ iv is optioneel.
$ crypt = mcrypt_encrypt ($ this-> Algo, $ this-> Key, $ data, MCRYPT_MODE_ECB, $ iv);
Codeer ten slotte de gecodeerde gegevens met base64_encode en snijd het in voordat u het terugstuurt.
return trim (base64_encode ($ crypt));
We moeten base64 de gecodeerde gegevens coderen om URL-veilige gegevens te krijgen. Dit is nodig omdat, als u de gecodeerde gegevens wilt gebruiken, bijvoorbeeld in een URL, er problemen zullen zijn met '&' omdat het een gereserveerd teken is dat is gespecificeerd in de RFC. U hebt dus iets nodig als alfanumerieke tekens, met andere woorden, tekens die veilig zijn. De base64-codering levert deze veilige tekens, daarom gebruiken we deze. We weten niet wat er met de gegevens zal gebeuren na de codering.
Opnieuw stellen we dezelfde eerste vraag. Zijn er gegevens? Als dat het geval is, moet je de data base64_decoderen zoals we die eerder hebben gecodeerd met base64_encode.
$ crypt = base64_decode ($ data);
Dan is het optionele deel met $ iv.
$ iv_size = mcrypt_get_iv_size ($ this-> Algo, MCRYPT_MODE_ECB); $ iv = mcrypt_create_iv ($ iv_size, MCRYPT_RAND);
Decryptie met de eenvoudige functie mcrypt_decrypt
. Hier hebben we - bijna - dezelfde parameters nodig. Het verschil is dat de decoderingsfunctie toegang moet hebben tot de gecrypteerde gegevens in plaats van tot de oorspronkelijke gegevens. Dus ook hier gebruiken we, het algoritme, de sleutel, de gecrypteerde gegevens, de versleutelingsmodus en de optionele iv.
$ decrypt = mcrypt_decrypt ($ this-> Algo, $ this-> Key, $ crypt, MCRYPT_MODE_ECB, $ iv);
Retourneer ten slotte de geknipte en ontsleutelde gegevens.
return trim ($ decrypt);
Definieer een globale Crypter. In dit voorbeeld gebruiken we RIJNDAEL_256 (AES) met het wachtwoord "Elk wachtwoord". Na het instancen bel je je functies of methoden om het te testen. Hier noemen we de functie foo
en de methode foo1
.
$ crypter = new Crypter ("Any password", MCRYPT_RIJNDAEL_256); foo (); $ foo = new Foo (); $ Foo-> foo1 ();
U kunt uw crypter van de opgeroepen Superglobal-variabele halen $ GLOBALS
. Dit is een associatieve array, zodat u al uw globale variabelen kunt aanroepen met de naam waarmee u ze hebt gedefinieerd. U kunt de $ crypter
die is gedefinieerd buiten het foo- of foo1-blok met $ GLOBALS [ "crypter"]
...
function foo () ... $ encryption = $ GLOBALS ["crypter"] -> Encrypt ($ data); $ decrypted = $ GLOBALS ["crypter"] -> Decoderen ($ versleuteld); ... class Foo public function foo1 () ... $ encryption = $ GLOBALS ["crypter"] -> Encrypt ($ data); $ decrypted = $ GLOBALS ["crypter"] -> Decoderen ($ versleuteld); ...
Nu hebt u een volledige Crypter-klasse en kunt u zo vaak als u wilt crypten en decoderen! Download de volledige broncode met een mooi voorbeeld als je het niet zelf wilt typen. Ik hoop dat je dit artikel leuk vond.