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,397 @@
# Cryptography Module - Konfiguration
Konfigurationsoptionen und Setup für das Cryptography Module.
## Service-Registrierung
### Dependency Injection Setup
```php
use App\Framework\DI\Initializer;
use App\Framework\DI\Container;
use App\Framework\Cryptography\KeyDerivationFunction;
use App\Framework\Cryptography\SecureTokenGenerator;
use App\Framework\Cryptography\CryptographicUtilities;
use App\Framework\Cryptography\DigitalSignature;
use App\Framework\Cryptography\AdvancedHash;
use App\Framework\Random\SecureRandomGenerator;
final readonly class CryptographyInitializer implements Initializer
{
public function initialize(Container $container): void
{
// Random Generator als Dependency
$container->singleton(RandomGenerator::class, new SecureRandomGenerator());
// Core Cryptography Services
$container->singleton(KeyDerivationFunction::class, function(Container $c) {
return new KeyDerivationFunction($c->get(RandomGenerator::class));
});
$container->singleton(SecureTokenGenerator::class, function(Container $c) {
return new SecureTokenGenerator($c->get(RandomGenerator::class));
});
$container->singleton(CryptographicUtilities::class, function(Container $c) {
return new CryptographicUtilities($c->get(RandomGenerator::class));
});
$container->singleton(DigitalSignature::class, function(Container $c) {
return new DigitalSignature($c->get(RandomGenerator::class));
});
$container->singleton(AdvancedHash::class, new AdvancedHash());
// Factory Methods als Alternative
$container->bind('kdf.factory', function(Container $c) {
return KeyDerivationFunction::create($c->get(RandomGenerator::class));
});
}
}
```
### AppBootstrapper Integration
```php
// In src/Framework/Core/AppBootstrapper.php
public function bootstrap(): Application
{
// ... existing bootstrapping
$initializer = new CryptographyInitializer();
$initializer->initialize($this->container);
return $application;
}
```
## Sicherheitsparameter
### Key Derivation Function Konfiguration
```php
final readonly class CryptographyConfig
{
public const DEFAULT_KDF_PARAMETERS = [
'pbkdf2-sha256' => [
'low' => ['iterations' => 50000, 'key_length' => 32],
'standard' => ['iterations' => 100000, 'key_length' => 32],
'high' => ['iterations' => 200000, 'key_length' => 32],
],
'argon2id' => [
'low' => ['memory_cost' => 32768, 'time_cost' => 3, 'threads' => 2],
'standard' => ['memory_cost' => 65536, 'time_cost' => 4, 'threads' => 3],
'high' => ['memory_cost' => 131072, 'time_cost' => 6, 'threads' => 4],
],
'scrypt' => [
'low' => ['cost_parameter' => 8192, 'block_size' => 8, 'parallelization' => 1],
'standard' => ['cost_parameter' => 16384, 'block_size' => 8, 'parallelization' => 1],
'high' => ['cost_parameter' => 32768, 'block_size' => 8, 'parallelization' => 2],
]
];
public static function getRecommendedParameters(
string $algorithm,
string $securityLevel = 'standard'
): array {
return self::DEFAULT_KDF_PARAMETERS[$algorithm][$securityLevel] ??
throw new InvalidArgumentException("Unsupported configuration: {$algorithm}:{$securityLevel}");
}
}
```
### Token-Generator Konfiguration
```php
final readonly class TokenConfig
{
public const DEFAULT_TOKEN_LENGTHS = [
SecureTokenGenerator::TYPE_API_KEY => 32, // 256 Bit
SecureTokenGenerator::TYPE_SESSION => 32, // 256 Bit
SecureTokenGenerator::TYPE_CSRF => 32, // 256 Bit
SecureTokenGenerator::TYPE_REFRESH => 64, // 512 Bit
SecureTokenGenerator::TYPE_VERIFICATION => 32, // 256 Bit
SecureTokenGenerator::TYPE_BEARER => 32, // 256 Bit
SecureTokenGenerator::TYPE_WEBHOOK => 32, // 256 Bit
];
public const DEFAULT_TOKEN_FORMATS = [
SecureTokenGenerator::TYPE_API_KEY => SecureTokenGenerator::FORMAT_BASE64_URL,
SecureTokenGenerator::TYPE_SESSION => SecureTokenGenerator::FORMAT_BASE64_URL,
SecureTokenGenerator::TYPE_OTP => SecureTokenGenerator::FORMAT_NUMERIC,
];
public const TOKEN_EXPIRY_TIMES = [
SecureTokenGenerator::TYPE_SESSION => 3600 * 24, // 24 Stunden
SecureTokenGenerator::TYPE_CSRF => 3600, // 1 Stunde
SecureTokenGenerator::TYPE_VERIFICATION => 3600 * 2, // 2 Stunden
SecureTokenGenerator::TYPE_OTP => 300, // 5 Minuten
SecureTokenGenerator::TYPE_REFRESH => 3600 * 24 * 30, // 30 Tage
];
}
```
## Environment-basierte Konfiguration
### .env Konfiguration
```bash
# Cryptography Configuration
CRYPTO_DEFAULT_KDF_ALGORITHM=argon2id
CRYPTO_DEFAULT_SECURITY_LEVEL=standard
# Token Configuration
CRYPTO_DEFAULT_TOKEN_LENGTH=32
CRYPTO_DEFAULT_TOKEN_FORMAT=base64_url
# Digital Signature Configuration
CRYPTO_DEFAULT_RSA_KEY_SIZE=2048
CRYPTO_DEFAULT_EC_CURVE=secp256r1
# Performance Configuration
CRYPTO_BATCH_SIZE_LIMIT=1000
CRYPTO_ENTROPY_THRESHOLD=7.0
```
### Environment-aware Service
```php
use App\Framework\Core\Environment;
use App\Framework\Core\EnvKey;
final readonly class CryptographyConfigService
{
public function __construct(
private Environment $environment
) {}
public function getDefaultKdfAlgorithm(): string
{
return $this->environment->get(
EnvKey::from('CRYPTO_DEFAULT_KDF_ALGORITHM'),
'argon2id'
);
}
public function getDefaultSecurityLevel(): string
{
return $this->environment->get(
EnvKey::from('CRYPTO_DEFAULT_SECURITY_LEVEL'),
'standard'
);
}
public function getDefaultTokenLength(): int
{
return $this->environment->getInt(
EnvKey::from('CRYPTO_DEFAULT_TOKEN_LENGTH'),
32
);
}
public function getEntropyThreshold(): float
{
return $this->environment->getFloat(
EnvKey::from('CRYPTO_ENTROPY_THRESHOLD'),
7.0
);
}
}
```
## Advanced Configuration
### Custom RandomGenerator
```php
// Eigener RandomGenerator für spezielle Anforderungen
final readonly class CustomSecureRandomGenerator implements RandomGenerator
{
public function bytes(int $length): string
{
// Custom implementation mit Hardware-RNG
return $this->getHardwareRandomBytes($length);
}
public function int(int $min = 0, int $max = PHP_INT_MAX): int
{
return random_int($min, $max);
}
private function getHardwareRandomBytes(int $length): string
{
// Implementation für Hardware-RNG
// z.B. über /dev/hwrng oder externe HSM
}
}
// In Initializer registrieren
$container->singleton(RandomGenerator::class, new CustomSecureRandomGenerator());
```
### Performance-optimierte Konfiguration
```php
final readonly class PerformanceOptimizedCryptoInitializer implements Initializer
{
public function initialize(Container $container): void
{
// Cached Services für bessere Performance
$container->singleton(KeyDerivationFunction::class, function(Container $c) {
$kdf = new KeyDerivationFunction($c->get(RandomGenerator::class));
return new CachedKeyDerivationFunction($kdf, $c->get(Cache::class));
});
// Batch-optimierte Token-Generierung
$container->singleton(SecureTokenGenerator::class, function(Container $c) {
return new BatchOptimizedTokenGenerator(
$c->get(RandomGenerator::class),
batchSize: 100 // Tokens in Batches vorgenerieren
);
});
}
}
```
### Test-Konfiguration
```php
// Für Unit Tests - deterministic aber sichere Werte
final readonly class TestCryptographyInitializer implements Initializer
{
public function initialize(Container $container): void
{
if (!$this->isTestEnvironment()) {
throw new InvalidArgumentException('TestCryptographyInitializer nur in Test-Umgebung verwenden');
}
// Deterministischer aber sicherer Generator für Tests
$container->singleton(RandomGenerator::class, new TestRandomGenerator());
// Reduzierte Parameter für schnellere Tests
$container->singleton(KeyDerivationFunction::class, function(Container $c) {
return new KeyDerivationFunction($c->get(RandomGenerator::class));
});
}
private function isTestEnvironment(): bool
{
return defined('PHPUNIT_RUNNING') ||
(isset($_ENV['APP_ENV']) && $_ENV['APP_ENV'] === 'testing');
}
}
```
## Middleware-Integration
### Automatic Token Validation
```php
final readonly class CryptoTokenValidationMiddleware
{
public function __construct(
private CryptographicUtilities $utils,
private CacheInterface $cache
) {}
public function handle(HttpRequest $request, RequestHandler $handler): HttpResponse
{
$authHeader = $request->server->getAuthorizationHeader();
if ($authHeader && str_starts_with($authHeader, 'Bearer ')) {
$token = substr($authHeader, 7);
// Token-Format validieren
if (!$this->utils->timingSafeEquals($token, trim($token))) {
throw new AuthenticationException('Invalid token format');
}
// Cache für Token-Validierung
$cacheKey = 'token_valid_' . hash('sha256', $token);
if (!$this->cache->has($cacheKey)) {
// Token in Datenbank validieren
$isValid = $this->validateTokenInDatabase($token);
$this->cache->set($cacheKey, $isValid, 300); // 5 Min Cache
}
}
return $handler->handle($request);
}
}
```
## Monitoring und Logging
### Security Event Integration
```php
final readonly class CryptographyEventLogger
{
public function __construct(
private Logger $logger,
private SecurityEventLogger $securityLogger
) {}
public function logTokenGeneration(SecureToken $token): void
{
$this->logger->info('Token generated', [
'type' => $token->getType(),
'format' => $token->getFormat(),
'length' => $token->getLength(),
'fingerprint' => $token->getShortFingerprint()
]);
}
public function logSuspiciousTokenActivity(string $token, string $reason): void
{
$this->securityLogger->logSecurityEvent(
new SuspiciousTokenActivityEvent(
tokenFingerprint: hash('sha256', $token),
reason: $reason,
timestamp: new DateTimeImmutable()
)
);
}
}
```
## Validierung der Konfiguration
```php
final readonly class CryptographyConfigValidator
{
public static function validateConfiguration(Container $container): void
{
// RandomGenerator verfügbar?
if (!$container->has(RandomGenerator::class)) {
throw new ConfigurationException('RandomGenerator nicht registriert');
}
// Cryptography Services verfügbar?
$requiredServices = [
KeyDerivationFunction::class,
SecureTokenGenerator::class,
CryptographicUtilities::class
];
foreach ($requiredServices as $service) {
if (!$container->has($service)) {
throw new ConfigurationException("Service nicht registriert: {$service}");
}
}
// Sicherheitsparameter validieren
$kdf = $container->get(KeyDerivationFunction::class);
try {
$params = $kdf->getRecommendedParameters('pbkdf2-sha256', 'standard');
if ($params['iterations'] < 50000) {
throw new ConfigurationException('PBKDF2 Iterationen zu niedrig (Minimum: 50000)');
}
} catch (InvalidArgumentException $e) {
throw new ConfigurationException('Ungültige KDF-Konfiguration: ' . $e->getMessage());
}
}
}
```
Diese Konfiguration ermöglicht es, das Cryptography Module flexibel an verschiedene Umgebungen und Sicherheitsanforderungen anzupassen, während Best Practices für Sicherheit und Performance eingehalten werden.

