-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathHash.cs
More file actions
73 lines (61 loc) · 2.54 KB
/
Hash.cs
File metadata and controls
73 lines (61 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace Extensions
{
public static class Hash
{
public static async Task<string> CreateHashFromFileAsync(string sourceFilePath)
{
var fi = new System.IO.FileInfo(sourceFilePath);
// If the file exceeds the limit of 1 GB, only create a partly hash
if (fi.Length >= 1024 * 1024 * 1024)
return await CreateHashFromFilePartlyAsync(sourceFilePath);
return await CreateFullHashFromFileAsync(sourceFilePath);
}
private static async Task<string> CreateFullHashFromFileAsync(string sourceFilePath)
{
using (SHA256 sha256Hash = SHA256.Create())
{
using (System.IO.FileStream fs = new System.IO.FileStream(sourceFilePath, System.IO.FileMode.Open))
{
var result = await sha256Hash.ComputeHashAsync(fs);
return result.ToHash();
}
}
}
private static async Task<string> CreateHashFromFilePartlyAsync(string sourceFilePath, int length = 50 * 1024 * 1024)
{
var bytes = await CreateHashBufferAsync(sourceFilePath, length);
using (SHA256 sha256Hash = SHA256.Create())
return sha256Hash.ComputeHash(bytes).ToHash();
}
private static string ToHash(this byte[] data)
{
return string.Join("", data.Select(p => p.ToString("x2")));
}
private static async Task<byte[]> CreateHashBufferAsync(string sourceFilePath, int length)
{
byte[] data;
var fi = new System.IO.FileInfo(sourceFilePath);
if (fi.Length < length * 3)
data = await System.IO.File.ReadAllBytesAsync(fi.FullName);
else
{
data = new byte[length * 3];
using (System.IO.FileStream fs = new System.IO.FileStream(sourceFilePath, System.IO.FileMode.Open))
{
// First n bytes
await fs.ReadAsync(data, 0, length);
// Middle + n bytes
fs.Seek(fs.Length / 2, System.IO.SeekOrigin.Begin);
await fs.ReadAsync(data, length, length);
// End - n bytes
fs.Seek(fs.Length - length, System.IO.SeekOrigin.Begin);
await fs.ReadAsync(data, length * 2, length);
}
}
return data;
}
}
}