protected static function checksumData(StreamInterface $fileStream, Key $key = null, bool $raw = false) : 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(), $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(), $config->HASH_LEN);
} elseif (isset($key)) {
throw new InvalidKey('Argument 2: Expected an instance of AuthenticationKey or SignaturePublicKey');
} else {
$state = \Sodium\crypto_generichash_init('', $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() + $config->BUFFER > $size) {
$amount_to_read = $size - $fileStream->getPos();
} else {
$amount_to_read = $config->BUFFER;
}
$read = $fileStream->readBytes($amount_to_read);
\Sodium\crypto_generichash_update($state, $read);
}
// 3. Do we want a raw checksum?
if ($raw) {
return \Sodium\crypto_generichash_final($state, $config->HASH_LEN);
}
return \Sodium\bin2hex(\Sodium\crypto_generichash_final($state, $config->HASH_LEN));
}