74 lines
2.3 KiB
C#
74 lines
2.3 KiB
C#
// dnlib: See LICENSE.txt for more info
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace dnlib.DotNet.Writer {
|
|
static class Hasher {
|
|
static HashAlgorithm CreateHasher(ChecksumAlgorithm checksumAlgorithm) =>
|
|
checksumAlgorithm switch {
|
|
ChecksumAlgorithm.SHA1 => SHA1.Create(),
|
|
ChecksumAlgorithm.SHA256 => SHA256.Create(),
|
|
ChecksumAlgorithm.SHA384 => SHA384.Create(),
|
|
ChecksumAlgorithm.SHA512 => SHA512.Create(),
|
|
_ => throw new ArgumentOutOfRangeException(nameof(checksumAlgorithm)),
|
|
};
|
|
|
|
public static string GetChecksumName(ChecksumAlgorithm checksumAlgorithm) =>
|
|
// https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md#pdb-checksum-debug-directory-entry-type-19
|
|
checksumAlgorithm switch {
|
|
ChecksumAlgorithm.SHA1 => "SHA1",
|
|
ChecksumAlgorithm.SHA256 => "SHA256",
|
|
ChecksumAlgorithm.SHA384 => "SHA384",
|
|
ChecksumAlgorithm.SHA512 => "SHA512",
|
|
_ => throw new ArgumentOutOfRangeException(nameof(checksumAlgorithm)),
|
|
};
|
|
|
|
public static bool TryGetChecksumAlgorithm(string checksumName, out ChecksumAlgorithm pdbChecksumAlgorithm, out int checksumSize) {
|
|
switch (checksumName) {
|
|
case "SHA1":
|
|
pdbChecksumAlgorithm = ChecksumAlgorithm.SHA1;
|
|
checksumSize = 20;
|
|
return true;
|
|
|
|
case "SHA256":
|
|
pdbChecksumAlgorithm = ChecksumAlgorithm.SHA256;
|
|
checksumSize = 32;
|
|
return true;
|
|
|
|
case "SHA384":
|
|
pdbChecksumAlgorithm = ChecksumAlgorithm.SHA384;
|
|
checksumSize = 48;
|
|
return true;
|
|
|
|
case "SHA512":
|
|
pdbChecksumAlgorithm = ChecksumAlgorithm.SHA512;
|
|
checksumSize = 64;
|
|
return true;
|
|
|
|
default:
|
|
pdbChecksumAlgorithm = 0;
|
|
checksumSize = -1;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static byte[] Hash(ChecksumAlgorithm checksumAlgorithm, Stream stream, long length) {
|
|
var buffer = new byte[(int)Math.Min(0x2000, length)];
|
|
using (var hasher = CreateHasher(checksumAlgorithm)) {
|
|
while (length > 0) {
|
|
int len = (int)Math.Min(length, buffer.Length);
|
|
int read = stream.Read(buffer, 0, len);
|
|
if (read == 0)
|
|
throw new InvalidOperationException("Couldn't read all bytes");
|
|
hasher.TransformBlock(buffer, 0, read, buffer, 0);
|
|
length -= read;
|
|
}
|
|
hasher.TransformFinalBlock(Array2.Empty<byte>(), 0, 0);
|
|
return hasher.Hash;
|
|
}
|
|
}
|
|
}
|
|
}
|