View File

@@ -0,0 +1,703 @@
# Cryptography Module - Praktische Beispiele
Umfassende Sammlung praktischer Anwendungsfälle für das Cryptography Module.
## Authentifizierung und Session-Management
### User Password System
```php
final readonly class UserAuthenticationService
{
public function __construct(
private KeyDerivationFunction $kdf,
private SecureTokenGenerator $tokenGenerator,
private UserRepository $userRepository
) {}
public function registerUser(string $email, string $password): User
{
// Password hashen mit Argon2ID
$hashedPassword = $this->kdf->hashPassword($password, 'argon2id', [
'memory_cost' => 65536, // 64 MB
'time_cost' => 4, // 4 Iterationen
'threads' => 3 // 3 Threads
]);
$user = new User(
id: Ulid::generate(),
email: new Email($email),
passwordHash: $hashedPassword,
createdAt: new DateTimeImmutable()
);
return $this->userRepository->save($user);
}
public function authenticateUser(string $email, string $password): ?SessionToken
{
$user = $this->userRepository->findByEmail(new Email($email));
if (!$user || !$this->kdf->verify($password, $user->getPasswordHash())) {
// Timing-Angriffe verhindern durch konstante Ausführungszeit
$this->kdf->hashPassword('dummy-password', 'argon2id');
return null;
}
// Session Token generieren
$sessionToken = $this->tokenGenerator->generateSessionToken(48); // 384 Bit
// In Session Store speichern
$this->storeSessionToken($user, $sessionToken);
return $sessionToken;
}
private function storeSessionToken(User $user, SecureToken $token): void
{
$session = new UserSession(
tokenHash: hash('sha256', $token->getValue()),
userId: $user->getId(),
expiresAt: (new DateTimeImmutable())->add(new DateInterval('PT24H')),
metadata: $token->getMetadata()
);
// Session in Datenbank speichern (nur Hash, nie Klartext!)
$this->sessionRepository->save($session);
}
}
```
### API Key Management System
```php
final readonly class ApiKeyManagementService
{
public function __construct(
private SecureTokenGenerator $tokenGenerator,
private CryptographicUtilities $utils,
private ApiKeyRepository $repository
) {}
public function createApiKey(
User $user,
string $name,
array $scopes = [],
?DateTimeImmutable $expiresAt = null
): ApiKeyResult {
// API Key mit Prefix generieren
$apiKey = $this->tokenGenerator->generateApiKey(
prefix: 'ak',
length: 32
);
// API Key Entity erstellen (Hash speichern, nicht Klartext)
$apiKeyEntity = new ApiKey(
id: Ulid::generate(),
userId: $user->getId(),
name: $name,
keyHash: hash('sha256', $apiKey->getValue()),
fingerprint: $apiKey->getFingerprint(),
scopes: $scopes,
expiresAt: $expiresAt,
createdAt: new DateTimeImmutable()
);
$this->repository->save($apiKeyEntity);
return new ApiKeyResult(
apiKey: $apiKey->getValue(), // Nur einmal zurückgeben
keyId: $apiKeyEntity->getId(),
fingerprint: $apiKey->getShortFingerprint(),
expiresAt: $expiresAt
);
}
public function validateApiKey(string $apiKey): ?ApiKey
{
$keyHash = hash('sha256', $apiKey);
$storedKey = $this->repository->findByHash($keyHash);
if (!$storedKey) {
return null;
}
// Timing-sicherer Vergleich
if (!$this->utils->timingSafeEquals($keyHash, $storedKey->getKeyHash())) {
return null;
}
// Expiration prüfen
if ($storedKey->getExpiresAt() && $storedKey->getExpiresAt() < new DateTimeImmutable()) {
return null;
}
return $storedKey;
}
public function rotateApiKey(string $currentApiKey): ApiKeyResult
{
$oldKey = $this->validateApiKey($currentApiKey);
if (!$oldKey) {
throw new ApiKeyException('Invalid API key for rotation');
}
// Neuen Key mit gleichen Eigenschaften erstellen
$newApiKey = $this->createApiKey(
user: $oldKey->getUser(),
name: $oldKey->getName() . ' (rotated)',
scopes: $oldKey->getScopes(),
expiresAt: $oldKey->getExpiresAt()
);
// Alten Key deaktivieren (nicht löschen für Audit-Trail)
$oldKey->deactivate();
$this->repository->save($oldKey);
return $newApiKey;
}
}
```
## CSRF Protection
### CSRF Token System
```php
final readonly class CsrfProtectionService
{
public function __construct(
private SecureTokenGenerator $tokenGenerator,
private CacheInterface $cache
) {}
public function generateCsrfToken(string $sessionId): SecureToken
{
$csrfToken = $this->tokenGenerator->generateCsrfToken();
// Token mit Session verknüpfen
$cacheKey = "csrf_token_{$sessionId}";
$this->cache->set($cacheKey, $csrfToken->getValue(), 3600); // 1 Stunde
return $csrfToken;
}
public function validateCsrfToken(string $sessionId, string $providedToken): bool
{
$cacheKey = "csrf_token_{$sessionId}";
$storedToken = $this->cache->get($cacheKey);
if (!$storedToken) {
return false;
}
// Timing-sicherer Vergleich
$isValid = hash_equals($storedToken, $providedToken);
// Token nach Verwendung löschen (Single-Use)
if ($isValid) {
$this->cache->delete($cacheKey);
}
return $isValid;
}
}
// CSRF Middleware
final readonly class CsrfProtectionMiddleware
{
public function __construct(
private CsrfProtectionService $csrfService
) {}
public function handle(HttpRequest $request, RequestHandler $handler): HttpResponse
{
// Nur bei state-changing Operations prüfen
if (in_array($request->method, [Method::POST, Method::PUT, Method::DELETE, Method::PATCH])) {
$sessionId = $request->session->getId();
$csrfToken = $request->parsedBody->get('_token') ?? $request->headers->get('X-CSRF-Token');
if (!$csrfToken || !$this->csrfService->validateCsrfToken($sessionId, $csrfToken)) {
throw new CsrfTokenMismatchException('CSRF token mismatch');
}
}
return $handler->handle($request);
}
}
```
## Webhook Security
### Webhook Signature System
```php
final readonly class WebhookSecurityService
{
public function __construct(
private SecureTokenGenerator $tokenGenerator,
private CryptographicUtilities $utils
) {}
public function generateWebhookSecret(): SecureToken
{
return $this->tokenGenerator->generateWebhookToken();
}
public function signWebhookPayload(string $payload, SecureToken $secret): string
{
$signature = hash_hmac('sha256', $payload, $secret->getValue());
return 'sha256=' . $signature;
}
public function validateWebhookSignature(
string $payload,
string $signature,
SecureToken $secret
): bool {
$expectedSignature = $this->signWebhookPayload($payload, $secret);
// Timing-sicherer Vergleich
return $this->utils->timingSafeEquals($signature, $expectedSignature);
}
}
// Webhook Handler
final readonly class PaymentWebhookHandler
{
public function __construct(
private WebhookSecurityService $security,
private WebhookConfigRepository $configRepository
) {}
#[Route(path: '/webhooks/payment', method: Method::POST)]
public function handlePaymentWebhook(HttpRequest $request): JsonResult
{
$signature = $request->headers->get('X-Hub-Signature-256');
$payload = $request->rawBody();
if (!$signature) {
throw new WebhookException('Missing signature header');
}
// Webhook Secret für den Sender abrufen
$senderId = $request->headers->get('X-Sender-ID');
$config = $this->configRepository->findBySenderId($senderId);
if (!$config) {
throw new WebhookException('Unknown sender');
}
// Signatur validieren
if (!$this->security->validateWebhookSignature($payload, $signature, $config->getSecret())) {
throw new WebhookException('Invalid signature');
}
// Payload verarbeiten
$data = json_decode($payload, true);
$this->processPaymentEvent($data);
return new JsonResult(['status' => 'processed']);
}
}
```
## Two-Factor Authentication (2FA)
### OTP-basiertes 2FA System
```php
final readonly class TwoFactorAuthService
{
public function __construct(
private SecureTokenGenerator $tokenGenerator,
private CacheInterface $cache,
private NotificationService $notificationService
) {}
public function generateOtpCode(User $user): string
{
$otpToken = $this->tokenGenerator->generateOtpToken(6); // 6-stelliger Code
// OTP mit User-ID und Expiration speichern
$cacheKey = "otp_{$user->getId()}";
$otpData = [
'code' => $otpToken->getValue(),
'attempts' => 0,
'created_at' => time()
];
$this->cache->set($cacheKey, $otpData, 300); // 5 Minuten gültig
return $otpToken->getValue();
}
public function sendOtpCode(User $user): void
{
$otpCode = $this->generateOtpCode($user);
// SMS oder Email versenden
$this->notificationService->sendOtpCode(
recipient: $user->getPhoneNumber() ?? $user->getEmail(),
code: $otpCode,
expiresInMinutes: 5
);
}
public function verifyOtpCode(User $user, string $providedCode): bool
{
$cacheKey = "otp_{$user->getId()}";
$otpData = $this->cache->get($cacheKey);
if (!$otpData) {
return false; // Kein OTP vorhanden oder abgelaufen
}
// Rate-Limiting: Max 3 Versuche
if ($otpData['attempts'] >= 3) {
$this->cache->delete($cacheKey);
return false;
}
// Timing-sicherer Vergleich
$isValid = hash_equals($otpData['code'], $providedCode);
if ($isValid) {
// Erfolgreiche Verifikation - OTP löschen
$this->cache->delete($cacheKey);
} else {
// Fehlversuch - Counter erhöhen
$otpData['attempts']++;
$this->cache->set($cacheKey, $otpData, 300);
}
return $isValid;
}
}
```
## Digitale Signaturen für Dokumente
### Document Signing Service
```php
final readonly class DocumentSigningService
{
public function __construct(
private DigitalSignature $signature,
private DocumentRepository $documentRepository
) {}
public function generateSigningKeyPair(): KeyPair
{
// RSA 4096 Bit für langfristige Dokumentensignaturen
return $this->signature->generateRsaKeyPair(4096);
}
public function signDocument(
Document $document,
PrivateKey $privateKey,
User $signer
): SignedDocument {
$documentContent = $document->getContent();
$metadata = [
'document_id' => $document->getId(),
'signer_id' => $signer->getId(),
'signed_at' => (new DateTimeImmutable())->format('c'),
'algorithm' => 'RSA-SHA256'
];
// Dokument + Metadaten signieren
$dataToSign = $documentContent . json_encode($metadata);
$signatureResult = $this->signature->sign($dataToSign, $privateKey, 'sha256');
$signedDocument = new SignedDocument(
originalDocument: $document,
signature: $signatureResult,
signerPublicKey: $privateKey->getPublicKey(),
metadata: $metadata,
signedAt: new DateTimeImmutable()
);
return $this->documentRepository->saveSignedDocument($signedDocument);
}
public function verifyDocumentSignature(SignedDocument $signedDocument): bool
{
$document = $signedDocument->getOriginalDocument();
$metadata = $signedDocument->getMetadata();
$dataToVerify = $document->getContent() . json_encode($metadata);
return $this->signature->verify(
$dataToVerify,
$signedDocument->getSignature(),
$signedDocument->getSignerPublicKey()
);
}
public function createSignatureChain(array $documents, array $signers): SignatureChain
{
$chain = new SignatureChain();
foreach ($documents as $index => $document) {
$signer = $signers[$index];
$signedDocument = $this->signDocument($document, $signer->getPrivateKey(), $signer);
$chain->addSignedDocument($signedDocument);
}
// Chain-Signatur erstellen (Hash der gesamten Kette)
$chainHash = $chain->calculateChainHash();
$chainSignature = $this->signature->sign($chainHash, $signers[0]->getPrivateKey());
$chain->setChainSignature($chainSignature);
return $chain;
}
}
```
## Passwort-Reset System
### Secure Password Reset
```php
final readonly class PasswordResetService
{
public function __construct(
private SecureTokenGenerator $tokenGenerator,
private KeyDerivationFunction $kdf,
private CacheInterface $cache,
private EmailService $emailService
) {}
public function initiatePasswordReset(User $user): void
{
// Sicheren Reset-Token generieren
$resetToken = $this->tokenGenerator->generateVerificationToken('password_reset');
// Token hashen und speichern (nie Klartext speichern)
$tokenHash = hash('sha256', $resetToken->getValue());
$resetData = [
'user_id' => $user->getId(),
'token_hash' => $tokenHash,
'created_at' => time(),
'used' => false
];
// 2 Stunden gültig
$cacheKey = "password_reset_{$user->getId()}";
$this->cache->set($cacheKey, $resetData, 7200);
// Reset-Link per Email senden
$resetLink = "https://app.example.com/reset-password?token=" .
urlencode($resetToken->getValue());
$this->emailService->send(
to: $user->getEmail(),
subject: 'Password Reset Request',
template: 'password_reset',
data: ['reset_link' => $resetLink, 'expires_in' => '2 hours']
);
}
public function validateResetToken(string $token): ?User
{
$tokenHash = hash('sha256', $token);
// Token in allen aktiven Reset-Anfragen suchen
$cacheKeys = $this->cache->getKeysByPattern('password_reset_*');
foreach ($cacheKeys as $cacheKey) {
$resetData = $this->cache->get($cacheKey);
if ($resetData &&
!$resetData['used'] &&
hash_equals($resetData['token_hash'], $tokenHash)) {
return $this->userRepository->find($resetData['user_id']);
}
}
return null;
}
public function resetPassword(string $token, string $newPassword): bool
{
$user = $this->validateResetToken($token);
if (!$user) {
return false;
}
// Neues Password hashen
$hashedPassword = $this->kdf->hashPassword($newPassword, 'argon2id');
// User Password aktualisieren
$user->updatePassword($hashedPassword);
$this->userRepository->save($user);
// Reset-Token als verwendet markieren
$cacheKey = "password_reset_{$user->getId()}";
$resetData = $this->cache->get($cacheKey);
if ($resetData) {
$resetData['used'] = true;
$this->cache->set($cacheKey, $resetData, 7200);
}
return true;
}
}
```
## Daten-Verschlüsselung mit Schlüssel-Ableitung
### Encrypted Data Storage
```php
final readonly class EncryptedDataService
{
public function __construct(
private KeyDerivationFunction $kdf,
private CryptographicUtilities $utils,
private EncryptionService $encryption
) {}
public function encryptPersonalData(
array $personalData,
string $userPassword
): EncryptedPersonalData {
// Benutzer-spezifischen Schlüssel aus Password ableiten
$salt = $this->utils->generateNonce(32);
$derivedKey = $this->kdf->pbkdf2($userPassword, $salt, 100000, 32);
// Daten serialisieren und verschlüsseln
$serializedData = json_encode($personalData);
$encryptedData = $this->encryption->encrypt($serializedData, $derivedKey->getKey());
return new EncryptedPersonalData(
encryptedData: $encryptedData,
salt: $salt,
keyDerivation: [
'algorithm' => $derivedKey->getAlgorithm(),
'iterations' => $derivedKey->getIterations()
]
);
}
public function decryptPersonalData(
EncryptedPersonalData $encryptedData,
string $userPassword
): array {
// Gleichen Schlüssel aus Password ableiten
$derivedKey = $this->kdf->pbkdf2(
$userPassword,
$encryptedData->getSalt(),
$encryptedData->getKeyDerivation()['iterations'],
32
);
// Daten entschlüsseln
$decryptedData = $this->encryption->decrypt(
$encryptedData->getEncryptedData(),
$derivedKey->getKey()
);
return json_decode($decryptedData, true);
}
}
```
## Audit-Trail mit Kryptographischen Fingerprints
### Secure Audit Trail
```php
final readonly class AuditTrailService
{
public function __construct(
private CryptographicUtilities $utils,
private DigitalSignature $signature,
private AuditLogRepository $repository
) {}
public function logUserAction(
User $user,
string $action,
array $context = []
): AuditLogEntry {
$timestamp = new DateTimeImmutable();
$logData = [
'user_id' => $user->getId(),
'action' => $action,
'context' => $context,
'timestamp' => $timestamp->format('c'),
'ip_address' => $this->getClientIpHash(),
'user_agent_hash' => $this->getUserAgentHash()
];
// Kryptographischen Fingerprint erstellen
$dataString = json_encode($logData, JSON_SORT_KEYS);
$fingerprint = hash('sha256', $dataString);
// Chain-Hash (verhindert Manipulation der Historie)
$previousEntry = $this->repository->getLatestEntry();
$chainHash = $previousEntry
? hash('sha256', $previousEntry->getChainHash() . $fingerprint)
: $fingerprint;
$auditEntry = new AuditLogEntry(
id: Ulid::generate(),
fingerprint: $fingerprint,
chainHash: $chainHash,
logData: $logData,
createdAt: $timestamp
);
return $this->repository->save($auditEntry);
}
public function verifyAuditTrailIntegrity(): bool
{
$entries = $this->repository->getAllEntriesOrdered();
$previousChainHash = null;
foreach ($entries as $entry) {
// Fingerprint verifizieren
$dataString = json_encode($entry->getLogData(), JSON_SORT_KEYS);
$expectedFingerprint = hash('sha256', $dataString);
if (!hash_equals($entry->getFingerprint(), $expectedFingerprint)) {
return false; // Entry wurde manipuliert
}
// Chain-Hash verifizieren
$expectedChainHash = $previousChainHash
? hash('sha256', $previousChainHash . $entry->getFingerprint())
: $entry->getFingerprint();
if (!hash_equals($entry->getChainHash(), $expectedChainHash)) {
return false; // Chain wurde unterbrochen
}
$previousChainHash = $entry->getChainHash();
}
return true;
}
private function getClientIpHash(): string
{
$clientIp = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
return hash('sha256', $clientIp); // IP nicht im Klartext speichern
}
private function getUserAgentHash(): string
{
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
return hash('sha256', $userAgent);
}
}
```
Diese Beispiele zeigen die praktische Anwendung des Cryptography Modules in realen Szenarien und demonstrieren Best Practices für sichere Implementierungen.

