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,178 @@
<?php
declare(strict_types=1);
use App\Framework\Cryptography\DerivedKey;
use App\Framework\Cryptography\KeyDerivationFunction;
use App\Framework\Random\SecureRandomGenerator;
it('generates salt with correct length', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$salt = $kdf->generateSalt(32);
expect(strlen($salt))->toBe(32);
});
it('throws exception for too short salt', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
expect(fn () => $kdf->generateSalt(8))
->toThrow(InvalidArgumentException::class, 'Salt length must be at least 16 bytes');
});
it('derives key using PBKDF2', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'test-password';
$salt = $kdf->generateSalt();
$derivedKey = $kdf->pbkdf2($password, $salt, 10000, 32);
expect($derivedKey)->toBeInstanceOf(DerivedKey::class);
expect($derivedKey->getAlgorithm())->toBe('pbkdf2-sha256');
expect($derivedKey->getKeyLength())->toBe(32);
expect($derivedKey->getIterations())->toBe(10000);
expect(strlen($derivedKey->getKey()))->toBe(32);
});
it('derives key using Argon2ID if available', function () {
if (! function_exists('sodium_crypto_pwhash') || ! defined('SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID')) {
$this->markTestSkipped('Sodium extension or Argon2ID constant not available');
}
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'test-password';
$salt = str_repeat("\x00", 32); // Argon2ID needs exactly 32 bytes
$derivedKey = $kdf->argon2id($password, $salt, 65536, 4, 3, 32);
expect($derivedKey)->toBeInstanceOf(DerivedKey::class);
expect($derivedKey->getAlgorithm())->toBe('argon2id');
expect($derivedKey->getKeyLength())->toBe(32);
expect(strlen($derivedKey->getKey()))->toBe(32);
});
it('derives key using scrypt if available', function () {
if (! function_exists('scrypt')) {
$this->markTestSkipped('scrypt function not available');
}
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'test-password';
$salt = $kdf->generateSalt();
$derivedKey = $kdf->scrypt($password, $salt, 16384, 8, 1, 32);
expect($derivedKey)->toBeInstanceOf(DerivedKey::class);
expect($derivedKey->getAlgorithm())->toBe('scrypt');
expect($derivedKey->getKeyLength())->toBe(32);
expect(strlen($derivedKey->getKey()))->toBe(32);
});
it('verifies password correctly', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'correct-password';
$wrongPassword = 'wrong-password';
$salt = $kdf->generateSalt();
$derivedKey = $kdf->pbkdf2($password, $salt, 10000, 32);
expect($kdf->verify($password, $derivedKey))->toBeTrue();
expect($kdf->verify($wrongPassword, $derivedKey))->toBeFalse();
});
it('hashes password with automatic salt generation', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'test-password';
$derivedKey = $kdf->hashPassword($password, 'pbkdf2-sha256');
expect($derivedKey)->toBeInstanceOf(DerivedKey::class);
expect($derivedKey->getAlgorithm())->toBe('pbkdf2-sha256');
expect(strlen($derivedKey->getSalt()))->toBe(32);
expect($kdf->verify($password, $derivedKey))->toBeTrue();
});
it('throws exception for empty password', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$salt = $kdf->generateSalt();
expect(fn () => $kdf->pbkdf2('', $salt))
->toThrow(InvalidArgumentException::class, 'Password cannot be empty');
});
it('throws exception for short salt', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
expect(fn () => $kdf->pbkdf2('password', 'short'))
->toThrow(InvalidArgumentException::class, 'Salt must be at least 16 bytes');
});
it('throws exception for too few iterations', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$salt = $kdf->generateSalt();
expect(fn () => $kdf->pbkdf2('password', $salt, 5000))
->toThrow(InvalidArgumentException::class, 'Iterations must be at least 10,000');
});
it('supports different hash algorithms', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'test-password';
$salt = $kdf->generateSalt();
$sha256Key = $kdf->pbkdf2($password, $salt, 10000, 32, 'sha256');
$sha512Key = $kdf->pbkdf2($password, $salt, 10000, 32, 'sha512');
expect($sha256Key->getAlgorithm())->toBe('pbkdf2-sha256');
expect($sha512Key->getAlgorithm())->toBe('pbkdf2-sha512');
expect($sha256Key->getKey())->not->toBe($sha512Key->getKey());
});
it('provides recommended parameters', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$params = $kdf->getRecommendedParameters('pbkdf2-sha256', 'standard');
expect($params)->toHaveKey('iterations');
expect($params)->toHaveKey('key_length');
expect($params['iterations'])->toBe(100000);
expect($params['key_length'])->toBe(32);
});
it('throws exception for unsupported algorithm in recommendations', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
expect(fn () => $kdf->getRecommendedParameters('unsupported', 'standard'))
->toThrow(InvalidArgumentException::class);
});
it('creates instance using factory method', function () {
$randomGen = new SecureRandomGenerator();
$kdf = KeyDerivationFunction::create($randomGen);
expect($kdf)->toBeInstanceOf(KeyDerivationFunction::class);
});
it('generates different keys for same password with different salts', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'same-password';
$salt1 = $kdf->generateSalt();
$salt2 = $kdf->generateSalt();
$key1 = $kdf->pbkdf2($password, $salt1);
$key2 = $kdf->pbkdf2($password, $salt2);
expect($key1->getKey())->not->toBe($key2->getKey());
});
it('generates consistent keys for same inputs', function () {
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
$password = 'test-password';
$salt = str_repeat('a', 16);
$key1 = $kdf->pbkdf2($password, $salt, 10000, 32);
$key2 = $kdf->pbkdf2($password, $salt, 10000, 32);
expect($key1->getKey())->toBe($key2->getKey());
});