Systemvoraussetzung
- Linux
- Windows
- PHP 4 >= 4.3.0
- PHP 5
- MySQL
- libmcrypt 2.4.x oder 2.5.x
Datei(en)
rijndael.php, rijndael.inc.php, rijndael.css, rijndael.sql
Problem
Bisher haben Sie gesehen, wie man Daten verschlüsselt und sie in Textdateien
speichert. Sicherlich hätten Sie es gerne komfortabler und die Daten nicht als
Textdateien, sondern in einer Datenbank vorliegen. Diesem Thema werden wir
uns nun widmen.
Lösung
Das folgende Beispiel ist eine komplette Lösung zur Verschlüsselung. Die
verschlüsselten Daten werden dabei in eine MySQL-Datenbank
gespeichert
und können über ein Drop-Down-Menü
jeweils ausgewählt werden. Weiterhin
speichert das Programm das Datum und die Uhrzeit von folgenden Ereignissen:
- Erstellungsdatum der letzten Verschlüsselung
- Datum der letzten erfolgreichen Entschlüsselung
- Datum der letzten fehlgeschlagenen Verschlüsselung
Somit können Sie genau sehen, wie auf den entsprechenden Datensatz zugegriffen
wurde. Sie können bei der Verschlüsselung einen Info-Text
eingeben,
sodass Sie später im Drop-Down-Menü
den entsprechenden Datensatz schneller
finden. Weiterhin haben Sie die Möglichkeit, zwischen einer Verschlüsselungsstärke
von 128, 192 oder 256 Bit zu wählen.
Bei der Verschlüsselung können Sie wahlweise reinen Text oder eine Datei
angeben. Sollte es sich um eine Datei handeln, wird der Inhalt der Datei
verschlüsselt und in die Datenbank gespeichert.
Um maximale Sicherheit zu gewährleisten, wird das Passwort für die Entschlüsselung
nicht mit in die Datenbank gespeichert. Sollten Sie dieses Passwort
verlieren, so sind Ihre Daten nicht mehr zu entschlüsseln. Also achten Sie sehr
gut auf Ihr Passwort!
Das Programm ist bereits so aufgebaut, dass Sie eigene Menüfelder hinzunehmen
können, um das Programm an Ihre Bedürfnisse anzupassen.
Hier im Buch verzichten wir auf die Quellcode-Darstellung
der HTML-Datei,
da
der Programmcode bereits viele Seiten einnimmt und die HTML-Seite
nur ein
paar PHP-Blöcke
zur Darstellung bereithält – dies müssen wir nicht gesondert
aufzeigen.
Im Folgenden sehen Sie drei Screenshots, die allerdings nicht die komplette
Programmseite wiedergeben, sondern nur Ausschnitte sind.
Den vollen Umfang
der Seite inkl. Menüs sehen Sie auf der folgenden gesonderten Seite.
Abbildung 12.2: Screenshot Verschlüsselung
Abbildung 12.3: Screenshot Entschlüsselung
Abbildung 12.4: Screenshot Info
Sie finden bei der beiliegenden ZIP-Datei
eine Datei mit dem Namen rijndael.sql.
Diese Datei enthält die Struktur der Tabelle für die Datenbank. Am einfachsten
ist es, wenn Sie diese Datei mit phpMyAdmin einlesen und sich somit die
Tabelle erstellen lassen.
Sollten Sie den Tabellennamen in dem SQL-Statement
ändern, so müssen
Sie diesen Namen auch in der Konfiguration ändern. Dann müssen Sie die
Parameter für den Datenbankzugriff angeben und können das Programm
sofort ausprobieren.
Dieses Programm können Sie nach Herzenslust erweitern und modifizieren.
Wie zu Beginn des Buches erwähnt, haben wir bewusst auf Klassen verzichtet,
daher finden Sie hier im Beispiel auch hauptsächlich Funktionen.
Das Programm bietet sich aber geradezu an, in eine Klasse implementiert zu
werden – also wenn Sie sich üben wollen oder bereits genug Erfahrung besitzen,
so modifizieren sie es.
Nun wollen wir uns aber dem Programmcode widmen. Wir werden uns zunächst
alle Funktionen anschauen, bevor wir zu dem Teil kommen, in dem
sich die einzelnen Verzweigungen für das Programm befinden.
function encryptAES($content,$key,$aes)
@param string $content
@param string $key
@param integer $aes
@return mixed
Die nachfolgende Funktion kennen Sie bereits aus dem vorangegangenen
Beispiel. Daher werden wir sie nicht noch einmal näher beschreiben. Falls
noch Fragen bestehen, so schauen Sie bitte im vorherigen Beispiel nach, dort
finden Sie eine sehr detaillierte Erklärung zu dieser Funktion. Einen kleinen
Unterschied gibt es in dieser Funktion aber dennoch.
Diesmal speichern wir die Daten nicht in eine Textdatei, sondern in einem
Array (41, 43, 55, 65). Wir speichern zum einen den verschlüsselten Text (35)
und zum anderen eine MD5-Prüfsumme
(65) des unverschlüsselten Textes.
Falls Sie sich jetzt fragen sollten wofür wir diese Prüfsumme benötigen, so ist
die Antwort schnell gegeben. Wir brauchen sie bei der Entschlüsselung.
Wir möchten alles protokollieren – vor allem aber die misslungenen Entschlüsselungen.
Vielleicht hat ja jemand versucht, die Daten über das Programm zu
entschlüsseln, hatte aber das falsche Passwort. Wenn Sie z. B. versuchen, den
folgenden verschlüsselten Text mit einem falschen Passwort zu entschlüsseln,
-ÉÚE7ækéªç¡Xûïãöù|‰LÂڈô¼õ`GO. . . ]Ò°Æ<2‚&
wð@Sʤîáî?2>:k¢æÂçíu‘ê?¼ |
so erhalten Sie als Ergebnis z. B. Folgendes als Rückgabetext (ist jedes Mal
verschieden):
Jetzt stehen wir vor einem Problem. Wie erkenne ich, ob der Text richtig
entschlüsselt wurde? An diesem Punkt kommt die MD5-Prüfsumme
ins Spiel.
Anhand dieser Prüfsumme, die wir aus dem unverschlüsselten Text erzeugt
haben, können wir beide Texte miteinander vergleichen.
Ist die Prüfsumme des entschlüsselten Textes genau wie die MD5-Prüfsumme,
die wir beim Verschlüsseln erzeugt haben, so muss das Passwort richtig
gewesen sein. Wären die beiden Prüfsummen unterschiedlich, so war die
Entschlüsselung bzw. das Passwort fehlerhaft.
Aus diesem Grund speichern wir nicht nur den verschlüsselten Text in die
Datenbank, sondern auch die MD5-Prüfsumme
(65). Diese Funktion gibt also
ein Array mit dem verschlüsselten Text und der Prüfsumme zurück (67).
017:
018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032: 033: 034: 035: 036: 037:
038:
039:
040: 041:
042: 043:
044: 045: 046: 047: 048: 049: 050: 051: 052: 053: 054: 055: 056: 057: 058: 059: 060: 061: 062: 063: 064: 065: 066: 067: 068: 069: |
function encryptAES($content,$key,$aes)
{
// Setzt den Algorithmus
switch ($aes) {
case 128: $rijndael = 'rijndael-128'; break; case 192: $rijndael = 'rijndael-192'; break; default: $rijndael = 'rijndael-256'; }
// Setzt den Verschlüsselungsalgorithmus // und setzt den Output Feedback (OFB) Modus $cp = mcrypt_module_open($rijndael, '', 'ofb', ''); if(!$cp) return 'Modul konnte nicht geladen werden'; // Ermittelt den Initialisierungsvector, der für die Modi CBC, CFB und
OFB benötigt wird.
// Der Initialisierungsvector muss beim Entschlüsseln den selben Wert
wie beim Verschlüsseln haben.
// Windows unterstützt nur MCRYPT_RAND
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $enc['iv'] = mcrypt_create_iv(mcrypt_enc_get_iv_size($cp),
MCRYPT_RAND); else $enc['iv'] = mcrypt_create_iv(mcrypt_enc_get_iv_size($cp),
MCRYPT_DEV_RANDOM); // Ermittelt die Anzahl der Bits, welche die Schlüssellänge des Keys festlegen $ks = mcrypt_enc_get_key_size($cp); // Erstellt den Schlüssel, der für die Verschlüsselung genutzt wird $key = substr(md5($key), 0, $ks); // Initialisiert die Verschlüsselung mcrypt_generic_init($cp, $key, $enc['iv']); // Verschlüsselt die Daten $enc['encrypted'] = mcrypt_generic($cp, $content); // Deinitialisiert die Verschlüsselung mcrypt_generic_deinit($cp); // Schließt das Modul mcrypt_module_close($cp); // Erstellt einen Hash-Wert um später prüfen zu können, ob ein misslungene // Entschlüsselung durchgeführt wurde $enc['md5'] = md5($content); return $enc; } |
Beispiel 12.14: rijndael.inc.php
function decryptAES($content,$iv, $key,$aes)
@param string $file
@param string $key
@param integer $aes
@param string $ivFile
@return mixed
Auch in dieser Funktion hat sich kaum was geändert. Im vorherigen Beispiel
konnten Sie bereits verfolgen, wie diese Funktion arbeitete. Sie entschlüsselt
unseren Text und gibt ihn der aufgerufenen Stelle zurück.
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
|
function decryptAES($content,$iv, $key,$aes)
{
// Setzt den Algorithmus
switch ($aes) {
case 128:
$rijndael = 'rijndael-128';
break;
case 192:
$rijndael = 'rijndael-192';
break;
default:
$rijndael = 'rijndael-256';
}
// Setzt den Verschlüsselungsalgorithmus
// und setzt den Output Feedback (OFB) Modus
$cp = mcrypt_module_open($rijndael, '', 'ofb', '');
// Ermittelt die Anzahl der Bits, welche die Schlüssellänge des Keys festlegen
$ks = mcrypt_enc_get_key_size($cp);
// Erstellt den Schlüssel, der für die Verschlüsselung genutzt wird
$key = substr(md5($key), 0, $ks);
// Initialisiert die Verschlüsselung
mcrypt_generic_init($cp, $key, $iv);
// Entschlüsselt die Daten
$decrypted = mdecrypt_generic($cp, $content);
// Beendet die Verschlüsselung
mcrypt_generic_deinit($cp);
// Schließt das Modul
mcrypt_module_close($cp);
return trim($decrypted);
} |
Beispiel 12.15: rijndael.inc.php
function insertBase($encrypted,$iv,$infotext,$aes,$md5,$dbTable)
@param string $encrypted
@param string $iv
@param string $infotext
@param integer $aes
@param string $md5
@param string $dbTable
@return bool
Die Funktion insertBase() ist für das Speichern eines verschlüsselten Textes
in die Datenbank verantwortlich. Sie erwartet als Parameter den verschlüsselten
Text, den IV-Tag
aus der Verschlüsselung (encryptAES()), den Infotext aus dem
Webformular, die Verschlüsselungsstärke (128, 192 oder 256 Bit), die MD5-Prüfsumme
aus der Verschlüsselung (encryptAES()) und zum Schluss den
Tabellennamen in der Datenbank.
Allerdings müssen wir den IV-Tag
und den verschlüsselten Text für die Datenbank
vorbereiten (141, 142), da innerhalb dieser beiden Variablen eine Vielzahl
von Anführungsstrichen etc. vorkommen kann und diese mit einem Backslash
(\) geschützt werden müssen.
Würden wir darauf verzichten, so würde das Einfügen in die Datenbank scheitern.
Wir setzen also unseren SQL-String
(144-152)
mit den gelieferten Daten
zusammen und fügen anschließend die Daten in die Datenbank ein (153).
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
|
function insertBase($encrypted,$iv,$infotext,$aes,$md5,$dbTable) {
$encrypted = addslashes($encrypted);
$iv = addslashes($iv);
$sqlString = "INSERT INTO
$dbTable
SET
infotext = '$infotext',
textaes = '$encrypted',
block = '$aes',
encrypt = NOW(),
ivTag = '$iv',
md5 = '$md5'";
$sqlInsert = @mysql_query($sqlString);
return true;
} |
Beispiel 12.16: rijndael.inc.php
function checkDecrypt($decrypted,$md5,$id=0,$database=false)
@param string $decrypted
@param string $md5
@param integer $id
@param bool $database
@return mixed
Die Funktion checkDecrypt() ist unsere Protokollfunktion. Sie überprüft,
ob der entschlüsselte Text identisch mit der Prüfsumme ist, die beim Verschlüsseln
erstellt wurde. Ist dies der Fall (176), so wird diese erfolgreiche
Entschlüsselung mit Datum und Uhrzeit gespeichert (177). Waren die beiden
Prüfsummen nicht identisch, so wird die fehlgeschlagene Entschlüsselung
ebenfalls mit Datum und Uhrzeit gespeichert (180).
Die Funktion hat noch einen weiteren Zweck. Wenn Sie einen Text verschlüsseln,
so wird der Text nicht einfach verschlüsselt und in die Datenbank geschrieben,
sondern vorher einem Test unterzogen. Die Funktion prüft dann,
ob die gerade erstellte Verschlüsselung auch wieder mit dem Passwort entschlüsselbar
ist.
Ist das der Fall, so gibt die Funktion TRUE zurück und die Daten werden
gespeichert. Konnte der Text nicht wieder entschlüsselt werden, so meldet die
Funktion FALSE und speichert die Daten nicht, sondern gibt einen Hinweistext
aus.
Daher ist der Aufruf der Funktion auch unterschiedlich. Wenn Sie einen Text
entschlüsseln wollen (175), so geben Sie der Funktion die beiden folgenden
optionalen Parameter mit:
- $id Die Datenbank-ID
des verschlüsselten Textes
- $database true, wenn Sie die Daten entschlüsseln wollen
Wollen Sie hingegen nur prüfen, ob der gerade verschlüsselte Text auch wieder
entschlüsselbar ist (183), so lassen Sie diese beiden Parameter einfach weg. Sie
werden dann mit den Standardwerten 0 (Null) und FALSE gefüllt.
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
|
function checkDecrypt($decrypted,$md5,$id=0,$database=false)
{
if($database) {
if(md5($decrypted) == $md5) {
$sqlUpdate = @mysql_query("UPDATE rijndael SET decrypt = NOW()
WHERE id = $id");
$message = "Daten konnten erfolgreich entschlüsselt werden.";
} else {
$sqlUpdate = @mysql_query("UPDATE rijndael SET decryptError = NOW()
WHERE id = $id");
$message = "Daten konnten nicht entschlüsselt werden!";
}
} else {
if(md5($decrypted) == $md5) {
return true;
} else {
return false;
}
}
return $message;
} |
Beispiel 12.17: rijndael.inc.php
function sendIV($iv,$md5,$rijndael)
@param string $iv
@param string $md5
@param integer $rijndael
@return void
Sie haben jederzeit die Möglichkeit, sich den IV-Tag
per Download zuschicken
zu lassen. Sie müssen lediglich das richtige Passwort kennen. Die Daten werden
entschlüsselt, bevor Sie an diese Funktion übergeben werden, und mit den
beiden MD5-Prüfsummen
verglichen. Stimmen beide Werte überein, so wird
diese Funktion aufgerufen.
Die Funktion erwartet als Parameter den IV-Tag,
die MD5-Prüfsumme
sowie die
Verschlüsselungsstärke (128, 192 oder 256 Bit). Basierend auf den Werten wird
eine „Datei“ erstellt (210-213),
die unter anderem die Verschlüsselungsstärke
(211), das Datum (211), an dem diese Download-Datei
erstellt wurde, und den
IV-Tag
(213) beinhaltet. Der Dateiname wird aus der MD5-Prüfsumme
gebildet
(216) und erhält als Dateiendung *.iv. Im Folgenden sehen Sie eine derartige
Beispieldatei.
Datei: 659a3c8c5d480399a2dd89b73c88ccf0.iv
; IV-Tag
Datei
; Erstellt am 05.04.2006 13:37:49
; Verschlüsselung 256 Bit
[óQÞiÍÛGem])žª '¸,*êèà¬keq) 2¡ |
Wie Sie sicherlich noch aus dem vorangegangenen Beispiel wissen, benötigen
Sie zur Entschlüsselung alle drei Werte. Zum einen den IV-Tag,
zum anderen
den verschlüsselten Text sowie die Verschlüsselungsstärke.
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
|
function sendIV($iv,$md5,$rijndael){
$message .= "; IV-Tag Datei\n";
$message .= "; Erstellt am ". date("d.m.Y H:i:s") . "\n";
$message .= "; Verschlüsselung " . $rijndael . "\n";
$message .= $iv;
header("Content-Type: text");
header("Content-Disposition: attachment; filename=\"$md5.iv\"");
echo $message;
exit;
} |
Beispiel 12.18: rijndael.inc.php
function sendEncrypt($content,$md5)
@param string $content
@param string $md5
@return void
Weiterhin haben Sie jederzeit die Möglichkeit, sich den verschlüsselten Text per
Download zuschicken zu lassen. Auch hier müssen Sie das richtige Passwort
kennen. Die Daten werden entschlüsselt, bevor Sie an diese Funktion übergeben
werden, und mit den beiden MD5-Prüfsummen
verglichen. Stimmen beide
Werte überein, so wird diese Funktion aufgerufen.
Die Funktion erwartet als Parameter den verschlüsselten Text sowie die MD5-Prüfsumme.
Basierend auf den Werten wird ein Header (234, 235) gesendet
und der verschlüsselte Text ausgegeben (237). Der Dateiname (235) wird aus
der MD5-Prüfsumme
gebildet und erhält als Dateiendung *.aes. Im Folgenden
haben wir eine solche eine Beispieldatei aufgeführt.
Datei: 659a3c8c5d480399a2dd89b73c88ccf0.aes
-ÉÚE7ækéªç¡X [2DC?]ûïãöù|‰LÂڈô¼õ`GO. . . ]Ò°Æ<2‚&
wð@Sʤîáî?2>:k¢æÂçíu‘ê?¼ |
Wie erwähnen es hier nur noch einmal vorsichtshalber: Zum Entschlüsseln
benötigen Sie alle drei Werte. Zum einen den IV-Tag,
zum anderen den verschlüsselten
Text sowie die Verschlüsselungsstärke.
232:
233:
234:
235:
236:
237:
238:
239:
240:
|
function sendEncrypt($content,$md5)
{
header("Content-Type: text");
header("Content-Disposition: attachment; filename=\"$md5.aes\"");
echo $content;
exit;
} |
Beispiel 12.19: rijndael.inc.php
Grundeinstellung
Die Grundeinstellung ist relativ simpel und bezieht sich lediglich auf die Datenbank.
Die benötigten Werte wie Benutzername (8), Datenbank (7), Host
(6) sowie Passwort (9) müssen Sie ergänzen. Falls Sie beim Anlegen der Tabelle
einen anderen Namen als „rijndael“ gewählt haben, müssen sie diesen
selbstverständlich auch ergänzen (10).
001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013:
014: |
<?PHP
/** * Datenbank Zugangsdaten */
define("DB_HOST","localhost"); // MySQL Hostname
define("DB_NAME","db_name"); // MySQL Datenbankname
define("DB_USER","db_user"); // MySQL Benutzername
define("DB_PASS","db_passwd"); // MySQL Passwort
$db['table'] = 'rijndael'; // MySQL Tabellenname
$dbCon = @MYSQL_CONNECT(DB_HOST,DB_USER,DB_PASS)
or die("Datenbank momentan nicht erreichbar"); $db_check = @MYSQL_SELECT_DB(DB_NAME)
or die("Datenbank momentan nicht erreichbar");
|
Beispiel 12.20: rijndael.php
Verschlüsseln
Wurde als Aufgabe die Verschlüsselung gewählt (84), so werden im Vorfeld die
übermittelten Variablen überprüft. Zum einen darf das Passwort nicht leer sein
(86) und zum anderen müssen beide zum Vergleich abgefragten Passwörter
identisch sein (98). Weiterhin darf der Infotext, der für die Darstellung der
Drop-Down-Darstellung
benötigt wird, nicht leer sein (92).
Je nach Ergebnis der Überprüfung werden unterschiedliche Fehlermeldungen
generiert und ausgegeben. Sie können diese Fehlermeldungen noch modifizieren,
indem Sie das Beispiel aus diesem Buch zur Fehlerüberprüfung bei
Formularen nehmen.
Falls Sie die Textverschlüsselung und nicht die Dateiverschlüsselung gewählt
haben, so wird auch hier eine Überprüfung vorgenommen (104) und ein eventueller
Fehler ausgegeben. Sollte es sich bei Ihrer Auswahl um eine Dateiverschlüsselung
handeln, so müssen wir in diesem Fall noch überprüfen, ob
überhaupt eine Datei angegeben wurde (110).
Wurde keine Datei angegeben, wird die IF-Abfrage
(113) greifen und einen
Fehler ausgeben. Wurde eine Datei angegeben, so wird der else-Zweig
(118)
weiterverarbeitet. Zuerst bilden wir aus der aktuellen Uhrzeit einen temporären
Namen (120) für den Upload der Datei, die wir dann mit move_upload_file()
(121) speichern und anschließend in eine Variable einlesen (122). Nachdem wir
den Inhalt der Datei eingelesen haben, können wir diese Datei wieder löschen
(123).
Jetzt haben wir alle notwendigen Informationen für unsere Verschlüsselung zusammen
und können im nächsten Schritt die Daten in die Datenbank speichern,
nachdem wir sie verschlüsselt haben. Da alle geforderten Variablen vollständig
sind, wird auch die IF-Abfrage
(127) nicht fehlschlagen und ausgeführt.
Sollte als Verschlüsselung die Textverschlüsselung gewählt (129) worden sein,
speichern wir den Inhalt der POST-Variablen
(130) in die Variable $content.
Falls eine Dateiverschlüsselung gewählt wurde, so ist die Variable bereits
gefüllt mit dem Text aus der Datei (122). Wir speichern noch unsere übermittelten
POST-Variablen
in bereits bestehende Variablen (131-133),
um nicht
ständig auf die POST-Variablen
zugreifen zu müssen. Erst dann inkludieren
wir unsere rinjndael.inc.php (135), die ja alle notwendigen Funktionen für die
Verschlüsselung enthält.
Wir verschlüsseln jetzt unseren Text (136) mit dem übergebenen Passwort
und prüfen im Anschluss, ob der verschlüsselte Text auch wieder mit diesem
Passwort entschlüsselt werden kann (138). War dieser Test erfolgreich, also
der Vergleich der beiden MD5-Prüfsummen
identisch (140), speichern wir
den verschlüsselten Datensatz mit der Funktion insertBase() (141) in die
Datenbank. Je nachdem, erhalten wir als Rückgabe entweder TRUE oder FALSE.
Somit ist unsere Verschlüsselung abgeschlossen und der Datensatz liegt sicher
in der Datenbank. Da wir beim Speichern vorher geprüft haben (140), ob der
Text auch wieder entschlüsselbar ist, können wir beruhigt an dieser Stelle den
Vorgang beenden.
084: 085: 086: 087: 088: 089: 090: 091: 092: 093: 094: 095: 096: 097: 098: 099: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141:
142:
143: 144: 145: 146:
| if(isset($_POST['typ']))
{ if(empty($_POST['password'])) { $error = true; $message .= 'Bitte geben Sie ein Passwort ein<br>'; } if(empty($_POST['info'])) { $error = true; $message .= 'Bitte geben Sie einen Infotext ein<br>'; } if($_POST['password'] != $_POST['passwordCheck']) { $error = true; $message .= 'Passwörter stimmen nicht überein<br>'; } if(empty($_POST['textfield']) && $_POST['typ'] == "1") { $error = true; $message .= 'Bitte geben Sie einen Text ein<br>'; } if ($_POST['typ'] == "2") { if($_FILES['file']['error']) { $error = true; $message .= 'Bitte geben Sie eine Datei an<br>'; } else { $filetmp = time() . '.tmp'; move_uploaded_file($_FILES['file']['tmp_name'], "./$filetmp"); $content = file_get_contents($filetmp); unlink($filetmp); } } if(!$error) { if($_POST['typ'] == "1") $content = $_POST['textfield']; $password = $_POST['password']; $rijndael = $_POST['rijndael']; $info = $_POST['info']; include_once("rijndael.inc.php"); $enc = encryptAES($content,$password,$rijndael); $decrypted = decryptAES($enc['encrypted'],$enc['iv'],$password,$rijndael); if(checkDecrypt($decrypted,$enc['md5'])) insertBase($enc['encrypted'],$enc['iv'],$info,$rijndael,
$enc['md5'],$db['table']);
else $message = 'Daten konnten nicht verschlüsselt werden!'; } }
|
Beispiel 12.21: rijndael.php
Entschlüsseln
Zuerst überprüfen (20) wir, ob ein Passwort übermittelt wurde. Ist das nicht
der Fall, also die Variable leer, so wird die zuvor auf „FALSE“ gesetzte Error-Variable
(16) auf „TRUE“ (22) gesetzt und eine Fehlermeldung generiert (23).
Die nächste IF-Abfrage
würde somit scheitern und der nachfolgende Programmcode
nicht mehr ausgeführt.
Wurde ein Passwort übermittelt, so besitzt die Error-Variable
(16) den Wert
„FALSE“ und wird der Überprüfung (26) standhalten. Der nachfolgende Programmcode
wird somit ausgeführt. Um nicht willkürlich eine Variable an die
Datenbank zu geben, erzwingen wir eine Konvertierung unserer mit POST
übergebenen Variablen in ein Integer, indem wir den Wert mit 0 (Null) addieren
(28).
Somit können wir jetzt unsere Datenbankabfrage zusammensetzen (29-33)
und anschließend ausführen (34). Bei der Datenbankabfrage formatieren wir
direkt unser Datum, das im amerikanischen Format vorliegt, ins deutsche
Format. Somit erhalten wir dann anstatt
eine Ausgabe in folgender Form
und ersparen uns eine spätere Konvertierung mit PHP. Sie sollten bei Datumsabfragen
aus einer Datenbank immer diesen Weg wählen, da er wesentlich
effizienter ist und unnötige Programmierarbeit vermeidet.
War die Datenbankabfrage erfolgreich, und wurde ein Datensatz geliefert (36),
so füllen wir unser Array (38-44)
mit den Werten aus unserer Abfrage. Erst
im nächsten Schritt inkludieren (46) wir unsere Datei rijndael.inc.php, die alle
zuvor beschriebenen Funktionen beinhaltet.
Um den Text aus der zuvor erhaltenen Danbankabfrage weiter zu bearbeiten,
übergeben wir diesen der Funktion decryptAES() (48) und erhalten, falls das
Passwort richtig ist, unseren entschlüsselten Text in die Variable $decrypted
zurück.
Mit einer switch-Abfrage
(50) überprüfen wir jetzt, welche Aufgabe wir erledigen
müssen. Mögliche Aufgaben wären:
- case 2 IV-Tag-Download
- case 3 Rijndael-Download
– also der verschlüsselte Text
- case 4 Datensatz löschen
- default Datensatz entschlüsseln
Vielleicht wundern Sie sich jetzt, weshalb wir den verschlüsselten Text vor der
switch-Abfrage
entschlüsselt haben. Sicherlich erinnern Sie sich noch, wie wir
überprüfen, ob eine Entschlüsselung funktioniert hat und eine Aufgabe, wie
z. B. das Löschen, durchgeführt werden darf.
Wir überprüfen jeweils die MD5-Prüfsumme
aus dem entschlüsselten Text mit
der MD5-Prüfsumme,
die beim Erstellen der Verschlüsselung generiert wurde.
Falls der Download der IV-Tag
Datei angefordert (52) wurde, übergeben wir
unseren entschlüsselten Text und die MD5-Prüfsumme
aus der Datenbank an
die Funktion checkDecrypt() (54). Stimmen beide Prüfsummen überein, so
erhalten Sie als Rückgabewert „TRUE“, ansonsten „FALSE“.
War die Überprüfung erfolgreich (TRUE), können wir im nächsten Schritt mit
der Funktion sendIV() (55) die IV-Tag
Datei zum Download anbieten und
brechen danach unsere switch-Abfrage
mit break (56) ab.
Mit dem Download der Rijndael-Datei
(57-61),
also unseres verschlüsselten
Textes, verfahren wir ebenso. Wir überprüfen unsere MD5-Prüfsummen
und
starten im Erfolgsfall den Download über die Funktion sendEncrypt().
Beim Löschen der Datei verhält es sich ebenso wie bei den vorangegangenen
Aufgaben. Wir überprüfen zuerst die Prüfsummen (64) und werden im Anschluss
daran den Datensatz im Erfolgsfall löschen (66). Da wir den Datensatz
bereits entschlüsselt haben und ihn nicht mehr anzeigen wollen, müssen wir
an dieser Stelle noch die Variable $decrypted löschen (67).
Erst am Ende, also wenn keine andere Aufgabe ausgewählt wurde, wird der
eigentliche entschlüsselte Text aufbereitet (70). Aufbereitet ist wohl nicht ganz
das richtige Wort, immerhin ist der Text ja schon entschlüsselt. Wir müssen
trotzdem auch hier eine Überprüfung vornehmen und die Prüfsummen vergleichen.
Zusätzlich speichern wir das Datum und die Uhrzeit dieses Zugriffs
in die Datenbank. Je nach Fall können folgende Ereignisse gespeichert werden:
- Das Datum und die Uhrzeit bei einer gelungenen Entschlüsselung
- Das Datum und die Uhrzeit bei einem Fehlversuch
Die Entschlüsselung ist somit abgeschlossen, und wir können unsere HTML-Darstellung
aufbauen, also unsere PHP-Variablen
ausgeben. Wie bereits erwähnt,
wird an dieser Stelle nicht der HTML-Quellcode
angezeigt, da er nur
unnötige Seiten füllen würde. An den Stellen, an denen etwas ausgegeben wird
(z. B. die InfoBox),
stehen einzelne PHP-Tags
mit echo-Ausgaben.
016:
017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032:
033:
034: 035: 036: 037: 038: 039: 040: 041: 042: 043: 044: 045: 046: 047: 048:
049:
050: 051: 052: 053: 054: 055: 056: 057: 058: 059: 060: 061: 062: 063: 064: 065: 066:
067:
068: 069: 070: 071: 072:
073:
074: 075: 076: 077: 078: 079: 080: 081: 082:
| $error = false;
if(isset($_POST['decode'])) { if(empty($_POST['password'])) { $error = true; $decodemessage = 'Bitte geben Sie ein Passwort ein<br>'; } if(!$error) { $id = $_POST['decode'] + 0;
$sqlDecrypt = "SELECT id, textaes, block,
DATE_FORMAT(encrypt,'%m.%m.%Y %H:%i:%s') AS encrypt, DATE_FORMAT(decrypt,'%m.%m.%Y %H:%i:%s') AS decrypt, DATE_FORMAT(decryptError,'%m.%m.%Y %H:%i:%s')
AS decryptError, ivTag, md5 FROM " . $db['table'] . " WHERE id = $id"; $status = @mysql_query($sqlDecrypt); if(@mysql_num_rows($status) == "1") {
$infoText['bit'] = @mysql_result($status,0,"block") . ' Bit';
$infoText['encrypt'] = @mysql_result($status,0,"encrypt");
$infoText['decrypt'] = @mysql_result($status,0,"decrypt");
$infoText['decryptError'] = @mysql_result($status,0,"decryptError");
$infoText['md5'] = @mysql_result($status,0,"md5");
$infoText['content'] = @mysql_result($status,0,"textaes");
$infoText['iv'] = @mysql_result($status,0,"ivTag"); include_once("rijndael.inc.php"); $decrypted = decryptAES($infoText['content'],$infoText['iv'],
$_POST['password'],$infoText['bit']);
switch ($_POST['job']) { case 2: // IV-Tag Download if(checkDecrypt($decrypted,$infoText['md5'])) sendIV($infoText['iv'],$infoText['md5'],$infoText['bit']); break; case 3: // Rijndael Download if(checkDecrypt($decrypted,$infoText['md5'])) sendEncrypt($infoText['content'],$infoText['md5']); break; case 4: // Löschen if(checkDecrypt($decrypted,$infoText['md5'])) { $sqlDelete = @mysql_query("DELETE FROM " .
$db['table'] . " WHERE id = $id"); unset($decrypted); } break; default: // Entschlüsseln $decodemessage = checkDecrypt($decrypted,
$infoText['md5'],$id,true); } } else { $decodemessage = 'Keine Daten vorhanden!<br>'; } } }
|
Beispiel 12.22: rijndael.php
Zum Schluss werden aus der Datenbank noch alle Datensätze, also die Infotexte,
geholt (149) und in einer Drop-Down-Box
(155) angezeigt. Anhand
dieser Infotexte können Sie jetzt gezielt den Datensatz auswählen, den Sie
entschlüsseln, löschen oder sich per Download zuschicken lassen wollen.
148:
149:
150:
151: 152: 153: 154: 155: 156:
157:
| // Holt alle Daten
$sqlShow = @mysql_query("SELECT id, infotext FROM " . $db['table'] .
" ORDER BY id");
while($row = @mysql_fetch_row($sqlShow)) { $selected = ''; if($_POST['decode'] == $row[0]) $selected = 'selected'; $data .= '<option value="'.$row[0].'" '.$selected.'>'.$row[1].'</option>'; } ?>
|
Beispiel 12.23: rijndael.php
Wie Sie sehen, haben wir hier ein voll funktionstüchtiges Programm erstellt,
das sogar unter realen Bedingungen genutzt werden kann. Wir hoffen, dieses
Beispiel hat Ihnen einen Anreiz gegeben, das vorliegende Programm zu
erweitern und zu modifizieren.
Ich würde mich sehr darüber freuen, wenn Sie sich derart engagieren und
uns Ihr modifiziertes Skript zusenden, sodass wir es eventuell auf SELFPHP
veröffentlichen können – selbstverständlich mit dem Hinweis darauf, dass Sie
der Autor sind.
Wir wollen das Thema Kryptografie an dieser Stelle beenden. Es war zwar nur
ein kleiner Ausblick, der Ihnen aber hoffentlich Freude gemacht hat und Sie
anspornt, Ihre Kenntnisse in diesem interessanten Thema zu vertiefen.
Dieses Skript aus dem SELFPHP KOCHBUCH wurde von SELFPHP unter dem "Tarif Mc500" von McAc.net-Webhosting erfolgreich ausgeführt und getestet!
Auf der Übersichtseite unter "McAc.net – Webhosting zu diesem Buch" finden Sie weitere Informationen zu dem Webhostingpaket, dass durch SELFPHP getestet wurde.
|