View File

@@ -0,0 +1,365 @@
# Cryptography Module
Das Cryptography Module erweitert die bestehenden Verschlüsselungsfunktionen des Frameworks um moderne kryptographische Primitive und bietet sichere Implementierungen für Schlüsselableitung, digitale Signaturen, erweiterte Hash-Funktionen und sichere Token-Generierung.
## Überblick
Das Modul folgt den Framework-Prinzipien:
- **Immutable Value Objects** für sichere Datenrepräsentation
- **Service Pattern** für Business Logic
- **Dependency Injection** für RandomGenerator Integration
- **Security-First Design** mit timing-sicheren Operationen
## Core Services
### KeyDerivationFunction Service
Sichere Schlüsselableitung für Password-Hashing und Key-Stretching.
```php
use App\Framework\Cryptography\KeyDerivationFunction;
use App\Framework\Random\SecureRandomGenerator;
$kdf = new KeyDerivationFunction(new SecureRandomGenerator());
// PBKDF2 (Standard)
$derivedKey = $kdf->pbkdf2('password', $salt, 100000, 32);
// Argon2ID (Empfohlen)
$derivedKey = $kdf->argon2id('password', $salt, 65536, 4, 3, 32);
// Password mit automatischer Salt-Generierung hashen
$derivedKey = $kdf->hashPassword('password', 'argon2id');
// Password verifizieren
$isValid = $kdf->verify('password', $derivedKey);
```
**Unterstützte Algorithmen:**
- **PBKDF2** mit SHA-256, SHA-512, SHA-384, SHA-224
- **Argon2ID** (empfohlen für neue Implementierungen)
- **scrypt** für spezielle Anwendungsfälle
### DigitalSignature Service
Digitale Signaturen für Datenintegrität und Authentifizierung.
```php
use App\Framework\Cryptography\DigitalSignature;
$signature = new DigitalSignature(new SecureRandomGenerator());
// RSA Schlüsselpaar generieren
$keyPair = $signature->generateRsaKeyPair(2048);
// Daten signieren
$signatureResult = $signature->sign('data to sign', $keyPair->getPrivateKey());
// Signatur verifizieren
$isValid = $signature->verify('data to sign', $signatureResult, $keyPair->getPublicKey());
// ECDSA mit secp256r1
$ecKeyPair = $signature->generateEcdsaKeyPair('secp256r1');
$ecSignature = $signature->signWithEcdsa('data', $ecKeyPair->getPrivateKey());
```
### AdvancedHash Service
Erweiterte Hash-Funktionen über grundlegende Algorithmen hinaus.
```php
use App\Framework\Cryptography\AdvancedHash;
$hash = new AdvancedHash();
// SHA-3 Familie
$sha3 = $hash->sha3('data', 256);
$shake = $hash->shake('data', 32, 128); // Extendable-output function
// BLAKE2
$blake2b = $hash->blake2b('data', 32, 'optional-key');
$blake2s = $hash->blake2s('data', 16);
// Hash-Ketten für komplexe Szenarien
$chainResult = $hash->hashChain('data', ['sha3-256', 'blake2b']);
```
### SecureTokenGenerator Service
Kryptographisch sichere Token-Generierung für APIs, Sessions und mehr.
```php
use App\Framework\Cryptography\SecureTokenGenerator;
$generator = new SecureTokenGenerator(new SecureRandomGenerator());
// API Keys mit Prefix
$apiKey = $generator->generateApiKey('myapp'); // myapp_...
// Session Tokens
$sessionToken = $generator->generateSessionToken();
// CSRF Tokens
$csrfToken = $generator->generateCsrfToken();
// OTP Tokens
$otp = $generator->generateOtpToken(6); // 6-stelliger numerischer Code
// Custom Tokens mit eigenem Alphabet
$customToken = $generator->generateCustom('0123456789ABCDEF', 16);
// Batch-Generierung
$tokens = $generator->generateBatch('session', 10, 32);
```
**Token-Formate:**
- `FORMAT_BASE64_URL` (Standard, URL-sicher)
- `FORMAT_BASE64` (Standard Base64)
- `FORMAT_HEX` (Hexadezimal)
- `FORMAT_BASE32` (Base32)
- `FORMAT_ALPHANUMERIC` (Buchstaben + Zahlen)
### CryptographicUtilities Service
Sammlung kryptographischer Utility-Funktionen.
```php
use App\Framework\Cryptography\CryptographicUtilities;
$utils = new CryptographicUtilities(new SecureRandomGenerator());
// Timing-sichere String-Vergleiche
$isEqual = $utils->timingSafeEquals($string1, $string2);
// Entropie-Validierung
$isHighEntropy = $utils->validateEntropy($data, 7.0);
$entropy = $utils->calculateShannonEntropy($data);
// Sichere UUIDs
$uuid4 = $utils->generateUuid4(); // Zufällige UUID
$uuid5 = $utils->generateUuid5($namespace, 'name'); // Deterministische UUID
// Key-Stretching
$stretched = $utils->stretchKey('password', 'salt', 10000, 32);
// Speicher sicher löschen
$utils->secureWipe($sensitiveData);
```
## Value Objects
### DerivedKey
Unveränderliche Repräsentation abgeleiteter Schlüssel.
```php
// Eigenschaften abrufen
$algorithm = $derivedKey->getAlgorithm(); // 'pbkdf2-sha256'
$keyLength = $derivedKey->getKeyLength(); // 32
$iterations = $derivedKey->getIterations(); // 100000
// Verschiedene Formate
$hex = $derivedKey->toHex();
$base64 = $derivedKey->toBase64();
// Serialisierung
$array = $derivedKey->toArray();
$restored = DerivedKey::fromArray($array);
// Gleichheit prüfen (timing-sicher)
$isEqual = $derivedKey->equals($otherKey);
```
### SecureToken
Token mit Metadaten und sicherheitsfokussierten Funktionen.
```php
// Token-Eigenschaften
$type = $token->getType(); // 'api_key'
$format = $token->getFormat(); // 'base64_url'
$hasPrefix = $token->hasPrefix(); // true/false
// Sichere Operationen
$isEqual = $token->equals($otherToken); // timing-sicher
$isValid = $token->verify($candidateToken); // timing-sicher
// Sicherheit und Logging
$masked = $token->getMaskedValue(); // myap****_Ab...fG
$fingerprint = $token->getFingerprint(); // SHA-256 Hash
$safeSummary = $token->getSafeSummary(); // Ohne Token-Wert
```
### KeyPair, PrivateKey, PublicKey
Sichere Verwaltung asymmetrischer Schlüssel.
```php
$keyPair = $signature->generateRsaKeyPair(2048);
$privateKey = $keyPair->getPrivateKey();
$publicKey = $keyPair->getPublicKey();
// Schlüssel-Export
$privatePem = $privateKey->toPem();
$publicPem = $publicKey->toPem();
// Schlüssel-Import
$privateKey = PrivateKey::fromPem($privatePem);
$publicKey = PublicKey::fromPem($publicPem);
```
## Sicherheitsfeatures
### Timing-Attack Schutz
Alle kritischen Vergleichsoperationen verwenden timing-sichere Implementierungen:
```php
// Timing-sichere String-Vergleiche
$utils->timingSafeEquals($secret1, $secret2);
// Timing-sichere Token-Verifikation
$token->verify($candidateToken);
// Timing-sichere Array-Suche
$utils->constantTimeArraySearch($haystack, $needle);
```
### Entropie-Validierung
Automatische Validierung der Schlüsselstärke:
```php
// Shannon-Entropie berechnen
$entropy = $utils->calculateShannonEntropy($data);
// Mindest-Entropie validieren
$isStrong = $utils->validateEntropy($data, 7.0);
// Schlüsselstärke prüfen
$isValidKey = $utils->validateKeyStrength($key, 128); // Minimum 128 Bits
```
### Sichere Speicher-Verwaltung
```php
// Sensitive Daten sicher löschen
$utils->secureWipe($password); // Überschreibt Speicher
// Automatische Metadaten-Bereinigung in Token-Logs
$safeSummary = $token->getSafeSummary(); // Ohne sensitive Werte
```
## Best Practices
### Empfohlene Parameter
```php
// PBKDF2 (Minimum)
$kdf->pbkdf2($password, $salt, 100000, 32, 'sha256');
// Argon2ID (Empfohlen)
$kdf->argon2id($password, $salt, 65536, 4, 3, 32);
// RSA Schlüssel (Minimum 2048 Bit)
$signature->generateRsaKeyPair(2048);
// Token-Längen
$generator->generateApiKey('prefix', 32); // 256 Bit
$generator->generateSessionToken(48); // 384 Bit für langlebige Sessions
```
### Sichere Implementierung
```php
// ✅ Gute Praxis
final readonly class AuthService
{
public function __construct(
private readonly KeyDerivationFunction $kdf,
private readonly SecureTokenGenerator $tokenGenerator
) {}
public function hashPassword(string $password): DerivedKey
{
return $this->kdf->hashPassword($password, 'argon2id');
}
public function generateApiKey(string $prefix): SecureToken
{
return $this->tokenGenerator->generateApiKey($prefix, 32);
}
}
// ❌ Schlechte Praxis - Nicht verwenden
// $hashedPassword = md5($password); // Unsicher
// $token = bin2hex(random_bytes(16)); // Zu kurz, keine Metadaten
```
## Integration mit Framework
### Dependency Injection
```php
final readonly class CryptographyServiceInitializer implements Initializer
{
public function initialize(Container $container): void
{
$randomGenerator = $container->get(RandomGenerator::class);
$container->singleton(KeyDerivationFunction::class,
new KeyDerivationFunction($randomGenerator));
$container->singleton(SecureTokenGenerator::class,
new SecureTokenGenerator($randomGenerator));
$container->singleton(CryptographicUtilities::class,
new CryptographicUtilities($randomGenerator));
}
}
```
### Controller Integration
```php
final readonly class ApiKeyController
{
#[Route(path: '/admin/api-keys', method: Method::POST)]
#[Auth(strategy: 'ip', allowedIps: ['127.0.0.1'])]
public function createApiKey(
CreateApiKeyRequest $request,
SecureTokenGenerator $tokenGenerator
): JsonResult {
$apiKey = $tokenGenerator->generateApiKey(
prefix: $request->prefix,
length: 32
);
// Token sicher in Datenbank speichern
// Nur Hash oder verschlüsselte Version speichern, nie Klartext
return new JsonResult([
'api_key' => $apiKey->getValue(),
'fingerprint' => $apiKey->getShortFingerprint(),
'created_at' => $apiKey->getCreatedAt()->format('c')
]);
}
}
```
## Performance
Das Cryptography Module ist für Production-Einsatz optimiert:
- **Cached Reflection Provider** für Dependency Injection
- **Batch-Operationen** für Token-Generierung
- **Effiziente Algorithmen** mit modernen kryptographischen Standards
- **Minimale Speicher-Allokation** durch readonly Value Objects
## Weiterführende Dokumentation
- [Konfiguration](configuration.md) - Setup und Anpassung
- [Beispiele](examples.md) - Praktische Anwendungsfälle
- [Migration](migration.md) - Upgrade von älteren Krypto-Implementierungen
- [Sicherheit](security.md) - Detaillierte Sicherheitsrichtlinien

