public sealed class ContentHasher
{
public async Task<string> ComputeSha256Async(Stream stream, CancellationToken cancellationToken)
{
if (!stream.CanSeek)
{
throw new NotSupportedException("Stream must be seekable for content hashing.");
}
var originalPosition = stream.Position;
try
{
stream.Position = 0;
using var sha = SHA256.Create();
var hash = await sha.ComputeHashAsync(stream, cancellationToken).ConfigureAwait(false);
return Convert.ToHexString(hash);
}
finally
{
stream.Position = originalPosition;
}
}
}