0) { return str_pad(substr($b, 0, 32), 32, "\0"); } return str_pad(substr($env, 0, 32), 32, "\0"); } // Fallback: alter Key aus bestehender Installation (32 ASCII-Bytes) return "12345678901234567890123456789012"; } // --- HKDF (SHA-256) über Token -> Session-Key (32 Byte) --- // Kompatibel zu Android-Implementierung: salt = leer, info = "qdb-aes" function hkdf_session_key_from_token(string $tokenHex, string $info = 'qdb-aes', int $len = 32): string { $ikm = @hex2bin(trim($tokenHex)); if ($ikm === false) $ikm = $tokenHex; // Falls bereits binär if (function_exists('hash_hkdf')) { return hash_hkdf('sha256', $ikm, $len, $info, ''); } // Fallback: eigene HKDF-Implementierung $hashLen = 32; $salt = str_repeat("\0", $hashLen); $prk = hash_hmac('sha256', $ikm, $salt, true); $okm = ''; $t = ''; $n = (int)ceil($len / $hashLen); for ($i = 1; $i <= $n; $i++) { $t = hash_hmac('sha256', $t . $info . chr($i), $prk, true); $okm .= $t; } return substr($okm, 0, $len); } // --- Token-Storage (mit Ablauf) --- function tokens_file_path(): string { return __DIR__ . '/tokens.jsonl'; } function token_add(string $token, int $ttlSeconds = 86400): void { $rec = [ 'token' => $token, 'created' => time(), 'exp' => time() + $ttlSeconds, ]; file_put_contents(tokens_file_path(), json_encode($rec) . PHP_EOL, FILE_APPEND | LOCK_EX); // optional weiterhin für Alt-Skripte: file_put_contents(__DIR__ . '/valid_tokens.txt', $token . PHP_EOL, FILE_APPEND | LOCK_EX); } function token_is_valid(string $token): bool { $f = tokens_file_path(); if (!file_exists($f)) return false; $h = fopen($f, 'r'); if (!$h) return false; $now = time(); $valid = false; while (($line = fgets($h)) !== false) { $j = json_decode($line, true); if (!is_array($j)) continue; if (($j['token'] ?? '') === $token && ($j['exp'] ?? 0) >= $now) { $valid = true; break; } } fclose($h); return $valid; } // --- AES-256-CBC: IV(16) + CIPHERTEXT --- function aes256_cbc_encrypt_bytes(string $plain, string $key): string { $key = str_pad(substr($key, 0, 32), 32, "\0"); $iv = random_bytes(16); $cipher = openssl_encrypt($plain, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); if ($cipher === false) throw new Exception('openssl_encrypt failed'); return $iv . $cipher; } function aes256_cbc_decrypt_bytes(string $data, string $key): string { if (strlen($data) < 16) throw new Exception('cipher too short'); $key = str_pad(substr($key, 0, 32), 32, "\0"); $iv = substr($data, 0, 16); $ct = substr($data, 16); $plain = openssl_decrypt($ct, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv); if ($plain === false) throw new Exception('openssl_decrypt failed'); return $plain; }