REDAXO-Addon zur transparenten Feldverschlüsselung in YForm-Tabellen.
Verschlüsselt sensible YForm-Felder serverseitig mit libsodium (XSalsa20-Poly1305). Die Daten werden verschlüsselt in der Datenbank gespeichert und im Backend automatisch entschlüsselt angezeigt. Der Schlüssel liegt außerhalb des Webroots.
- 🔐 Transparente Verschlüsselung – YForm-Felder werden beim Speichern automatisch ver- und beim Anzeigen entschlüsselt, ohne Änderungen am Formular
- 🗝️ Schlüssel außerhalb des Webroots – als Datei oder Umgebungsvariable (
YFORM_ENCRYPTION_KEY), kompatibel mit Plesk, Docker, Apache, Nginx - 📋 Feldzuordnung per Backend – pro Tabelle einzelne Felder zur Verschlüsselung auswählen, keine Codeänderungen nötig
- 🔄 Bulk-Migration – bestehende Datensätze nachträglich ver- oder entschlüsseln, gesichert durch SessionGuard (Re-Authentifizierung)
- 📊 Integrierter CSV- und Excel-Export – entschlüsselte Daten exportieren, nutzbar für alle YForm-Tabellen (auch unverschlüsselte), inklusive Dokument-Metadaten (Autor, Zeitstempel, Domain)
- 🔎 Info-Seite – zeigt Schlüsselstatus, Quelle und verschlüsselte Felder je Tabelle
- 🛡️ Feingranulare Berechtigungen – Addon-Verwaltung nur für Admins; der Export (CSV/Excel) kann über die Rolle
yform_encryption[export]auch nicht-admininistativen Backend-Nutzern erlaubt werden - 🔗 PHP-API –
Helper-Klasse für einfachen Zugriff aus Modulen und Templates
- REDAXO ≥ 5.18
- PHP ≥ 8.1 mit aktivierter
sodium-Extension - YForm ≥ 5.0
- Inkompatibel mit dem Addon
yform_export(eigener Export ist integriert)
- Addon über den REDAXO-Installer installieren oder manuell in
redaxo/src/addons/yform_encryption/ablegen. - Im REDAXO-Backend unter YForm Encryption → Einstellungen den Schlüsselpfad konfigurieren (Verzeichnis außerhalb des Webroots empfohlen).
- Schlüssel generieren lassen oder vorhandenen Schlüssel hinterlegen.
| Einstellung | Beschreibung |
|---|---|
| Schlüsselpfad | Absoluter Pfad zur Schlüsseldatei, idealerweise außerhalb des Webroots |
| Schlüssel generieren | Neuen libsodium-Schlüssel erzeugen und speichern |
Statt den Schlüssel in einer Datei zu speichern, kann er als Systemumgebungsvariable YFORM_ENCRYPTION_KEY hinterlegt werden. Das Addon prüft diese Variable zuerst – vor dem Dateipfad.
Der Wert muss der Base64-kodierte 32-Byte-Schlüssel sein (wird im Backend unter „Einstellungen → Schlüssel anzeigen" angezeigt).
- Plesk → Domain → Apache & nginx-Einstellungen
- Im Feld „Zusätzliche Apache-Direktiven" (HTTP oder HTTPS):
SetEnv YFORM_ENCRYPTION_KEY "IhrBase64SchluesselHier==" - Speichern – Plesk schreibt die Direktive in die vHost-Konfiguration.
Alternativ über die Plesk-Erweiterung „Node.js/PHP Environment Variables" oder direkt in der php.ini der Domain:
; Plesk → PHP-Einstellungen → Zusätzliche Direktiven
env[YFORM_ENCRYPTION_KEY] = "IhrBase64SchluesselHier=="In docker-compose.yml:
services:
web:
image: your-redaxo-image
environment:
YFORM_ENCRYPTION_KEY: "IhrBase64SchluesselHier=="Oder mit einer .env-Datei (niemals ins Repository einchecken!):
# .env
YFORM_ENCRYPTION_KEY=IhrBase64SchluesselHier==# docker-compose.yml
services:
web:
env_file:
- .envBeim direkten docker run:
docker run -e YFORM_ENCRYPTION_KEY="IhrBase64SchluesselHier==" your-redaxo-imageIn der VirtualHost-Konfiguration oder .htaccess:
# /etc/apache2/sites-available/ihre-domain.conf ODER .htaccess
SetEnv YFORM_ENCRYPTION_KEY "IhrBase64SchluesselHier=="
.htaccessist weniger sicher als die VirtualHost-Konfiguration, da sie im Webroot liegen kann. Den.htaccess-Eintrag unbedingt außerhalb des öffentlich zugänglichen Verzeichnisses setzen oder perDeny from allschützen.
Nginx selbst unterstützt SetEnv nicht – die Variable muss im PHP-FPM-Pool gesetzt werden:
# /etc/php/8.x/fpm/pool.d/ihre-domain.conf
env[YFORM_ENCRYPTION_KEY] = "IhrBase64SchluesselHier=="Nach dem Bearbeiten PHP-FPM neu starten:
systemctl restart php8.x-fpmFür systemd-verwaltete PHP-FPM-Dienste in der Override-Konfiguration:
systemctl edit php8.x-fpm[Service]
Environment="YFORM_ENCRYPTION_KEY=IhrBase64SchluesselHier=="Global für alle Prozesse (weniger empfohlen):
# /etc/environment
YFORM_ENCRYPTION_KEY="IhrBase64SchluesselHier==".env-Dateien niemals in Git einchecken –.gitignore-Eintrag prüfen.- Berechtigungen von Konfigurationsdateien mit dem Schlüssel auf
640oder600setzen. - In Shared-Hosting-Umgebungen lieber die Schlüsseldatei außerhalb des Webroots verwenden, da Umgebungsvariablen u.U. durch
phpinfo()sichtbar werden.
Unter YForm Encryption → Feldzuordnung können pro YForm-Tabelle einzelne Felder zur Verschlüsselung markiert werden.
Folgende YForm-Feldtypen können verschlüsselt werden:
| Feldtyp | Beschreibung | Typischer Anwendungsfall |
|---|---|---|
text |
Einzeiliges Textfeld | Name, Vorname, Ausweisnummer, Tokens |
textarea |
Mehrzeiliges Textfeld | Notizen, Anamnese, Freitexte mit sensiblem Inhalt |
email |
E-Mail-Adresse | Kontaktdaten mit erhöhtem Schutzbedarf |
phone |
Telefonnummer | Mobil-/Festnetznummern |
url |
URL-Feld | Interne Links, Token-URLs |
ip |
IP-Adresse | Logging, DSGVO-relevante Netzwerkdaten |
fields_iban |
IBAN (fields-Addon) | Bankverbindungen – besonders schützenswert |
fields_inline |
Inline-Gruppe (fields-Addon) | Kombinierte Felder z.B. Adresse + IBAN |
Nicht verschlüsselbar (und auch nicht sinnvoll):
- Auswahlfelder (
select,choice,checkbox,radio) – zu wenige diskrete Werte, Verschlüsselung bringt keinen Sicherheitsgewinn - Relationsfelder (
be_relation,relation) – nur IDs, kein personenbezogener Inhalt - Zahlenfelder (
integer,float) – Datenbanktyp inkompatibel mit Ciphertext-String - Datumsfelder (
date,datetime) – oft für Sortierung/Filterung nötig, Verschlüsselung würde Abfragen komplett blockieren be_media,upload– Dateiname/Pfad, Dateiinhalt selbst liegt im Dateisystem
Nach dem Speichern der Feldzuordnung werden neue Einträge automatisch verschlüsselt gespeichert. Bestehende Daten können über die Migration-Funktion nachträglich verschlüsselt werden.
Das Addon ersetzt yform_export und bringt einen eigenen, vollwertigen Exporter mit:
- In der YForm-Datenliste erscheinen CSV- und Excel (XLSX)-Buttons für jede Tabelle.
- Verschlüsselte Felder werden beim Export automatisch entschlüsselt.
- Funktioniert auch für vollständig unverschlüsselte Tabellen – der Exporter ist ein vollwertiger Ersatz für
yform_exportund kann für beliebige YForm-Tabellen genutzt werden. - Die Excel-Datei enthält Dokument-Metadaten: Autor (eingeloggter REDAXO-User), Exportzeitpunkt, Sitetitel und Domain.
- CSV-Export mit UTF-8-BOM für korrekte Darstellung in Excel.
- Spaltenbezeichnungen aus den YForm-Feldlabels (nicht die Datenbankspaltenname).
- Erste Zeile in Excel fett formatiert, Spaltenbreite automatisch, erste Zeile eingefroren.
Berechtigung: Der Export steht Admins sowie allen Nutzern zur Verfügung, denen in der Rollenverwaltung die Berechtigung yform_encryption[export] zugewiesen wurde. Die Buttons erscheinen nur für berechtigte Nutzer.
Die integrierte YForm-Datenlisten-Suche kann verschlüsselte Felder nicht durchsuchen.
Der Grund: Die Suche arbeitet mit SQL-LIKE-Abfragen direkt auf der Datenbank. Verschlüsselte Werte liegen als Ciphertext vor – ein Klartext-Suchbegriff kann dort keine Treffer finden.
Betroffen sind alle als verschlüsselt markierten Felder. Nicht-verschlüsselte Felder derselben Tabelle (z.B. id, Datumsfelder, Status-Felder) sind weiterhin normal durchsuchbar.
Workaround: Den CSV- oder Excel-Export nutzen und lokal in der Tabellenkalkulation suchen – die exportierten Daten sind vollständig entschlüsselt.
Empfehlung: Nur wirklich sensible Felder verschlüsseln (IBAN, Ausweisdaten, Gesundheitsdaten, Tokens). Felder, nach denen häufig gesucht wird (z.B. Name, E-Mail), nur verschlüsseln wenn ein erhöhtes Breach-Risiko besteht – dann ist der Komfortverlust durch die eingeschränkte Suche bewusst in Kauf zu nehmen.
Massenoperationen wie das nachträgliche Ver- oder Entschlüsseln bestehender Datensätze (Migration) sind durch einen zusätzlichen Authentifizierungsschritt gesichert – den SessionGuard.
Ablauf:
- Unter YForm Encryption → Feldzuordnung eine Bulk-Aktion auslösen (z.B. „Alle bestehenden Datensätze verschlüsseln").
- Das System fordert eine erneute Eingabe von REDAXO-Benutzername und Passwort.
- Nach erfolgreicher Eingabe ist die Session für 30 Minuten freigeschaltet.
- Weitere Bulk-Aktionen innerhalb dieses Zeitfensters erfordern keine erneute Eingabe.
- Nach Ablauf des Timeouts (oder manueller Sperrung) muss erneut authentifiziert werden.
Der Timeout ist nicht über das Backend-UI änderbar. Er wird in der
package.ymldes Addons alssession_timeout(in Sekunden) konfiguriert. Standard:1800(30 Minuten).
Warum dieser zusätzliche Schutz?
Bulk-Operationen schreiben alle Datensätze einer Tabelle um. Ein versehentlicher Klick – oder ein kompromittiertes Admin-Konto das gerade in der Session läuft – könnte sonst alle verschlüsselten Daten im Klartext in die DB schreiben. Die erneute Passwortabfrage stellt sicher, dass die Aktion bewusst von einer autorisierten Person ausgelöst wird.
- Den Schlüssel regelmäßig sichern – ohne Schlüssel sind verschlüsselte Daten unwiederbringlich verloren.
- Den Schlüssel niemals im Webroot ablegen.
- Den Schlüssel nicht in der Versionsverwaltung tracken.
- Bei einem Server-Umzug den Schlüssel separat übertragen.
Alle Klassen liegen im Namespace FriendsOfREDAXO\YFormEncryption\ und werden von REDAXO automatisch geladen.
Die einfachste Klasse für den Zugriff aus Modulen, Addons oder Templates.
use FriendsOfREDAXO\YFormEncryption\Helper;| Methode | Rückgabe | Beschreibung |
|---|---|---|
Helper::getDecryptedRow(string $tableName, int $id) |
?array |
Einzelnen Datensatz laden und alle verschlüsselten Felder entschlüsseln |
Helper::getDecryptedTable(string $tableName, string $where, string $orderBy, int $limit, int $offset) |
array |
Mehrere Datensätze laden und entschlüsseln |
Helper::decryptValue(string $value) |
string |
Einzelnen Wert entschlüsseln (gibt Klartext zurück, auch wenn nicht verschlüsselt) |
Helper::encryptValue(string $value) |
string |
Einzelnen Wert verschlüsseln |
Helper::isEncrypted(string $value) |
bool |
Prüfen ob ein Wert verschlüsselt ist |
Helper::getEncryptedFieldsForTable(string $tableName) |
array |
Liste der verschlüsselten Feldnamen für eine Tabelle |
Beispiel:
$row = Helper::getDecryptedRow('rex_my_table', 42);
echo $row['iban']; // entschlüsselt
$rows = Helper::getDecryptedTable('rex_my_table', 'status = 1', 'id DESC', 50);use FriendsOfREDAXO\YFormEncryption\EncryptionService;
$enc = EncryptionService::getInstance();| Methode | Rückgabe | Beschreibung |
|---|---|---|
getInstance() |
self |
Singleton-Instanz |
encrypt(string $plaintext) |
string |
Text verschlüsseln (mit Prefix) |
decrypt(string $encrypted) |
string |
Text entschlüsseln |
decryptSafe(string $value) |
string |
Entschlüsseln ohne Exception – gibt Originalwert bei Fehler zurück |
isEncrypted(string $value) |
bool |
Präfix-Prüfung |
encryptFields(array $data, array $fields) |
array |
Mehrere Felder eines Datensatzes verschlüsseln |
decryptFields(array $data, array $fields) |
array |
Mehrere Felder eines Datensatzes entschlüsseln |
getPrefix() |
string |
Verschlüsselungs-Präfix (statisch) |
use FriendsOfREDAXO\YFormEncryption\FieldMapper;
$mapper = FieldMapper::getInstance();| Methode | Rückgabe | Beschreibung |
|---|---|---|
getInstance() |
self |
Singleton-Instanz |
getEncryptedFields(string $tableName) |
array |
Alle verschlüsselten Feldnamen einer Tabelle |
hasEncryptedFields(string $tableName) |
bool |
Hat die Tabelle verschlüsselte Felder? |
isFieldEncrypted(string $tableName, string $fieldName) |
bool |
Ist ein bestimmtes Feld verschlüsselt? |
addField(string $tableName, string $fieldName) |
void |
Feld zur Verschlüsselung hinzufügen |
removeField(string $tableName, string $fieldName) |
void |
Feld aus der Verschlüsselung entfernen (Mapping löschen) |
getAllMappings() |
array |
Alle Zuordnungen als ['table' => ['field1', 'field2']] |
getAvailableTablesAndFields() |
array |
Alle YForm-Tabellen mit verschlüsselbaren Feldern |
use FriendsOfREDAXO\YFormEncryption\KeyManager;
$km = KeyManager::getInstance();| Methode | Rückgabe | Beschreibung |
|---|---|---|
getInstance() |
self |
Singleton-Instanz |
hasKey() |
bool |
Ist ein Schlüssel verfügbar? |
getKey() |
string |
Rohen Schlüssel-Binärstring liefern |
getKeySource() |
string |
Herkunft des Schlüssels: environment, file, data_dir |
getKeyFilePath() |
string |
Pfad zur konfigurierten Schlüsseldatei |
generateKey(string $location) |
string |
Neuen Schlüssel erzeugen ('file' oder 'data_dir') |
Schlüsselpriorität: YFORM_ENCRYPTION_KEY (Env) → konfigurierter Dateipfad → data/-Verzeichnis
use FriendsOfREDAXO\YFormEncryption\SessionGuard;
$guard = SessionGuard::getInstance();| Methode | Rückgabe | Beschreibung |
|---|---|---|
getInstance() |
self |
Singleton-Instanz |
isUnlocked() |
bool |
Ist die Session aktuell entsperrt? |
authenticate(string $login, string $password) |
bool |
Authentifizieren und Session entsperren |
unlock() |
void |
Session manuell entsperren (ohne Passwort) |
lock() |
void |
Session sofort sperren |
getRemainingTime() |
int |
Verbleibende Sekunden bis zum Timeout |
getTimeout() |
int |
Konfigurierten Timeout in Sekunden liefern |
use FriendsOfREDAXO\YFormEncryption\ColumnMigrator;| Methode | Rückgabe | Beschreibung |
|---|---|---|
ColumnMigrator::checkColumns(string $tableName, array $fields) |
array |
Prüfen welche Spalten auf TEXT erweitert werden müssen |
ColumnMigrator::migrateColumns(string $tableName, array $fields) |
int |
Spalten auf TEXT migrieren, gibt Anzahl geänderter Spalten zurück |
ColumnMigrator::getWarnings() |
array |
Warnungen der letzten Migration abrufen |
Ciphertexte sind länger als Klartexte –
VARCHAR-Spalten werden bei Bedarf automatisch aufTEXTerweitert.
MIT – siehe LICENSE.md
Autor: FriendsOfREDAXO
Support: https://github.com/FriendsOfREDAXO/yform_encryption