frostfs-sdk-csharp/src/FrostFS.SDK.Cryptography/DataHasher.cs
Pavel Gross 87fe8db674 [] Client: Memory optimization
Signed-off-by: Pavel Gross <p.gross@yadro.com>
2025-03-31 11:40:04 +03:00

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);
}
}