Wie man sensible Daten in einer Datenbank speichert (AES_ENCRYPT)

AES_ENCRYPTImmer wieder hört man davon dass Datenbanken gehackt und sensible Daten wie Kreditkartennummern oder eMail-Adressen entwendet wurden. In diesem Tutorial möchte ich nun einen Weg zeigen, wie man sensible Daten relativ sicher per AES_Encrypt in einer Datenbank speichert.

Sicher gibt es auch hier mehr als eine Methode um Daten sicher oder relativ sicher speichern zu können. AES_ENCRYPT() und AES_DECRYPT() gelten jedoch als die aus kryptografischer Sicht sichersten Verschlüsselungsfunktionen, die derzeit in MySQL zur Verfügung stehen.

Beachten Sie aber dass die verschlüsselte Speicherung von Daten nicht verhindert das Ihre Datenbank gehackt wird, sie dient lediglich dafür das Ihre Daten nicht so ohne weiteres ausgelesen und für kriminelle Machenschaften verwendet werden können.

Die Funktionen AES_ENCRYPT(str, key) und AES_DECRYPT(str, key) gestatten die Ver- und Entschlüsselung von Daten mithilfe des offiziellen AES-Algorithmus (Advanced Encryption Standard). Die Verschlüsselung erfolgt mit einem 128-Bit-Schlüssel, der durch Modifizierung des Quellendes sogar noch auf 256 Bits erweitert werden kann. Die Funktionen AES_ENCRYPT und AES_DECRYPT erwarten zwei Parameter, Parameter1 ist der zu verschlüsselnde Wert und Parameter2 ist der Schlüssel mit dem der Wert verschlüsselt werden soll.

Mit AES_ENCRYPT wird ein String verschlüsselt, wobei als Ergebnis ein Binärwert zurückgegeben wird.
Mit AES_DECRYPT wird der verschlüsselte Binärwert entschlüsselt und als Original String zurückgegeben.

Weiterführende Informationen zu AES_ENCRYPT und AES_DECRYPT finden Sie auf dev.mysql.com


Datenbank

Ein Feld in dem AES_ENCRYPT verschlüsselte Daten gespeichert werden sollen, sollte im Format BLOB oder VARBINARY vorliegen um Datenverluste zu verhindern.

Für dieses Tutorial legen wir zunächst eine Datenbanktabelle an, in der Kundendaten wie Name, Vorname und Geburtsdatum, Logindaten und eMailadresse gespeichert werden sollen. Natürlich sollte man Verschlüsselung auch für Konto und Kreditkartendaten verwenden.

Anlegen der MySQL-Datenbank

CREATE TABLE `kundendaten` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `vorname` varchar(50) DEFAULT NULL,
  `nachname` varchar(50) DEFAULT NULL,
  `geburtsdatum` varbinary(128) DEFAULT NULL,
  `username` varbinary(128) DEFAULT NULL,
  `passwort` varbinary(128) DEFAULT NULL,
  `email` varbinary(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Sensible Daten in der Datenbank speichern

Für die AES-Funktionen benötigen wir einen sicheren Schlüssel. Dieser sollte wie jedes sichere Passwort aus Buchstaben, Zahlen und Sonderzeichen bestehen und länger als 8 Zeichen sein. Ganz wichtig zu erwähnen ist hier, dass der Schlüssel weder in einer normalen Text oder HTML Datei gespeichert auf dem Server abgelegt werden sollte, noch dass der Schlüssel in der selben Datenbank gespeichert werden sollte, in der die zu verschlüsselnden Daten abgelegt werden.

Ich lege für dieses Beispiel eine Datei mit dem Namen „config.inc.php“ an und speichere diese im Verzeichnis „includes“ die Zugriffsrechte der Datei und des Ordners liegen bei 644. In dieser Datei speichere ich meinen Schlüssel in der Variablen $AES_SALT.

config.inc.php

<?php
if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) exit('No direct access allowed.');

$AES_SALT = 'byot4Yods8yoK5eF2qUiv5Uv2jeut7';
?>

Datenbankverbindung herstellen

Meine MySQL-Zugangsdaten läge ich immer in eine externe Datei aus die ich mittels include in jede Datei einbinde, die Zugriff auf die Datenbank benötigt. Der Vorteil dabei ist, dass ich nur eine Datei bearbeiten muss wenn ich mal mein Passwort ändere oder ich zu einem neuen Provider umziehe.

Legen Sie also eine neue Datei mit dem Namen „mySQLi.inc.php“ an und speichern Sie diese im Verzeichnis „includes“
fügen Sie folgenden Code in diese Datei ein, passen Sie Ihre Zugangsdaten an und speichern Sie die Datei!

mysqli.inc.php

<?php
if (__FILE__ == $_SERVER['SCRIPT_FILENAME']) exit('No direct access allowed.');

$DB_SERVER   = "localhost";
$DB_NAME     = "DATENBANKNAME";
$DB_USER     = "DATENBANKUSER";
$DB_PASSWORD = "DATENBANKPASSWORT";
 
$db = new mysqli($DB_SERVER, $DB_USER, $DB_PASSWORD, $DB_NAME);
 
if (mysqli_connect_errno()) {
 printf("db-connection Error: %s\n", mysqli_connect_error());
 exit();
}

if (!$db->set_charset("utf8")) {
  printf("Error loading character set utf8: %s\n", $db->error);
}
?>

 

Kundendaten in Datenbank speichern

