diff --git a/src/Controller/Api/ApiAccountController.php b/src/Controller/Api/ApiAccountController.php index 05678fb..759ac7c 100644 --- a/src/Controller/Api/ApiAccountController.php +++ b/src/Controller/Api/ApiAccountController.php @@ -41,13 +41,8 @@ class ApiAccountController extends AbstractController $user = $em->getRepository(User::class)->findOneBy(['email' => $email]); - if (!$user) { - return $this->error('Utilisateur introuvable.', 404); - } - - return $this->success([ - 'id' => $user->getId(), - 'stripeAccountId' => $user->getStripeAccountId(), - ]); + return $user + ? $this->success(['id' => $user->getId(), 'stripeAccountId' => $user->getStripeAccountId()]) + : $this->error('Utilisateur introuvable.', 404); } } diff --git a/src/Controller/AttestationController.php b/src/Controller/AttestationController.php index 0a7b346..b264d0e 100644 --- a/src/Controller/AttestationController.php +++ b/src/Controller/AttestationController.php @@ -12,6 +12,7 @@ use Symfony\Component\Routing\Attribute\Route; class AttestationController extends AbstractController { + private const TPL_NOT_FOUND_VENTES = 'attestation/not_found_ventes.html.twig'; public function __construct( #[Autowire('%kernel.secret%')] private string $appSecret, ) { @@ -50,7 +51,7 @@ class AttestationController extends AbstractController $attestation = $em->getRepository(Attestation::class)->findOneBy(['reference' => $reference]); if (!$attestation) { - return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]); + return $this->render(self::TPL_NOT_FOUND_VENTES, ['breadcrumbs' => $breadcrumbs]); } return $this->render('attestation/check_ventes.html.twig', [ @@ -69,38 +70,47 @@ class AttestationController extends AbstractController ['name' => 'Verification attestation de ventes', 'url' => null], ]; + $result = $this->decodeAndVerifyHash($hash); + + if (!$result) { + return $this->render(self::TPL_NOT_FOUND_VENTES, ['breadcrumbs' => $breadcrumbs]); + } + + $attestation = $em->getRepository(Attestation::class)->findOneBy(['signatureHash' => $result['signatureHash']]); + + return $this->render('attestation/check_ventes.html.twig', [ + 'data' => $result['data'], + 'breadcrumbs' => $breadcrumbs, + 'isRegistered' => null !== $attestation, + 'attestation' => $attestation, + ]); + } + + /** + * @return array{data: array, signatureHash: string}|null + */ + private function decodeAndVerifyHash(string $hash): ?array + { $decoded = base64_decode(strtr($hash, '-_', '+/'), true); if (!$decoded) { - return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]); + return null; } $parts = explode('|', $decoded, 2); if (2 !== \count($parts)) { - return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]); + return null; } [$signature, $jsonPayload] = $parts; $expectedSignature = hash_hmac('sha256', $jsonPayload, $this->appSecret); if (!hash_equals($expectedSignature, $signature)) { - return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]); + return null; } $data = json_decode($jsonPayload, true); - if (!$data) { - return $this->render('attestation/not_found_ventes.html.twig', ['breadcrumbs' => $breadcrumbs]); - } - $signatureHash = hash_hmac('sha256', $jsonPayload, $this->appSecret); - $attestation = $em->getRepository(Attestation::class)->findOneBy(['signatureHash' => $signatureHash]); - $isRegistered = null !== $attestation; - - return $this->render('attestation/check_ventes.html.twig', [ - 'data' => $data, - 'breadcrumbs' => $breadcrumbs, - 'isRegistered' => $isRegistered, - 'attestation' => $attestation, - ]); + return $data ? ['data' => $data, 'signatureHash' => $expectedSignature] : null; } /** diff --git a/src/Service/AnalyticsCryptoService.php b/src/Service/AnalyticsCryptoService.php index eb714b3..1c468f6 100644 --- a/src/Service/AnalyticsCryptoService.php +++ b/src/Service/AnalyticsCryptoService.php @@ -33,30 +33,26 @@ class AnalyticsCryptoService return null; } - // Try JS format first: iv (12) + ciphertext_with_tag (tag is last 16 bytes) $iv = substr($raw, 0, 12); - $ciphertextWithTag = substr($raw, 12); - if (\strlen($ciphertextWithTag) >= 16) { - $tag = substr($ciphertextWithTag, -16); - $encrypted = substr($ciphertextWithTag, 0, -16); - - $json = openssl_decrypt($encrypted, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag); - if (false !== $json) { - return json_decode($json, true); - } - } + // Try JS format first: iv (12) + ciphertext_with_tag (tag is last 16 bytes) + $json = $this->tryDecryptJsFormat($iv, substr($raw, 12)); // Fallback: PHP format iv (12) + tag (16) + ciphertext - $tag = substr($raw, 12, 16); - $encrypted = substr($raw, 28); + $json ??= openssl_decrypt(substr($raw, 28), 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, substr($raw, 12, 16)) ?: null; - $json = openssl_decrypt($encrypted, 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, $tag); - if (false === $json) { + return $json ? json_decode($json, true) : null; + } + + private function tryDecryptJsFormat(string $iv, string $ciphertextWithTag): ?string + { + if (\strlen($ciphertextWithTag) < 16) { return null; } - return json_decode($json, true); + $json = openssl_decrypt(substr($ciphertextWithTag, 0, -16), 'aes-256-gcm', $this->key, \OPENSSL_RAW_DATA, $iv, substr($ciphertextWithTag, -16)); + + return false !== $json ? $json : null; } public function generateVisitorHash(string $uid): string diff --git a/src/Service/InfraService.php b/src/Service/InfraService.php index 8c9556c..dc412cf 100644 --- a/src/Service/InfraService.php +++ b/src/Service/InfraService.php @@ -174,7 +174,11 @@ class InfraService $issuer = $cert['issuer']['O'] ?? $cert['issuer']['CN'] ?? '?'; return [ - 'status' => $daysLeft > 7 ? 'ok' : ($daysLeft > 0 ? 'warning' : 'error'), + 'status' => match (true) { + $daysLeft > 7 => 'ok', + $daysLeft > 0 => 'warning', + default => 'error', + }, 'domain' => $host, 'issuer' => $issuer, 'valid_until' => $validTo->format('d/m/Y'), @@ -483,16 +487,11 @@ class InfraService public static function fmtDuration(int $seconds): string { - if ($seconds >= 86400) { - return round($seconds / 86400, 1).'j'; - } - if ($seconds >= 3600) { - return round($seconds / 3600, 1).'h'; - } - if ($seconds >= 60) { - return round($seconds / 60).'min'; - } - - return $seconds.'s'; + return match (true) { + $seconds >= 86400 => round($seconds / 86400, 1).'j', + $seconds >= 3600 => round($seconds / 3600, 1).'h', + $seconds >= 60 => round($seconds / 60).'min', + default => $seconds.'s', + }; } }