2010-09-01 35 views
14

Giải pháp tốt nhất trong C# để tính toán md5 "đang hoạt động" như băm của một luồng có chiều dài không xác định là gì? Cụ thể, tôi muốn tính toán băm từ dữ liệu nhận được qua mạng. Tôi biết tôi đã hoàn thành việc nhận dữ liệu khi người gửi chấm dứt kết nối, vì vậy tôi không biết trước thời hạn.Tính toán băm từ một luồng có độ dài không xác định trong C#

[EDIT] - Ngay bây giờ tôi đang sử dụng md5, nhưng điều này yêu cầu một lần thứ hai vượt qua dữ liệu sau khi nó được lưu và ghi vào đĩa. Tôi muốn băm nó tại chỗ khi nó đến từ mạng.

Trả lời

43

MD5, giống như các hàm băm khác, không yêu cầu hai thẻ.

Để bắt đầu:

HashAlgorithm hasher = ..; 
hasher.Initialize(); 

Khi mỗi khối dữ liệu đến:

byte[] buffer = ..; 
int bytesReceived = ..; 
hasher.TransformBlock(buffer, 0, bytesReceived, null, 0); 

Để hoàn tất và lấy các hash:

hasher.TransformFinalBlock(new byte[0], 0, 0); 
byte[] hash = hasher.Hash; 

mô hình này hoạt động cho bất kỳ loại có nguồn gốc từ HashAlgorithm, bao gồm MD5CryptoServiceProviderSHA1Managed.

HashAlgorithm cũng xác định phương thức ComputeHash có đối tượng Stream; tuy nhiên, phương pháp này sẽ chặn luồng cho đến khi luồng được sử dụng. Sử dụng cách tiếp cận TransformBlock cho phép "băm không đồng bộ" được tính như dữ liệu đến mà không cần sử dụng hết chuỗi.

+0

Tôi đã nhìn thấy các phương pháp đó nhưng chưa bao giờ điều tra những gì họ đã làm. Xấu hổ với tôi. Điều này có vẻ như nó sẽ hoạt động. – jjxtra

7

Tiếp tục để @ peter-mourfield 's câu trả lời, đây là mã có sử dụng ComputeHash():

private static string CalculateMd5(string filePathName) { 
    using (var stream = File.OpenRead(filePathName)) 
    using (var md5 = MD5.Create()) { 
    var hash = md5.ComputeHash(stream); 
    var base64String = Convert.ToBase64String(hash); 
    return base64String; 
    } 
} 

Kể từ khi cả hai dòng cũng như MD5 thực hiện IDisposible, bạn cần phải sử dụng using(...){...}

Các phương pháp trong ví dụ mã trả về cùng một chuỗi được sử dụng cho kiểm tra MD5 trong Azure Blob lưu trữ.

1

Necromancing.

Hai possibilitites trong C# .NET Core:

private static System.Security.Cryptography.HashAlgorithm GetHashAlgorithm(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName) 
{ 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.MD5) 
     return (System.Security.Cryptography.HashAlgorithm) System.Security.Cryptography.MD5.Create(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA1) 
     return (System.Security.Cryptography.HashAlgorithm) System.Security.Cryptography.SHA1.Create(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA256) 
     return (System.Security.Cryptography.HashAlgorithm) System.Security.Cryptography.SHA256.Create(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA384) 
     return (System.Security.Cryptography.HashAlgorithm) System.Security.Cryptography.SHA384.Create(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA512) 
     return (System.Security.Cryptography.HashAlgorithm) System.Security.Cryptography.SHA512.Create(); 

    throw new System.Security.Cryptography.CryptographicException($"Unknown hash algorithm \"{hashAlgorithmName.Name}\"."); 
} 


protected override byte[] HashData(System.IO.Stream data, 
    System.Security.Cryptography.HashAlgorithmName hashAlgorithm) 
{ 
    using (System.Security.Cryptography.HashAlgorithm hashAlgorithm1 = 
    GetHashAlgorithm(hashAlgorithm)) 
    return hashAlgorithm1.ComputeHash(data); 
} 

hoặc với BouncyCastle:

private static Org.BouncyCastle.Crypto.IDigest GetBouncyAlgorithm(
    System.Security.Cryptography.HashAlgorithmName hashAlgorithmName) 
{ 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.MD5) 
     return new Org.BouncyCastle.Crypto.Digests.MD5Digest(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA1) 
     return new Org.BouncyCastle.Crypto.Digests.Sha1Digest(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA256) 
     return new Org.BouncyCastle.Crypto.Digests.Sha256Digest(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA384) 
     return new Org.BouncyCastle.Crypto.Digests.Sha384Digest(); 
    if (hashAlgorithmName == System.Security.Cryptography.HashAlgorithmName.SHA512) 
     return new Org.BouncyCastle.Crypto.Digests.Sha512Digest(); 

    throw new System.Security.Cryptography.CryptographicException(
     $"Unknown hash algorithm \"{hashAlgorithmName.Name}\"." 
    ); 
} // End Function GetBouncyAlgorithm 



protected override byte[] HashData(System.IO.Stream data, 
    System.Security.Cryptography.HashAlgorithmName hashAlgorithm) 
{ 
    Org.BouncyCastle.Crypto.IDigest digest = GetBouncyAlgorithm(hashAlgorithm); 

    byte[] buffer = new byte[4096]; 
    int cbSize; 
    while ((cbSize = data.Read(buffer, 0, buffer.Length)) > 0) 
     digest.BlockUpdate(buffer, 0, cbSize); 

    byte[] hash = new byte[digest.GetDigestSize()]; 
    digest.DoFinal(hash, 0); 
    return hash; 
} 
Các vấn đề liên quan