public static function getNonce(string $action, Session $session, array $context = [], int $timestamp = null)
    {
        // When nonce are not allowed to be stored, the nonce is not actually 
        // used only once since it needs to be reproducable to be verifiable.
        // Therefore, it sent timestamped to the client.
        $timestamp = $timestamp ?? time();
        $hashable = $action . $timestamp . $session->getSessionSalt();
        foreach ($context as $key => $value)
        {
            if ($value === null)
                $value = "NULL";
            if (!is_scalar($value))
                throw new InvalidArgumentException("Context variables must be scalar");
            $hashable .= '&' . $key . '=' . $value;
        }

        $nonce = sha1($hashable) . '$' . $timestamp;
        return $nonce;
    }