diff --git a/.gitignore b/.gitignore index 7775ee0..4746614 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ househub_db_data .env +data/.hh_app_secret diff --git a/docker-compose.yml b/docker-compose.yml index e08317c..d06e235 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,8 @@ services: DB_NAME: ${DB_NAME:-househub} DB_USER: ${DB_USER:-househub} DB_PASS: ${DB_PASS:-changeme} + # Clé applicative pour chiffrer les secrets (iCloud, etc.). Optionnel si absent : fichier data/.hh_app_secret ou dérivation DB. + APP_SECRET_KEY: ${APP_SECRET_KEY:-} volumes: - househub_uploads:/uploads - /opt/container/househub:/var/www/html diff --git a/includes/crypto.php b/includes/crypto.php index 9f57f80..fc77a53 100644 --- a/includes/crypto.php +++ b/includes/crypto.php @@ -1,11 +1,56 @@ = 32) { + return $content; + } + } + + $dir = dirname($keyFile); + if (!is_dir($dir)) { + @mkdir($dir, 0700, true); + } + if (is_dir($dir) && is_writable($dir)) { + try { + $material = bin2hex(random_bytes(32)); + if (@file_put_contents($keyFile, $material, LOCK_EX) !== false) { + @chmod($keyFile, 0600); + return $material; + } + } catch (\Throwable $e) { + // continuer vers la dérivation + } + } + + $dbPass = (string) (getenv('DB_PASS') ?: ''); + $dbHost = (string) (getenv('DB_HOST') ?: ''); + return 'hh-derived|' . $dbPass . '|' . $dbHost . '|HouseHub-calendar-ios-v1'; +} + +function hh_encryption_key(): string +{ + return hash('sha256', hh_secret_key_material(), true); +} + function hh_encrypt_secret(string $plain): string { - $keyMaterial = getenv('APP_SECRET_KEY') ?: ''; - if ($keyMaterial === '') { - throw new RuntimeException('APP_SECRET_KEY manquant'); - } - $key = hash('sha256', $keyMaterial, true); + $key = hh_encryption_key(); $iv = random_bytes(16); $cipher = openssl_encrypt($plain, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); if ($cipher === false) { @@ -16,15 +61,11 @@ function hh_encrypt_secret(string $plain): string function hh_decrypt_secret(string $encrypted): string { - $keyMaterial = getenv('APP_SECRET_KEY') ?: ''; - if ($keyMaterial === '') { - throw new RuntimeException('APP_SECRET_KEY manquant'); - } + $key = hh_encryption_key(); $raw = base64_decode($encrypted, true); if ($raw === false || strlen($raw) <= 16) { throw new RuntimeException('Secret invalide'); } - $key = hash('sha256', $keyMaterial, true); $iv = substr($raw, 0, 16); $cipher = substr($raw, 16); $plain = openssl_decrypt($cipher, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);