private function decryptBody(string $response, string $publicKey, string $nonce) : string
    {
        try {
            if (\strlen($publicKey) !== SODIUM_CRYPTO_BOX_PUBLICKEYBYTES) {
                throw new InvalidArgumentException(sprintf("Public key should be %d bytes.", SODIUM_CRYPTO_BOX_PUBLICKEYBYTES));
            }

            if (\strlen($nonce) !== SODIUM_CRYPTO_BOX_NONCEBYTES) {
                throw new InvalidArgumentException(sprintf("Nonce should be %d bytes.", SODIUM_CRYPTO_BOX_NONCEBYTES));
            }

            if (\strlen($response) < SODIUM_CRYPTO_BOX_MACBYTES) {
                throw new DecryptionFailedException("Minimum message length not met.");
            }

            $keypair = new Keypair(
                $this->secretKey,
                $publicKey
            );

            $result = \sodium_crypto_box_open(
                $response,
                $nonce,
                $keypair->getSodiumKeypair()
            );

            if ($result !== false) {
                return $result;
            }

            throw new DecryptionFailedException;
        } catch (SodiumException $e) {
            throw new InvalidArgumentException($e->getMessage());
        }
    }