public function encrypt(string $request, string $publicKey, int $version = 2, string $nonce = null) : string
    {
        $this->nonce = $nonce ?? \random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);

        if (\strlen($publicKey) !== SODIUM_CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new InvalidArgumentException(sprintf("Remote public key should be %d bytes.", SODIUM_CRYPTO_BOX_PUBLICKEYBYTES));
        }

        if ($version === 2) {
            $version = \pack('H*', 'DE259002');
            $body = $this->encryptBody($request, $publicKey, $this->nonce);
            if (!$body) {
                throw new EncryptionFailedException('An unexpected error occured when encrypting the message.');
            }

            $iPublicKey = \sodium_crypto_box_publickey_from_secretkey($this->secretKey);
            $sigPubKey = \sodium_crypto_sign_publickey_from_secretkey($this->signatureSecretKey);
            $payload = $version . $this->nonce . $iPublicKey . $body . $sigPubKey . $this->sign($request);
            $checksum = sodium_crypto_generichash($payload, $this->nonce, 64);

            return $payload . $checksum;
        }


        // Version 1 payload is just a single sodium crypto box
        return $this->encryptBody($request, $publicKey, $this->nonce);
    }