/** * Calculate the BLAKE2b checksum of an entire stream * * @param StreamInterface $fileStream * @param Key $key * @param bool $raw * @return string * @throws CryptoException\InvalidKey */ protected static function checksumData(StreamInterface $fileStream, Key $key = null, bool $raw = false) : string { $config = self::getConfig(Halite::HALITE_VERSION_FILE, 'checksum'); if ($key instanceof AuthenticationKey) { $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 CryptoException\InvalidKey('Argument 2: Expected an instance of AuthenticationKey'); } else { $state = \Sodium\crypto_generichash_init('', $config->HASH_LEN); } $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); } // 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)); }
/** * Calculate the BLAKE2b checksum of the contents of a file * * @param StreamInterface $fileStream * @param Key $key * @param mixed $encoding Which encoding scheme to use for the checksum? * @return string * @throws InvalidKey */ 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(), $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? $encoder = Halite::chooseEncoder($encoding); if ($encoder) { return $encoder(\Sodium\crypto_generichash_final($state, $config->HASH_LEN)); } return \Sodium\crypto_generichash_final($state, $config->HASH_LEN); }