feat: Version 3.3.4 - Nouvelle architecture pages, optimisations widgets Flutter et API
- Mise à jour VERSION vers 3.3.4 - Optimisations et révisions architecture API (deploy-api.sh, scripts de migration) - Ajout documentation Stripe Tap to Pay complète - Migration vers polices Inter Variable pour Flutter - Optimisations build Android et nettoyage fichiers temporaires - Amélioration système de déploiement avec gestion backups - Ajout scripts CRON et migrations base de données 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
188
bao/lib/CryptoService.php
Normal file
188
bao/lib/CryptoService.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Service de chiffrement/déchiffrement AES-256-CBC
|
||||
* Compatible avec le système de chiffrement de l'API Geosector
|
||||
*/
|
||||
class CryptoService {
|
||||
private string $encryptionKey;
|
||||
private string $cipher = 'AES-256-CBC';
|
||||
|
||||
public function __construct(string $encryptionKey) {
|
||||
// Décoder la clé base64
|
||||
$this->encryptionKey = base64_decode($encryptionKey);
|
||||
|
||||
if (strlen($this->encryptionKey) !== 32) {
|
||||
throw new RuntimeException("La clé de chiffrement doit faire 32 bytes (256 bits)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffre les données "searchable" (encrypted_user_name, encrypted_email)
|
||||
* Format: base64 simple avec IV fixe
|
||||
*/
|
||||
public function decryptSearchable(?string $encryptedData): ?string {
|
||||
if (empty($encryptedData)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$encrypted = base64_decode($encryptedData);
|
||||
if ($encrypted === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$iv = str_repeat("\0", 16); // IV fixe
|
||||
|
||||
$decrypted = openssl_decrypt($encrypted, $this->cipher, $this->encryptionKey, 0, $iv);
|
||||
|
||||
if ($decrypted === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Supprimer le caractère de contrôle ajouté
|
||||
if (substr($decrypted, -1) === "\x01") {
|
||||
return substr($decrypted, 0, -1);
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffre les données avec IV aléatoire (encrypted_name, encrypted_phone, etc.)
|
||||
* Format: base64(IV + encrypted)
|
||||
*/
|
||||
public function decryptWithIV(?string $encryptedData): ?string {
|
||||
if (empty($encryptedData)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = base64_decode($encryptedData);
|
||||
if ($data === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ivLength = openssl_cipher_iv_length($this->cipher);
|
||||
|
||||
if (strlen($data) <= $ivLength) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$iv = substr($data, 0, $ivLength);
|
||||
$encrypted = substr($data, $ivLength);
|
||||
|
||||
$decrypted = openssl_decrypt($encrypted, $this->cipher, $this->encryptionKey, 0, $iv);
|
||||
|
||||
return $decrypted !== false ? $decrypted : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffre une valeur chiffrée
|
||||
*
|
||||
* @param string|null $encryptedValue Valeur chiffrée (format base64:iv:data)
|
||||
* @return string|null Valeur déchiffrée ou null
|
||||
*/
|
||||
public function decrypt(?string $encryptedValue): ?string {
|
||||
if (empty($encryptedValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Le format de l'API est : base64:iv:encrypted_data
|
||||
$parts = explode(':', $encryptedValue);
|
||||
|
||||
if (count($parts) !== 3 || $parts[0] !== 'base64') {
|
||||
// Format invalide, peut-être déjà en clair
|
||||
return $encryptedValue;
|
||||
}
|
||||
|
||||
$iv = base64_decode($parts[1]);
|
||||
$encrypted = base64_decode($parts[2]);
|
||||
|
||||
if ($iv === false || $encrypted === false) {
|
||||
throw new RuntimeException("Impossible de décoder les données chiffrées");
|
||||
}
|
||||
|
||||
$decrypted = openssl_decrypt(
|
||||
$encrypted,
|
||||
$this->cipher,
|
||||
$this->encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
|
||||
if ($decrypted === false) {
|
||||
throw new RuntimeException("Échec du déchiffrement : " . openssl_error_string());
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chiffre une valeur
|
||||
*
|
||||
* @param string $value Valeur à chiffrer
|
||||
* @return string Valeur chiffrée (format base64:iv:data)
|
||||
*/
|
||||
public function encrypt(string $value): string {
|
||||
$ivLength = openssl_cipher_iv_length($this->cipher);
|
||||
$iv = openssl_random_pseudo_bytes($ivLength);
|
||||
|
||||
$encrypted = openssl_encrypt(
|
||||
$value,
|
||||
$this->cipher,
|
||||
$this->encryptionKey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
|
||||
if ($encrypted === false) {
|
||||
throw new RuntimeException("Échec du chiffrement : " . openssl_error_string());
|
||||
}
|
||||
|
||||
return 'base64:' . base64_encode($iv) . ':' . base64_encode($encrypted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffre plusieurs colonnes d'un tableau
|
||||
*
|
||||
* @param array $row Ligne de base de données
|
||||
* @param array $encryptedColumns Liste des colonnes à déchiffrer (sans le préfixe encrypted_)
|
||||
* @return array Tableau avec colonnes déchiffrées
|
||||
*/
|
||||
public function decryptRow(array $row, array $encryptedColumns): array {
|
||||
$decrypted = $row;
|
||||
|
||||
foreach ($encryptedColumns as $column) {
|
||||
$encryptedColumn = 'encrypted_' . $column;
|
||||
|
||||
if (isset($row[$encryptedColumn])) {
|
||||
$decrypted[$column] = $this->decrypt($row[$encryptedColumn]);
|
||||
}
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffre les colonnes encrypted_* d'un utilisateur
|
||||
*
|
||||
* @param array $user Données utilisateur
|
||||
* @return array Utilisateur avec données déchiffrées
|
||||
*/
|
||||
public function decryptUser(array $user): array {
|
||||
$columns = ['user_name', 'email', 'name', 'phone', 'mobile'];
|
||||
return $this->decryptRow($user, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Déchiffre les colonnes encrypted_* d'une entité
|
||||
*
|
||||
* @param array $entite Données entité
|
||||
* @return array Entité avec données déchiffrées
|
||||
*/
|
||||
public function decryptEntite(array $entite): array {
|
||||
$columns = ['name', 'email', 'phone', 'mobile', 'iban', 'bic'];
|
||||
return $this->decryptRow($entite, $columns);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user