Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,259 @@
<?php
declare(strict_types=1);
namespace App\Framework\Cryptography;
use InvalidArgumentException;
/**
* Public Key Value Object
*
* Represents a cryptographic public key with metadata.
*/
final readonly class PublicKey
{
public function __construct(
private string $keyMaterial,
private string $algorithm,
private int $keySize,
private ?string $curve = null
) {
if (empty($keyMaterial)) {
throw new InvalidArgumentException('Key material cannot be empty');
}
if (empty($algorithm)) {
throw new InvalidArgumentException('Algorithm cannot be empty');
}
$supportedAlgorithms = ['rsa', 'ecdsa'];
if (! in_array($algorithm, $supportedAlgorithms, true)) {
throw new InvalidArgumentException('Unsupported algorithm');
}
if ($keySize < 256) {
throw new InvalidArgumentException('Key size must be at least 256 bits');
}
if ($algorithm === 'ecdsa' && $curve === null) {
throw new InvalidArgumentException('ECDSA keys must specify a curve');
}
}
/**
* Get the key material (PEM format)
*/
public function getKeyMaterial(): string
{
return $this->keyMaterial;
}
/**
* Get the algorithm
*/
public function getAlgorithm(): string
{
return $this->algorithm;
}
/**
* Get the key size in bits
*/
public function getKeySize(): int
{
return $this->keySize;
}
/**
* Get the curve name (ECDSA only)
*/
public function getCurve(): ?string
{
return $this->curve;
}
/**
* Check if this is an RSA key
*/
public function isRsa(): bool
{
return $this->algorithm === 'rsa';
}
/**
* Check if this is an ECDSA key
*/
public function isEcdsa(): bool
{
return $this->algorithm === 'ecdsa';
}
/**
* Export key to array (includes key material - safe for public keys)
*/
public function toArray(): array
{
$data = [
'key_material' => $this->keyMaterial,
'algorithm' => $this->algorithm,
'key_size' => $this->keySize,
];
if ($this->curve !== null) {
$data['curve'] = $this->curve;
}
return $data;
}
/**
* Create from array
*/
public static function fromArray(array $data): self
{
$requiredFields = ['key_material', 'algorithm', 'key_size'];
foreach ($requiredFields as $field) {
if (! isset($data[$field])) {
throw new InvalidArgumentException("Missing required field: {$field}");
}
}
return new self(
keyMaterial: $data['key_material'],
algorithm: $data['algorithm'],
keySize: (int)$data['key_size'],
curve: $data['curve'] ?? null
);
}
/**
* Get key fingerprint (SHA-256 hash)
*/
public function getFingerprint(): string
{
return hash('sha256', $this->keyMaterial);
}
/**
* Get short fingerprint (first 16 chars of full fingerprint)
*/
public function getShortFingerprint(): string
{
return substr($this->getFingerprint(), 0, 16);
}
/**
* Get key in DER format (binary)
*/
public function getDerFormat(): string
{
$resource = openssl_pkey_get_public($this->keyMaterial);
if ($resource === false) {
throw new InvalidArgumentException('Invalid public key');
}
$details = openssl_pkey_get_details($resource);
if ($details === false || ! isset($details['key'])) {
throw new InvalidArgumentException('Failed to get key details');
}
// Convert PEM to DER
$pem = $details['key'];
$pem = str_replace(['-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----'], '', $pem);
$pem = str_replace(["\r", "\n", " "], '', $pem);
$der = base64_decode($pem);
if ($der === false) {
throw new InvalidArgumentException('Failed to convert to DER format');
}
return $der;
}
/**
* Get key type description
*/
public function getDescription(): string
{
$description = strtoupper($this->algorithm);
if ($this->algorithm === 'rsa') {
$description .= " {$this->keySize}-bit";
} elseif ($this->algorithm === 'ecdsa') {
$description .= " {$this->curve}";
}
return $description;
}
/**
* Check equality with another public key
*/
public function equals(self $other): bool
{
return hash_equals($this->keyMaterial, $other->keyMaterial);
}
/**
* Validate key material
*/
public function isValid(): bool
{
$resource = openssl_pkey_get_public($this->keyMaterial);
return $resource !== false;
}
/**
* Get key as JWK (JSON Web Key) format
*/
public function toJwk(): array
{
if (! $this->isValid()) {
throw new InvalidArgumentException('Invalid key material');
}
$resource = openssl_pkey_get_public($this->keyMaterial);
$details = openssl_pkey_get_details($resource);
if ($this->algorithm === 'rsa') {
return [
'kty' => 'RSA',
'alg' => 'RS256',
'use' => 'sig',
'n' => $this->base64UrlEncode($details['rsa']['n']),
'e' => $this->base64UrlEncode($details['rsa']['e']),
];
}
if ($this->algorithm === 'ecdsa') {
$crv = match ($this->curve) {
'prime256v1' => 'P-256',
'secp384r1' => 'P-384',
'secp521r1' => 'P-521',
default => throw new InvalidArgumentException('Unsupported curve for JWK')
};
return [
'kty' => 'EC',
'alg' => 'ES256',
'use' => 'sig',
'crv' => $crv,
'x' => $this->base64UrlEncode($details['ec']['x']),
'y' => $this->base64UrlEncode($details['ec']['y']),
];
}
throw new InvalidArgumentException('Unsupported algorithm for JWK conversion');
}
/**
* Base64 URL encode (for JWK format)
*/
private function base64UrlEncode(string $data): string
{
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
}