base64_encode($iv), 'tag' => base64_encode($tag), 'value' => base64_encode($cipherText) ]); } /** * Descriptografa uma string. * * @param string $payload * @return string * @throws Exception */ public static function decrypt(string $payload): string { $algorithm = self::getAlgorithm(); $key = self::getKey(); $decodedPayload = self::decodePayload($payload); $plainText = openssl_decrypt( base64_decode($decodedPayload['value']), $algorithm, $key, OPENSSL_RAW_DATA, base64_decode($decodedPayload['iv']), base64_decode($decodedPayload['tag']) ); if ($plainText === false) { throw new Exception('Failed to decrypt data'); } return $plainText; } /** * Retorna o algoritmo configurado. * * @return string * @throws Exception */ private static function getAlgorithm(): string { $algorithm = $_ENV['SYSTEM_CRYPTO_ALGO']; if (!in_array($algorithm, openssl_get_cipher_methods(), true)) { throw new Exception('Invalid cipher algorithm'); } return $algorithm; } /** * Retorna a chave de criptografia. * * A chave deve ser uma string hexadecimal de 64 caracteres (32 bytes). * * @return string * @throws Exception */ private static function getKey(): string { $hexKey = $_ENV['SYSTEM_CRYPTO_KEY']; if (empty($hexKey)) { throw new Exception('Encryption key not configured'); } $key = hex2bin($hexKey); if ($key === false || strlen($key) !== 32) { throw new Exception(message: 'Invalid encryption key. Expected 32 bytes (64 hex characters).'); } return $key; } /** * Codifica o payload para armazenamento. * * @param array $payload * @return string * @throws JsonException */ private static function encodePayload(array $payload): string { return base64_encode( json_encode( $payload, JSON_THROW_ON_ERROR ) ); } /** * Decodifica o payload criptografado. * * @param string $payload * @return array * @throws Exception */ private static function decodePayload(string $payload): array { try { $decoded = json_decode( base64_decode($payload), true, 512, JSON_THROW_ON_ERROR ); } catch (JsonException $e) { throw new Exception(message: 'Invalid encrypted payload', previous: $e); } foreach (['iv', 'tag', 'value'] as $field) { if (!isset($decoded[$field])) { throw new Exception(sprintf('Missing "%s" field in encrypted payload', $field)); } } return $decoded; } }