encrypt($data); } public static function decrypt(string $encrypted): string { return self::cipher()->decrypt($encrypted); } public static function encryptFile(string $src, string $dst): void { self::cipher()->encryptFile($src, $dst); } public static function decryptFile(string $src, string $dst): void { self::cipher()->decryptFile($src, $dst); } /** * Le chiffreur, construit sur la matière de clé WordPress. * * La validation est faite ICI, avant de déléguer, pour que le message reste * actionnable : « régénérez les salts WordPress » dit quoi faire, là où un message * neutre venu du cœur laisserait l'exploitant chercher. Le cœur refait le contrôle * de longueur de son côté — un garde-fou n'est pas moins utile parce qu'il est * doublé. */ /** * Le chiffreur, exposé pour le chemin reprenable. * * `cipher()` reste privé : c'est l'API par verbe (chiffre ceci, déchiffre cela) * qui doit servir partout. La reprise, elle, a besoin de l'objet lui-même * parce qu'elle rend et reprend un état — l'exposer ici évite de dupliquer la * validation de la matière de clé, qui est la seule chose de valeur ici. */ public static function cipherForResume(): AuthenticatedCipher { return self::cipher(); } private static function cipher(): AuthenticatedCipher { if (self::$cipher !== null) { return self::$cipher; } $authKey = defined('AUTH_KEY') ? (string) AUTH_KEY : ''; $secureAuthKey = defined('SECURE_AUTH_KEY') ? (string) SECURE_AUTH_KEY : ''; $raw = $authKey . $secureAuthKey; self::assertUsableKeyMaterial($raw); return self::$cipher = new AuthenticatedCipher($raw, self::PLACEHOLDER_KEY_MATERIAL); } private static function assertUsableKeyMaterial(string $raw): void { if (strlen(trim($raw)) < AuthenticatedCipher::MIN_KEY_MATERIAL) { throw new \RuntimeException( 'Sentinelo: clé de chiffrement indisponible — AUTH_KEY / SECURE_AUTH_KEY ' . 'sont absents ou trop courts. Régénérez les salts WordPress avant ' . 'de stocker un secret ou de lancer un backup.' ); } $needle = strtolower($raw); foreach (self::PLACEHOLDER_KEY_MATERIAL as $placeholder) { if (str_contains($needle, $placeholder)) { throw new \RuntimeException( 'Sentinelo: AUTH_KEY / SECURE_AUTH_KEY contiennent encore les valeurs ' . "d'exemple de wp-config-sample.php. Régénérez les salts WordPress : " . 'ces valeurs sont publiques et n\'offrent aucune confidentialité.' ); } } } }