Bir dosyanın Hash(Checksum) değerini hesaplamak için önemli olan bazı konulardan bahsetmem gerekmektedir. Hash değeri hesaplanırken, hash sonucu bir byte dizisine yazılır. Sonucun daha sonrasında byte dizisi olarak hafızada tutmamak gerekir. Fazladan RAM tüketimi olmaması için mutlaka işiniz bittikten sonra sonucu NULL olarak temizlemeniz gerekir.
Bir dosyanın hash değerini hesaplamamız için o dosyanın tüm byte’larına ihtiyacımız vardır. Bu byte değerleri normalde hafızaya almanız gerekmektedir. Fakat dosyanın boyutu 2GB veya üstü büyüklükte olursa “OutOfMemoryException” hatası alırsınız. Çünkü dosyanın tüm verisi RAM üzerine yazılmış oluyor. Bu yüzden bizim dosyanın hash değerini hesaplamamız için “FileStream” kullanmamız gerekmektedir. Böylece tüm iş yükünü işlemciye ve diske yansıtmış oluyoruz.
Aşağıdaki classı alıp namespace adını değiştirip kullanabilirsiniz.
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace KorayUstundag
{
public class FileHash : IDisposable
{
public enum Method
{
MD5,SHA1,SHA256,SHA384,SHA512
}
private string _FilePath { get; set; }
byte[] result;
private readonly MD5 md;
private readonly SHA1 sha1;
private readonly SHA256 sha256;
private readonly SHA384 sha384;
private readonly SHA512 sha512;
private readonly FileStream srcStream;
private Method mtd;
private StringBuilder sb;
private bool disposedValue;
public FileHash(string filePath)
{
_FilePath = filePath;
mtd = Method.SHA256;
sb = new StringBuilder();
srcStream = new FileStream(_FilePath, FileMode.Open, FileAccess.Read);
}
public FileHash(string filePath, Method method)
{
_FilePath = filePath;
mtd = method;
sb = new StringBuilder();
srcStream = new FileStream(_FilePath, FileMode.Open, FileAccess.Read);
if (method == Method.MD5)
{
md = MD5.Create();
}
else if (method == Method.SHA1)
{
sha1 = SHA1.Create();
}
else if (method == Method.SHA256)
{
sha256 = SHA256.Create();
}
else if (method == Method.SHA384)
{
sha384 = SHA384.Create();
}
else if (method == Method.SHA512)
{
sha512 = SHA512.Create();
}
else
{
sha256 = SHA256.Create();
}
}
public string Calculate()
{
if (mtd == Method.MD5)
{
sb.Clear();
result = md.ComputeHash(srcStream);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
return sb.ToString();
}
else if (mtd == Method.SHA1)
{
sb.Clear();
result = sha1.ComputeHash(srcStream);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
return sb.ToString();
}
else if (mtd == Method.SHA256)
{
sb.Clear();
result = sha256.ComputeHash(srcStream);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
return sb.ToString();
}
else if (mtd == Method.SHA384)
{
sb.Clear();
result = sha384.ComputeHash(srcStream);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
return sb.ToString();
}
else if (mtd == Method.SHA512)
{
sb.Clear();
result = sha512.ComputeHash(srcStream);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x2"));
}
return sb.ToString();
}
else
{
throw new ArgumentNullException(nameof(Method));
}
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
if (md != null)
{
md.Clear();
md.Dispose();
}
if (sha1 != null)
{
sha1.Clear();
sha1.Dispose();
}
if (sha256 != null)
{
sha256.Clear();
sha256.Dispose();
}
if (sha384 != null)
{
sha384.Clear();
sha384.Dispose();
}
if (sha512 != null)
{
sha512.Clear();
sha512.Dispose();
}
if (srcStream != null)
{
srcStream.Close();
srcStream.Dispose();
}
if (sb != null)
{
sb.Clear();
}
}
result = null;
disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}