- Add initializer count logging in DiscoveryServiceBootstrapper - Add route structure analysis in RouterSetup - Add request parameter logging in HttpRouter - Update PHP production config for better OPcache handling - Fix various config and error handling improvements
114 lines
3.0 KiB
PHP
114 lines
3.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Http;
|
|
|
|
/**
|
|
* Repräsentiert eine kryptografisch sichere und signierte Request-ID.
|
|
* Enthält sowohl die ID selbst als auch deren HMAC-Signatur zur Validierung.
|
|
*/
|
|
final readonly class RequestId
|
|
{
|
|
private string $id;
|
|
|
|
private string $signature;
|
|
|
|
private string $combined;
|
|
|
|
/**
|
|
* Erstellt eine neue Request-ID oder parsed eine bestehende
|
|
*
|
|
* @param string $secret Das Secret für die HMAC-Signatur (REQUIRED)
|
|
* @param string|null $combined Wenn nicht null, wird diese ID validiert und verwendet
|
|
*/
|
|
public function __construct(string $secret, ?string $combined = null)
|
|
{
|
|
|
|
if ($combined !== null && self::isValidFormat($combined)) {
|
|
// Bestehende ID parsen
|
|
[$rawId, $signature] = explode('.', $combined, 2);
|
|
|
|
// Signatur validieren
|
|
$expectedSignature = $this->generateSignature($rawId, $secret);
|
|
|
|
if (! hash_equals($expectedSignature, $signature)) {
|
|
// Bei ungültiger Signatur, neue ID erstellen
|
|
$this->generateNew($secret);
|
|
} else {
|
|
// Bei gültiger Signatur, diese ID verwenden
|
|
$this->id = $rawId;
|
|
$this->signature = $signature;
|
|
$this->combined = $combined;
|
|
}
|
|
} else {
|
|
// Neue ID erstellen
|
|
$this->generateNew($secret);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generiert eine neue Request-ID mit Signatur
|
|
*/
|
|
private function generateNew(string $secret): void
|
|
{
|
|
// Zufällige ID generieren (16 Byte = 32 Hex-Zeichen)
|
|
$this->id = bin2hex(random_bytes(16));
|
|
|
|
// Signatur erstellen
|
|
$this->signature = $this->generateSignature($this->id, $secret);
|
|
|
|
// Kombinierte Darstellung erstellen
|
|
$this->combined = $this->id . '.' . $this->signature;
|
|
}
|
|
|
|
/**
|
|
* Generiert eine HMAC-Signatur für die ID
|
|
*/
|
|
private function generateSignature(string $id, string $secret): string
|
|
{
|
|
return hash_hmac('sha256', $id, $secret, false);
|
|
}
|
|
|
|
/**
|
|
* Prüft, ob eine kombinierte ID das korrekte Format hat
|
|
*/
|
|
private static function isValidFormat(string $combined): bool
|
|
{
|
|
// Format: 32 Hex-Zeichen + Punkt + 64 Hex-Zeichen (SHA-256 HMAC)
|
|
return preg_match('/^[a-f0-9]{32}\.[a-f0-9]{64}$/i', $combined) === 1;
|
|
}
|
|
|
|
/**
|
|
* Gibt die kombinierte ID (ID + Signatur) zurück
|
|
*/
|
|
public function toString(): string
|
|
{
|
|
return $this->combined;
|
|
}
|
|
|
|
/**
|
|
* Gibt nur die eigentliche ID ohne Signatur zurück
|
|
*/
|
|
public function getId(): string
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* Gibt die Signatur zurück
|
|
*/
|
|
public function getSignature(): string
|
|
{
|
|
return $this->signature;
|
|
}
|
|
|
|
/**
|
|
* String-Repräsentation für Debugging
|
|
*/
|
|
public function __toString(): string
|
|
{
|
|
return $this->toString();
|
|
}
|
|
}
|