121 lines
2.9 KiB
C#
121 lines
2.9 KiB
C#
using System;
|
|
using System.Buffers;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace FrostFS.SDK.Cryptography;
|
|
|
|
public static class DataHasher
|
|
{
|
|
private const int LargeBlockSize = 1024 * 1024;
|
|
private const int SmallBlockSize = 256;
|
|
|
|
public static byte[] Hash(this ReadOnlyMemory<byte> bytes, HashAlgorithm algorithm)
|
|
{
|
|
if (algorithm is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(algorithm));
|
|
}
|
|
|
|
if (bytes.Length == 0)
|
|
{
|
|
return algorithm.ComputeHash([]);
|
|
}
|
|
|
|
int rest, pos = 0;
|
|
|
|
var blockSize = bytes.Length <= SmallBlockSize ? SmallBlockSize : LargeBlockSize;
|
|
|
|
byte[] buffer = ArrayPool<byte>.Shared.Rent(blockSize);
|
|
|
|
try
|
|
{
|
|
while ((rest = bytes.Length - pos) > 0)
|
|
{
|
|
var size = Math.Min(rest, blockSize);
|
|
|
|
bytes.Slice(pos, size).CopyTo(buffer);
|
|
|
|
algorithm.TransformBlock(buffer, 0, size, buffer, 0);
|
|
|
|
pos += size;
|
|
}
|
|
|
|
algorithm.TransformFinalBlock([], 0, 0);
|
|
return algorithm.Hash;
|
|
}
|
|
finally
|
|
{
|
|
if (buffer != null)
|
|
{
|
|
ArrayPool<byte>.Shared.Return(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static byte[] Hash(this ReadOnlySpan<byte> bytes, HashAlgorithm algorithm)
|
|
{
|
|
if (algorithm is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(algorithm));
|
|
}
|
|
|
|
if (bytes.Length == 0)
|
|
{
|
|
return algorithm.ComputeHash([]);
|
|
}
|
|
|
|
int rest, pos = 0;
|
|
|
|
var blockSize = bytes.Length <= SmallBlockSize ? SmallBlockSize : LargeBlockSize;
|
|
|
|
byte[] buffer = ArrayPool<byte>.Shared.Rent(blockSize);
|
|
|
|
try
|
|
{
|
|
while ((rest = bytes.Length - pos) > 0)
|
|
{
|
|
var size = Math.Min(rest, blockSize);
|
|
|
|
bytes.Slice(pos, size).CopyTo(buffer);
|
|
|
|
algorithm.TransformBlock(buffer, 0, size, buffer, 0);
|
|
|
|
pos += size;
|
|
}
|
|
|
|
algorithm.TransformFinalBlock([], 0, 0);
|
|
return algorithm.Hash;
|
|
}
|
|
finally
|
|
{
|
|
if (buffer != null)
|
|
{
|
|
ArrayPool<byte>.Shared.Return(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static byte[] Sha256(ReadOnlyMemory<byte> value)
|
|
{
|
|
using SHA256 sha = SHA256.Create();
|
|
return Hash(value, sha);
|
|
}
|
|
|
|
public static byte[] Sha256(ReadOnlySpan<byte> value)
|
|
{
|
|
using SHA256 sha = SHA256.Create();
|
|
return Hash(value, sha);
|
|
}
|
|
|
|
public static byte[] Sha512(ReadOnlyMemory<byte> value)
|
|
{
|
|
using SHA512 sha = SHA512.Create();
|
|
return Hash(value, sha);
|
|
}
|
|
|
|
public static byte[] Sha512(ReadOnlySpan<byte> value)
|
|
{
|
|
using SHA512 sha = SHA512.Create();
|
|
return Hash(value, sha);
|
|
}
|
|
}
|