Legen Sie am besten eine neue Datei an und benennen Sie diese „newCustomer.php“. Wird diese Seite aufgerufen dann sehen Sie folgendes Formular, in dem Sie die Kundendaten eingeben können.

<form id="form1" method="post">
<table>
  <tr>
    <td>Vorname:</td>
    <td><input type="text" name="vorname"></td>
  </tr>
  <tr>
    <td>Nachname:</td>
    <td><input type="text" name="nachname"></td>
  </tr>
  <tr>
    <td>Geburtsdatum:</td>
    <td><input type="date" name="geburtsdatum"></td>
  </tr>
  <tr>
    <td>Username:</td>
    <td><input type="text" name="username"></td>
  </tr>
  <tr>
    <td>Passwort:</td>
    <td><input type="password" name="passwort"></td>
  </tr>
  <tr>
    <td>eMail:</td>
    <td><input type="email" name="email"></td>
  </tr>
  <tr>
    <td></td>
    <td><input type="submit" name="MM_SUBMIT" value="Speichern"></td>
  </tr>
</table>  
</form>

Kundendaten Eingabeformular

Sobald das Formular über den „Speichern“ Button abgeschickt wird, wird folgender PHP-Code aufgerufen.

Setzen Sie diesen Code an den Anfang der Datei „newCustomer.php“, also oberhalb des Formulars. In diesem Code werden  zunächst die zwei Dateien „mysqli.inc.php“ und „config.inc.php“ aus dem Verzeichnis „includes“ eingebunden.

In diesem Code wird zunächst geprüft ob das Formular über den Button „Speichern“ abgeschickt wurde.
Anschließend werden die Werte der einzelnen Eingabefelder Variablen zugewiesen, wobei zuvor spezielle Zeichen mittels mysqli_escape_string() maskiert werden. mysqli_escape_string() ist übrigens ein Alias für mysqli_real_escape_string().

Danach werden die Daten über prepared Statements in die Datenbank geschrieben.

include('includes/mysqli.inc.php');
include('includes/config.inc.php');

if(isset($_POST['MM_SUBMIT']) && $_POST['MM_SUBMIT'] == 'Speichern')
{
  $vorname  = mysqli_escape_string($db, $_POST['vorname']);
  $nachname = mysqli_escape_string($db, $_POST['nachname']);
  $geburtsd = mysqli_escape_string($db, $_POST['geburtsdatum']); 
  $username = mysqli_escape_string($db, $_POST['username']);
  $passwort = mysqli_escape_string($db, $_POST['passwort']);
  $email    = mysqli_escape_string($db, $_POST['email']);

  if($stmt = $db->prepare("INSERT INTO `kundendaten` (`vorname`,`nachname`,`geburtsdatum`,`username`,`passwort`,`email`) 
                           VALUES (?,?,AES_ENCRYPT(?,'$AES_SALT'),?,AES_ENCRYPT(?,'$AES_SALT'),AES_ENCRYPT(?,'$AES_SALT'))"))
  {
    $stmt->bind_param("ssssss",$vorname,$nachname,$geburtsd,$username,$passwort,$email);
    $stmt->execute();
    $stmt->close();
    $lastid = $db->insert_id;
  }
}
?>

Wenn Sie sich nun den Inhalt der Werte in der Datenbank anschauen dann werden Sie die zuvor eingegebenen Werte in dieser Art vorfinden. Sie sehen das Geburtsdatum, Passwort und eMail-Adresse verschlüsselt gespeichert wurden.
ASC_DECRYPT_DBENTRY

Kundendaten aus Datenbank auslesen

ASC_DECRYPTED DATA

Um nun die original eingegebenen Daten in Klartext wieder auslesen zu können, bedienen wir uns der Funktion AES_DECRYPT().

Wir bleiben bei der Datei „new_customer.php“ und fügen direkt unter dem Formular folgenden code zum auslesen des zuvor eingegebenen Datensatzes ein.

<?php
if($stmt = $db->prepare("SELECT `vorname`,`nachname`, 
                                 AES_DECRYPT(`geburtsdatum`, '$AES_SALT') AS `geburtsdatum`, 
                                `username`, AES_DECRYPT(`passwort`, '$AES_SALT') AS `passwort`, 
                                 AES_DECRYPT(`email`, '$AES_SALT') AS `email` FROM `kundendaten` 
                                 WHERE id = ?"))
{
  $stmt->bind_param("i", $lastid);
  $stmt->execute();
  $stmt->store_result();
  $anzahl = $stmt->num_rows;
  $stmt->bind_result($vorname,$nachname,$geburtsdatum,$username,$passwort,$email);
  if($anzahl > 0)
  {
    while($stmt->fetch())
    {
      echo "Vorname: ".$vorname . "<br />";
      echo "Nachname: ".$nachname. "<br />";
      echo "Geburtsdatum: ".$geburtsdatum. "<br />";
      echo "Username: ".$username. "<br />";
      echo "Passwort: ".$passwort. "<br />";
      echo "eMail: ".$email. "<br />";
    }
    $stmt->free_result();
    $stmt->close();
    $db->close();
  }
}
?>

 

Sie sehen das man mit einfachen Mitteln viel tun kann um seine Daten vor unberechtigtem Zugriff zu schützen.
Ich hoffe Ihnen hat dieses Tutorial gefallen und würde mich über Fragen, Anregungen und Tipps in den Kommentaren freuen.

Über Enrico S.

Programmierer, Webdesigner, Grafiker, Blogger, Screencaster, Arduino- und eMobility Enthusiast. nefilim3006 ist auch bei Google+ vertreten

Kommentare geschlossen.