View File

@@ -0,0 +1,728 @@
# Cryptography Module - Sicherheitsrichtlinien
Detaillierte Sicherheitsrichtlinien und Best Practices für das Cryptography Module.
## Grundlegende Sicherheitsprinzipien
### Defense in Depth
Das Cryptography Module implementiert mehrschichtigen Schutz:
1. **Algorithmus-Ebene**: Moderne, peer-reviewed Algorithmen (Argon2ID, SHA-3, ECDSA)
2. **Implementation-Ebene**: Timing-sichere Operationen und sichere Speicherverwaltung
3. **Application-Ebene**: Sichere Integration und Konfiguration
4. **System-Ebene**: Sicherer Random Number Generator und Entropie-Validierung
### Zero-Trust Architektur
```php
// ✅ Vertraue niemals Eingaben - validiere alles
final readonly class SecureTokenValidator
{
public function validateApiKey(string $providedKey): ?ApiKeyContext
{
// Eingabe-Validierung
if (empty($providedKey) || strlen($providedKey) < 32) {
return null;
}
// Format-Validierung
if (!$this->tokenGenerator->isValidFormat($providedKey, 'base64_url')) {
return null;
}
// Timing-sicherer Vergleich mit gespeichertem Hash
$keyHash = hash('sha256', $providedKey);
$storedKey = $this->repository->findByHash($keyHash);
if (!$storedKey || !hash_equals($keyHash, $storedKey->getHash())) {
return null;
}
// Zusätzliche Sicherheitsprüfungen
return $this->performSecurityChecks($storedKey);
}
}
```
## Kryptographische Best Practices
### Sichere Schlüssel-Ableitung
```php
// ✅ Empfohlene Parameter für verschiedene Szenarien
final readonly class SecureKeyDerivation
{
private const SECURITY_LEVELS = [
// Hohe Sicherheit für sensitive Daten
'high_security' => [
'algorithm' => 'argon2id',
'memory_cost' => 131072, // 128 MB
'time_cost' => 6, // 6 Iterationen
'threads' => 4, // 4 Threads
'key_length' => 32 // 256 Bit
],
// Standard für normale Anwendungen
'standard' => [
'algorithm' => 'argon2id',
'memory_cost' => 65536, // 64 MB
'time_cost' => 4, // 4 Iterationen
'threads' => 3, // 3 Threads
'key_length' => 32 // 256 Bit
],
// Kompatibilität mit älteren Systemen
'legacy_compatible' => [
'algorithm' => 'pbkdf2-sha256',
'iterations' => 200000, // 200k Iterationen
'key_length' => 32 // 256 Bit
]
];
public function hashPassword(string $password, string $level = 'standard'): DerivedKey
{
$params = self::SECURITY_LEVELS[$level] ?? self::SECURITY_LEVELS['standard'];
return match ($params['algorithm']) {
'argon2id' => $this->kdf->argon2id(
$password,
$this->kdf->generateSalt(32),
$params['memory_cost'],
$params['time_cost'],
$params['threads'],
$params['key_length']
),
'pbkdf2-sha256' => $this->kdf->pbkdf2(
$password,
$this->kdf->generateSalt(32),
$params['iterations'],
$params['key_length']
)
};
}
}
```
### Sichere Token-Generierung
```php
// ✅ Token-Sicherheit nach Verwendungszweck
final readonly class SecurityAwareTokenGenerator
{
private const TOKEN_SECURITY_REQUIREMENTS = [
'api_key' => [
'length' => 32, // 256 Bit
'format' => 'base64_url',
'entropy_min' => 7.0,
'expires' => false, // Langlebig
'single_use' => false
],
'session' => [
'length' => 48, // 384 Bit (höhere Sicherheit)
'format' => 'base64_url',
'entropy_min' => 7.5,
'expires' => true,
'single_use' => false
],
'csrf' => [
'length' => 32, // 256 Bit
'format' => 'base64_url',
'entropy_min' => 7.0,
'expires' => true, // Kurze Lebensdauer
'single_use' => true // Einmalverwendung
],
'password_reset' => [
'length' => 64, // 512 Bit (maximale Sicherheit)
'format' => 'base64_url',
'entropy_min' => 7.8,
'expires' => true,
'single_use' => true,
'max_lifetime' => 3600 * 2 // 2 Stunden
]
];
public function generateSecureToken(string $type): SecureToken
{
$requirements = self::TOKEN_SECURITY_REQUIREMENTS[$type] ??
throw new InvalidArgumentException("Unknown token type: {$type}");
do {
$token = $this->tokenGenerator->generate(
$type,
$requirements['length'],
$requirements['format']
);
// Entropie validieren
$entropy = $this->utils->calculateShannonEntropy($token->getRawBytes());
} while ($entropy < $requirements['entropy_min']);
return $token;
}
}
```
## Timing-Attack Prevention
### Konstante Ausführungszeit
```php
// ✅ Timing-sichere Implementierung
final readonly class TimingSafeOperations
{
public function authenticateUser(string $email, string $password): ?User
{
$user = $this->userRepository->findByEmail(new Email($email));
// WICHTIG: Immer Hashing durchführen, auch bei ungültigem User
$providedHash = $user
? $user->getPasswordHash()
: $this->createDummyHash(); // Konstante Ausführungszeit
$isValid = $this->kdf->verify($password, $providedHash);
// Zusätzliche konstante Verzögerung
$this->enforceConstantTime();
return $isValid && $user ? $user : null;
}
private function createDummyHash(): DerivedKey
{
// Dummy-Hash mit gleichen Parametern wie echte Hashes
static $dummyHash = null;
if ($dummyHash === null) {
$dummyHash = $this->kdf->hashPassword('dummy-password', 'argon2id');
}
return $dummyHash;
}
private function enforceConstantTime(): void
{
// Minimale zusätzliche Verzögerung (1-5ms)
usleep(random_int(1000, 5000));
}
}
```
### Side-Channel Resistance
```php
// ✅ Schutz vor Side-Channel-Angriffen
final readonly class SideChannelResistantComparison
{
public function compareSecrets(string $secret1, string $secret2): bool
{
// PHP's hash_equals ist timing-sicher implementiert
return hash_equals($secret1, $secret2);
}
public function compareArrays(array $array1, array $array2): bool
{
// Arrays zu Strings serialisieren für timing-sicheren Vergleich
$string1 = json_encode($array1, JSON_SORT_KEYS);
$string2 = json_encode($array2, JSON_SORT_KEYS);
return hash_equals($string1, $string2);
}
public function searchInArray(array $haystack, mixed $needle): bool
{
$found = false;
// Alle Elemente durchgehen (konstante Zeit)
foreach ($haystack as $value) {
$isMatch = is_string($value) && is_string($needle)
? hash_equals($value, $needle)
: ($value === $needle);
$found = $found || $isMatch; // Kein frühes Beenden
}
return $found;
}
}
```
## Sichere Speicherverwaltung
### Sensitive Data Handling
```php
// ✅ Sicherer Umgang mit sensitiven Daten
final readonly class SecureMemoryManagement
{
public function processSecretData(string $secretData): ProcessedResult
{
try {
// Daten verarbeiten
$result = $this->doSecretProcessing($secretData);
// Sensitive Daten aus Speicher löschen
$this->utils->secureWipe($secretData);
return $result;
} catch (Throwable $e) {
// Auch bei Fehlern Speicher löschen
$this->utils->secureWipe($secretData);
throw $e;
}
}
public function createSecureTemporaryFile(string $data): SecureTemporaryFile
{
// Temporary file mit restriktiven Berechtigungen erstellen
$tempFile = tempnam(sys_get_temp_dir(), 'secure_');
chmod($tempFile, 0600); // Nur Owner kann lesen/schreiben
// Daten schreiben und sofort aus Speicher löschen
file_put_contents($tempFile, $data);
$this->utils->secureWipe($data);
// Auto-cleanup mit Destruktor
return new SecureTemporaryFile($tempFile);
}
}
// Auto-cleanup für temporäre Dateien
final class SecureTemporaryFile
{
public function __construct(private string $filePath) {}
public function __destruct()
{
if (file_exists($this->filePath)) {
// Datei mehrfach überschreiben vor dem Löschen
$fileSize = filesize($this->filePath);
for ($i = 0; $i < 3; $i++) {
file_put_contents($this->filePath, random_bytes($fileSize));
}
unlink($this->filePath);
}
}
public function getPath(): string
{
return $this->filePath;
}
}
```
## Input Validation und Sanitization
### Comprehensive Input Validation
```php
// ✅ Umfassende Eingabe-Validierung
final readonly class CryptographicInputValidator
{
public function validatePasswordStrength(string $password): ValidationResult
{
$errors = [];
// Länge prüfen
if (strlen($password) < 8) {
$errors[] = 'Password must be at least 8 characters long';
}
// Komplexität prüfen
if (!preg_match('/[A-Z]/', $password)) {
$errors[] = 'Password must contain uppercase letters';
}
if (!preg_match('/[a-z]/', $password)) {
$errors[] = 'Password must contain lowercase letters';
}
if (!preg_match('/[0-9]/', $password)) {
$errors[] = 'Password must contain numbers';
}
if (!preg_match('/[^A-Za-z0-9]/', $password)) {
$errors[] = 'Password must contain special characters';
}
// Entropie prüfen
$entropy = $this->utils->calculateShannonEntropy($password);
if ($entropy < 3.5) {
$errors[] = 'Password has insufficient entropy';
}
// Gegen Common-Passwords prüfen
if ($this->isCommonPassword($password)) {
$errors[] = 'Password is too common';
}
return new ValidationResult(empty($errors), $errors);
}
public function validateApiKeyFormat(string $apiKey): bool
{
// Länge prüfen (32-64 Zeichen)
if (strlen($apiKey) < 32 || strlen($apiKey) > 64) {
return false;
}
// Format prüfen (Base64URL)
if (!preg_match('/^[A-Za-z0-9_-]+$/', $apiKey)) {
return false;
}
// Entropie validieren
$entropy = $this->utils->calculateShannonEntropy($apiKey);
return $entropy >= 6.0;
}
public function sanitizeUserInput(string $input): string
{
// Whitespace normalisieren
$sanitized = trim($input);
// Null-Bytes entfernen (verhindern Directory Traversal)
$sanitized = str_replace("\0", '', $sanitized);
// Control Characters entfernen
$sanitized = preg_replace('/[\x00-\x1F\x7F]/', '', $sanitized);
return $sanitized;
}
private function isCommonPassword(string $password): bool
{
$commonPasswords = [
'password', '123456', 'password123', 'admin', 'qwerty',
'letmein', 'welcome', 'monkey', '1234567890', 'password1'
];
$lowercase = strtolower($password);
foreach ($commonPasswords as $common) {
if ($lowercase === $common ||
levenshtein($lowercase, $common) <= 2) {
return true;
}
}
return false;
}
}
```
## Rate Limiting und Abuse Prevention
### Cryptographic Rate Limiting
```php
// ✅ Rate-Limiting für kryptographische Operationen
final readonly class CryptographicRateLimiter
{
private const LIMITS = [
'password_attempts' => ['count' => 5, 'window' => 900], // 5 in 15 Min
'token_generation' => ['count' => 100, 'window' => 3600], // 100 in 1 Stunde
'password_reset' => ['count' => 3, 'window' => 3600], // 3 in 1 Stunde
'otp_generation' => ['count' => 5, 'window' => 300], // 5 in 5 Min
];
public function __construct(
private CacheInterface $cache,
private SecurityEventLogger $securityLogger
) {}
public function checkLimit(string $operation, string $identifier): bool
{
$limit = self::LIMITS[$operation] ?? null;
if (!$limit) {
return true; // Kein Limit definiert
}
$cacheKey = "ratelimit_{$operation}_{$identifier}";
$attempts = $this->cache->get($cacheKey, []);
$now = time();
// Abgelaufene Versuche entfernen
$attempts = array_filter($attempts, fn($timestamp) =>
$now - $timestamp < $limit['window']);
if (count($attempts) >= $limit['count']) {
// Rate-Limit erreicht
$this->securityLogger->logRateLimitExceeded($operation, $identifier);
return false;
}
// Neuen Versuch hinzufügen
$attempts[] = $now;
$this->cache->set($cacheKey, $attempts, $limit['window']);
return true;
}
public function recordFailedAttempt(string $operation, string $identifier): void
{
$cacheKey = "failed_{$operation}_{$identifier}";
$failures = $this->cache->get($cacheKey, 0);
$failures++;
$this->cache->set($cacheKey, $failures, 3600); // 1 Stunde
// Bei vielen Fehlversuchen Sicherheitsteam benachrichtigen
if ($failures >= 10) {
$this->securityLogger->logSuspiciousActivity(
$operation,
$identifier,
"Multiple failed attempts: {$failures}"
);
}
}
}
```
## Error Handling und Information Leakage Prevention
### Secure Error Handling
```php
// ✅ Sichere Fehlerbehandlung ohne Information Leakage
final readonly class SecureErrorHandler
{
public function handleCryptographicError(Throwable $error): ErrorResponse
{
// Detaillierte Logs für interne Analyse
$this->logger->error('Cryptographic error occurred', [
'error_type' => get_class($error),
'message' => $error->getMessage(),
'trace' => $error->getTraceAsString(),
'context' => $this->getSecureContext()
]);
// Generische Antwort für Client (keine Details)
$publicMessage = match (true) {
$error instanceof InvalidPasswordException => 'Authentication failed',
$error instanceof TokenExpiredException => 'Token has expired',
$error instanceof TokenInvalidException => 'Invalid token',
$error instanceof CryptographicException => 'Security operation failed',
default => 'Internal error occurred'
};
return new ErrorResponse(
message: $publicMessage,
code: $this->getPublicErrorCode($error),
timestamp: new DateTimeImmutable()
);
}
private function getSecureContext(): array
{
return [
'request_id' => $this->generateRequestId(),
'user_agent_hash' => hash('sha256', $_SERVER['HTTP_USER_AGENT'] ?? ''),
'ip_hash' => hash('sha256', $_SERVER['REMOTE_ADDR'] ?? ''),
'timestamp' => time()
];
}
private function generateRequestId(): string
{
return bin2hex(random_bytes(16));
}
}
```
## Monitoring und Alerting
### Security Monitoring
```php
// ✅ Sicherheits-Monitoring für kryptographische Operationen
final readonly class CryptographicSecurityMonitor
{
public function __construct(
private MetricsCollector $metrics,
private AlertManager $alerts,
private SecurityEventLogger $securityLogger
) {}
public function monitorOperation(string $operation, callable $callback): mixed
{
$startTime = microtime(true);
$operationId = bin2hex(random_bytes(8));
try {
$result = $callback();
// Erfolgreiche Operation protokollieren
$duration = microtime(true) - $startTime;
$this->metrics->increment("crypto.{$operation}.success");
$this->metrics->timing("crypto.{$operation}.duration", $duration);
// Ungewöhnlich lange Operationen melden
if ($duration > $this->getExpectedDuration($operation) * 2) {
$this->alerts->sendAlert(
level: 'warning',
message: "Slow cryptographic operation: {$operation}",
context: ['duration' => $duration, 'operation_id' => $operationId]
);
}
return $result;
} catch (Throwable $e) {
// Fehlgeschlagene Operation protokollieren
$this->metrics->increment("crypto.{$operation}.failure");
$this->securityLogger->logCryptographicFailure($operation, $e, $operationId);
// Bei kritischen Fehlern sofort alarmieren
if ($this->isCriticalError($e)) {
$this->alerts->sendAlert(
level: 'critical',
message: "Critical cryptographic failure: {$operation}",
context: [
'error' => $e->getMessage(),
'operation_id' => $operationId
]
);
}
throw $e;
}
}
public function detectAnomalousPatterns(): void
{
// Erhöhte Fehlerrate erkennen
$errorRate = $this->metrics->getRate('crypto.*.failure', '5m');
if ($errorRate > 0.1) { // >10% Fehlerrate
$this->alerts->sendAlert(
level: 'warning',
message: 'High cryptographic error rate detected',
context: ['error_rate' => $errorRate]
);
}
// Ungewöhnliche Aktivitätsmuster
$operations = $this->metrics->getCount('crypto.*.success', '1h');
$baseline = $this->getHistoricalBaseline();
if ($operations > $baseline * 5) {
$this->alerts->sendAlert(
level: 'warning',
message: 'Unusual spike in cryptographic operations',
context: ['operations' => $operations, 'baseline' => $baseline]
);
}
}
private function getExpectedDuration(string $operation): float
{
return match ($operation) {
'token_generation' => 0.001, // 1ms
'password_hash' => 0.5, // 500ms (Argon2ID)
'password_verify' => 0.5, // 500ms
'signature_create' => 0.01, // 10ms
'signature_verify' => 0.005, // 5ms
default => 0.1 // 100ms
};
}
}
```
## Compliance und Audit
### Compliance Framework
```php
// ✅ Compliance-Unterstützung für Regulierungen
final readonly class CryptographicComplianceValidator
{
private const COMPLIANCE_REQUIREMENTS = [
'GDPR' => [
'encryption_required' => true,
'key_length_min' => 256,
'algorithm_approved' => ['AES-256-GCM', 'ChaCha20-Poly1305'],
'key_rotation_days' => 365,
'audit_trail_required' => true
],
'PCI_DSS' => [
'encryption_required' => true,
'key_length_min' => 256,
'algorithm_approved' => ['AES-256', 'RSA-2048'],
'key_rotation_days' => 365,
'secure_key_storage' => true
],
'FIPS_140_2' => [
'approved_algorithms_only' => true,
'algorithm_approved' => ['AES', 'SHA-256', 'RSA', 'ECDSA'],
'random_number_generator' => 'FIPS_approved',
'key_length_min' => 256
]
];
public function validateCompliance(string $standard): ComplianceReport
{
$requirements = self::COMPLIANCE_REQUIREMENTS[$standard] ??
throw new InvalidArgumentException("Unknown standard: {$standard}");
$violations = [];
$report = new ComplianceReport($standard);
// Algorithmus-Compliance prüfen
if (isset($requirements['algorithm_approved'])) {
$usedAlgorithms = $this->getUsedAlgorithms();
$approvedAlgorithms = $requirements['algorithm_approved'];
foreach ($usedAlgorithms as $algorithm) {
if (!in_array($algorithm, $approvedAlgorithms)) {
$violations[] = "Non-approved algorithm in use: {$algorithm}";
}
}
}
// Schlüssel-Längen prüfen
if (isset($requirements['key_length_min'])) {
$keyLengths = $this->getKeyLengths();
$minLength = $requirements['key_length_min'];
foreach ($keyLengths as $context => $length) {
if ($length < $minLength) {
$violations[] = "Key length too short in {$context}: {$length} < {$minLength}";
}
}
}
// Schlüssel-Rotation prüfen
if (isset($requirements['key_rotation_days'])) {
$rotationViolations = $this->checkKeyRotation($requirements['key_rotation_days']);
$violations = array_merge($violations, $rotationViolations);
}
$report->setViolations($violations);
$report->setCompliant(empty($violations));
return $report;
}
public function generateAuditReport(): AuditReport
{
return new AuditReport([
'cryptographic_operations' => $this->getCryptoOperationStats(),
'key_management' => $this->getKeyManagementStats(),
'algorithm_usage' => $this->getAlgorithmUsageStats(),
'security_events' => $this->getSecurityEventSummary(),
'compliance_status' => $this->getComplianceStatus()
]);
}
}
```
Diese Sicherheitsrichtlinien stellen sicher, dass das Cryptography Module höchste Sicherheitsstandards erfüllt und gegen moderne Angriffsvektoren geschützt ist.