Steuerkram/scripts/encrypt_bank_secrets.php
fds2610-bot 995b52fbd3 Feature: FinTS-Direktverbindung und vereinheitlichte Importquellen
- FinTS-Abruf für Comdirect/DKB/Sparkassen via nemiah/php-fints (4.1)
  inkl. photoTAN-Eingabe-Modal und Multi-Konto-Auswahl
- Neue Tabelle bank_sources (CSV/API/FinTS) ersetzt bank_import_formats
  und bank_connections, Backfill in Migration 068
- Symmetrische Verschlüsselung sensibler Felder (PayPal-Signature,
  FinTS-PIN) mit AES-256-GCM, APP_KEY in .env
- Routes /bank/fints* → /bank/direkt*; "+ Neue Bank…"-Dialog erlaubt
  freie API/FinTS-Anbieter
- Scripts/encrypt_bank_secrets.php als idempotenter Migrations-Helfer
- Neue Tests 36 (Crypto) und 37 (BankSource)
2026-05-22 07:17:00 +02:00

64 lines
1.9 KiB
PHP

<?php
/**
* Verschlüsselt die nach Migration 068 noch im Klartext in bank_sources liegenden
* Felder (client_id_enc, secret_enc, pin_enc) mit dem APP_KEY.
*
* Das Skript ist idempotent: bereits verschlüsselte Werte (Magic-Prefix "enc:v1:")
* werden übersprungen. Nach Ausführung kann es gefahrlos erneut aufgerufen werden.
*
* Aufruf:
* docker compose exec web php scripts/encrypt_bank_secrets.php
*
* Voraussetzung: APP_KEY in .env gesetzt (64-stellige Hex-Zeichenkette).
*/
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use Steuerkram\Config;
use Steuerkram\Database;
use Steuerkram\Services\Crypto;
Config::load();
if ((string)Config::get('app_key', '') === '') {
fwrite(STDERR, "FEHLER: APP_KEY ist nicht gesetzt. Bitte zuerst in .env hinterlegen.\n");
fwrite(STDERR, "Generieren mit: php -r \"echo bin2hex(random_bytes(32));\"\n");
exit(1);
}
$rows = Database::fetchAll('SELECT id, client_id_enc, secret_enc, pin_enc FROM bank_sources');
$touched = 0;
$skipped = 0;
foreach ($rows as $row) {
$update = [];
foreach (['client_id_enc', 'secret_enc', 'pin_enc'] as $field) {
$value = $row[$field] ?? null;
if ($value === null || $value === '') {
continue;
}
if (Crypto::isEncrypted((string)$value)) {
continue;
}
$update[$field] = Crypto::encrypt((string)$value);
}
if (empty($update)) {
$skipped++;
continue;
}
$sets = implode(', ', array_map(fn($k) => "$k = ?", array_keys($update)));
$params = array_values($update);
$params[] = (int)$row['id'];
Database::execute("UPDATE bank_sources SET $sets WHERE id = ?", $params);
$touched++;
echo "Verschlüsselt: bank_sources.id={$row['id']} (Felder: " . implode(', ', array_keys($update)) . ")\n";
}
echo "\n";
echo "Fertig: {$touched} Zeile(n) aktualisiert, {$skipped} bereits verschlüsselt oder leer.\n";