protected static function checksumData(
        StreamInterface $fileStream,
        Key $key = null,
        $encoding = Halite::ENCODE_BASE64URLSAFE
    ): string {
        $config = self::getConfig(
            Halite::HALITE_VERSION_FILE,
            'checksum'
        );

        // 1. Initialize the hash context
        if ($key instanceof AuthenticationKey) {
            // AuthenticationKey is for HMAC, but we can use it for keyed hashes too
            $state = \sodium_crypto_generichash_init(
                $key->getRawKeyMaterial(),
                (int) $config->HASH_LEN
            );
        } elseif($config->CHECKSUM_PUBKEY && ($key instanceof SignaturePublicKey)) {
            // In version 2, we use the public key as a hash key
            $state = \sodium_crypto_generichash_init(
                $key->getRawKeyMaterial(),
                (int) $config->HASH_LEN
            );
        // @codeCoverageIgnoreStart
        } elseif (isset($key)) {
        // @codeCoverageIgnoreEnd
            throw new InvalidKey(
                'Argument 2: Expected an instance of AuthenticationKey or SignaturePublicKey'
            );
        } else {
            $state = \sodium_crypto_generichash_init(
                '',
                (int) $config->HASH_LEN
            );
        }

        // 2. Calculate the hash
        $size = $fileStream->getSize();
        while ($fileStream->remainingBytes() > 0) {
            // Don't go past the file size even if $config->BUFFER is not an even multiple of it:
            if (($fileStream->getPos() + (int) $config->BUFFER) > $size) {
                /** @var int $amount_to_read */
                $amount_to_read = ($size - $fileStream->getPos());
            } else {
                // @codeCoverageIgnoreStart
                /** @var int $amount_to_read */
                $amount_to_read = (int) $config->BUFFER;
                // @codeCoverageIgnoreEnd
            }
            $read = $fileStream->readBytes($amount_to_read);
            \sodium_crypto_generichash_update($state, $read);
        }

        // 3. Do we want a raw checksum?
        $encoder = Halite::chooseEncoder($encoding);
        if ($encoder) {
            return (string) $encoder(
                \sodium_crypto_generichash_final(
                    // @codeCoverageIgnoreStart
                    $state,
                    // @codeCoverageIgnoreEnd
                    (int) $config->HASH_LEN
                )
            );
        }
        return (string) \sodium_crypto_generichash_final(
            // @codeCoverageIgnoreStart
            $state,
            // @codeCoverageIgnoreEnd
            (int) $config->HASH_LEN
        );
    }