Statistics
| Branch: | Revision:

root / trunk / Pithos.Network / Signature.cs @ c875d683

History | View | Annotate | Download (12.6 kB)

1 255f5f86 Panagiotis Kanavos
#region
2 255f5f86 Panagiotis Kanavos
/* -----------------------------------------------------------------------
3 255f5f86 Panagiotis Kanavos
 * <copyright file="Signature.cs" company="GRNet">
4 255f5f86 Panagiotis Kanavos
 * 
5 255f5f86 Panagiotis Kanavos
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6 255f5f86 Panagiotis Kanavos
 *
7 255f5f86 Panagiotis Kanavos
 * Redistribution and use in source and binary forms, with or
8 255f5f86 Panagiotis Kanavos
 * without modification, are permitted provided that the following
9 255f5f86 Panagiotis Kanavos
 * conditions are met:
10 255f5f86 Panagiotis Kanavos
 *
11 255f5f86 Panagiotis Kanavos
 *   1. Redistributions of source code must retain the above
12 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
13 255f5f86 Panagiotis Kanavos
 *      disclaimer.
14 255f5f86 Panagiotis Kanavos
 *
15 255f5f86 Panagiotis Kanavos
 *   2. Redistributions in binary form must reproduce the above
16 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
17 255f5f86 Panagiotis Kanavos
 *      disclaimer in the documentation and/or other materials
18 255f5f86 Panagiotis Kanavos
 *      provided with the distribution.
19 255f5f86 Panagiotis Kanavos
 *
20 255f5f86 Panagiotis Kanavos
 *
21 255f5f86 Panagiotis Kanavos
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22 255f5f86 Panagiotis Kanavos
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 255f5f86 Panagiotis Kanavos
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 255f5f86 Panagiotis Kanavos
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25 255f5f86 Panagiotis Kanavos
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 255f5f86 Panagiotis Kanavos
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 255f5f86 Panagiotis Kanavos
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 255f5f86 Panagiotis Kanavos
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 255f5f86 Panagiotis Kanavos
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 255f5f86 Panagiotis Kanavos
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 255f5f86 Panagiotis Kanavos
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 255f5f86 Panagiotis Kanavos
 * POSSIBILITY OF SUCH DAMAGE.
33 255f5f86 Panagiotis Kanavos
 *
34 255f5f86 Panagiotis Kanavos
 * The views and conclusions contained in the software and
35 255f5f86 Panagiotis Kanavos
 * documentation are those of the authors and should not be
36 255f5f86 Panagiotis Kanavos
 * interpreted as representing official policies, either expressed
37 255f5f86 Panagiotis Kanavos
 * or implied, of GRNET S.A.
38 255f5f86 Panagiotis Kanavos
 * </copyright>
39 255f5f86 Panagiotis Kanavos
 * -----------------------------------------------------------------------
40 255f5f86 Panagiotis Kanavos
 */
41 255f5f86 Panagiotis Kanavos
#endregion
42 0c02aa65 Panagiotis Kanavos
using System;
43 0c02aa65 Panagiotis Kanavos
using System.Collections.Concurrent;
44 0c02aa65 Panagiotis Kanavos
using System.Collections.Generic;
45 9c4346c9 Panagiotis Kanavos
using System.Diagnostics.Contracts;
46 0eea575a Panagiotis Kanavos
using System.IO;
47 6bcdd8e2 Panagiotis Kanavos
using System.Reflection;
48 9c4346c9 Panagiotis Kanavos
using System.Runtime.Remoting.Metadata.W3cXsd2001;
49 0eea575a Panagiotis Kanavos
using System.Security.Cryptography;
50 c875d683 pkanavos
using System.Threading;
51 0c02aa65 Panagiotis Kanavos
using System.Threading.Tasks;
52 0c02aa65 Panagiotis Kanavos
using System.Linq;
53 0eea575a Panagiotis Kanavos
54 1caef52e Panagiotis Kanavos
namespace Pithos.Network
55 0eea575a Panagiotis Kanavos
{
56 9c4346c9 Panagiotis Kanavos
    public static class Signature
57 0eea575a Panagiotis Kanavos
    {
58 6bcdd8e2 Panagiotis Kanavos
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 f5f9b225 pkanavos
        public const  int BufferSize = 16384;
60 6bcdd8e2 Panagiotis Kanavos
61 a60e5887 pkanavos
        public const string MD5_EMPTY = "d41d8cd98f00b204e9800998ecf8427e";
62 cd942434 pkanavos
        public const string MERKLE_EMPTY = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
63 a60e5887 pkanavos
64 a60e5887 pkanavos
65 a60e5887 pkanavos
        public static string CalculateMD5(FileSystemInfo info)
66 a27aa447 Panagiotis Kanavos
        {
67 a27aa447 Panagiotis Kanavos
            if (info==null)
68 a27aa447 Panagiotis Kanavos
                throw new ArgumentNullException("info");
69 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(info.FullName))
70 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("info.FullName is empty","info");
71 a27aa447 Panagiotis Kanavos
            Contract.EndContractBlock();
72 a27aa447 Panagiotis Kanavos
73 a60e5887 pkanavos
            if (info is DirectoryInfo)
74 a60e5887 pkanavos
                return MD5_EMPTY;
75 a60e5887 pkanavos
76 a27aa447 Panagiotis Kanavos
            return CalculateMD5(info.FullName);
77 a27aa447 Panagiotis Kanavos
        }
78 a27aa447 Panagiotis Kanavos
79 9c4346c9 Panagiotis Kanavos
        public static string CalculateMD5(string path)
80 0eea575a Panagiotis Kanavos
        {
81 9c4346c9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
82 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("path");
83 9c4346c9 Panagiotis Kanavos
            Contract.EndContractBlock();
84 0c02aa65 Panagiotis Kanavos
85 1caef52e Panagiotis Kanavos
            //DON'T calculate hashes for folders
86 1caef52e Panagiotis Kanavos
            if (Directory.Exists(path))
87 1caef52e Panagiotis Kanavos
                return "";
88 1caef52e Panagiotis Kanavos
89 9c4346c9 Panagiotis Kanavos
            string hash;
90 9c4346c9 Panagiotis Kanavos
            using (var hasher = MD5.Create())
91 f5f9b225 pkanavos
            using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, Signature.BufferSize, true))
92 0c02aa65 Panagiotis Kanavos
            {
93 9c4346c9 Panagiotis Kanavos
                var hashBytes = hasher.ComputeHash(stream);
94 9c4346c9 Panagiotis Kanavos
                hash = hashBytes.ToHashString();
95 9c4346c9 Panagiotis Kanavos
            }
96 9c4346c9 Panagiotis Kanavos
            return hash;
97 9c4346c9 Panagiotis Kanavos
        }
98 9c4346c9 Panagiotis Kanavos
99 9c4346c9 Panagiotis Kanavos
/*
100 9c4346c9 Panagiotis Kanavos
        public static string BytesToString(byte[] hashBytes)
101 9c4346c9 Panagiotis Kanavos
        {
102 9c4346c9 Panagiotis Kanavos
            var shb=new SoapHexBinary(hashBytes);
103 9c4346c9 Panagiotis Kanavos
            return shb.ToString();
104 0c02aa65 Panagiotis Kanavos
            
105 9c4346c9 Panagiotis Kanavos
        }
106 0c02aa65 Panagiotis Kanavos
107 0c02aa65 Panagiotis Kanavos
108 9c4346c9 Panagiotis Kanavos
        public static byte[] StringToBytes(string hash)
109 0c02aa65 Panagiotis Kanavos
        {
110 9c4346c9 Panagiotis Kanavos
            var shb=SoapHexBinary.Parse(hash);
111 9c4346c9 Panagiotis Kanavos
            return shb.Value;
112 0c02aa65 Panagiotis Kanavos
        }
113 9c4346c9 Panagiotis Kanavos
*/
114 0c02aa65 Panagiotis Kanavos
115 9c4346c9 Panagiotis Kanavos
        public static byte[] ToBytes(this string hash)
116 9c4346c9 Panagiotis Kanavos
        {
117 9c4346c9 Panagiotis Kanavos
            var shb = SoapHexBinary.Parse(hash);
118 9c4346c9 Panagiotis Kanavos
            return shb.Value;
119 9c4346c9 Panagiotis Kanavos
        }
120 9c4346c9 Panagiotis Kanavos
121 9c4346c9 Panagiotis Kanavos
        public static string ToHashString(this byte[] hashBytes)
122 0c02aa65 Panagiotis Kanavos
        {
123 9c4346c9 Panagiotis Kanavos
            var shb = new SoapHexBinary(hashBytes);
124 bfc13ed8 Panagiotis Kanavos
            return shb.ToString().ToLower();
125 9c4346c9 Panagiotis Kanavos
        }
126 9c4346c9 Panagiotis Kanavos
127 c875d683 pkanavos
        public static TreeHash CalculateTreeHash(FileSystemInfo fileInfo, int blockSize, string algorithm,CancellationToken token,IProgress<double> progress )
128 a27aa447 Panagiotis Kanavos
        {
129 174bbb6e Panagiotis Kanavos
            if (fileInfo == null)
130 a27aa447 Panagiotis Kanavos
                throw new ArgumentNullException("fileInfo");
131 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(fileInfo.FullName))
132 174bbb6e Panagiotis Kanavos
                throw new ArgumentException("fileInfo.FullName is empty", "fileInfo");
133 a27aa447 Panagiotis Kanavos
            if (blockSize <= 0)
134 a27aa447 Panagiotis Kanavos
                throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero ");
135 a27aa447 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(algorithm))
136 a27aa447 Panagiotis Kanavos
                throw new ArgumentNullException("algorithm");
137 a27aa447 Panagiotis Kanavos
            Contract.EndContractBlock();
138 c945b450 pkanavos
            fileInfo.Refresh();
139 174bbb6e Panagiotis Kanavos
            if (fileInfo is DirectoryInfo || !fileInfo.Exists)
140 174bbb6e Panagiotis Kanavos
                return TreeHash.Empty;
141 174bbb6e Panagiotis Kanavos
142 c875d683 pkanavos
            return CalculateTreeHash(fileInfo.FullName, blockSize, algorithm,token,progress);
143 a27aa447 Panagiotis Kanavos
        }
144 0c02aa65 Panagiotis Kanavos
145 9c4346c9 Panagiotis Kanavos
        /// <summary>
146 9c4346c9 Panagiotis Kanavos
        /// Calculates a file's tree hash synchronously, using the specified block size
147 9c4346c9 Panagiotis Kanavos
        /// </summary>
148 9c4346c9 Panagiotis Kanavos
        /// <param name="filePath">Path to an existing file</param>
149 9c4346c9 Panagiotis Kanavos
        /// <param name="blockSize">Block size used to calculate leaf hashes</param>
150 9c4346c9 Panagiotis Kanavos
        /// <param name="algorithm"></param>
151 9c4346c9 Panagiotis Kanavos
        /// <returns>A <see cref="TreeHash"/> with the block hashes and top hash</returns>
152 c875d683 pkanavos
        public static TreeHash CalculateTreeHash(string filePath, int blockSize, string algorithm,CancellationToken token,IProgress<double> progress )
153 9c4346c9 Panagiotis Kanavos
        {
154 9c4346c9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(filePath))
155 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("filePath");
156 9c4346c9 Panagiotis Kanavos
            if (blockSize<=0)
157 9c4346c9 Panagiotis Kanavos
                throw new ArgumentOutOfRangeException("blockSize","blockSize must be a value greater than zero ");
158 9c4346c9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(algorithm))
159 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("algorithm");
160 4b58c004 pkanavos
            Contract.EndContractBlock();           
161 c875d683 pkanavos
            var hash=CalculateTreeHashAsync(filePath, blockSize, algorithm, 1,token,progress);
162 4b58c004 pkanavos
            return hash;
163 0c02aa65 Panagiotis Kanavos
        }
164 a27aa447 Panagiotis Kanavos
        
165 c875d683 pkanavos
        public static TreeHash CalculateTreeHashAsync(FileInfo fileInfo, int blockSize, string algorithm, byte parallelism,CancellationToken token,IProgress<double> progress )
166 a27aa447 Panagiotis Kanavos
        {
167 a27aa447 Panagiotis Kanavos
            if (fileInfo == null)
168 a27aa447 Panagiotis Kanavos
                throw new ArgumentNullException("fileInfo");
169 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(fileInfo.FullName))
170 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("fileInfo.FullName is empty","fileInfo");
171 a27aa447 Panagiotis Kanavos
            if (blockSize <= 0)
172 a27aa447 Panagiotis Kanavos
                throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero ");
173 a27aa447 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(algorithm))
174 a27aa447 Panagiotis Kanavos
                throw new ArgumentNullException("algorithm");
175 a27aa447 Panagiotis Kanavos
            Contract.EndContractBlock();
176 422c9598 Panagiotis Kanavos
            
177 c875d683 pkanavos
            return CalculateTreeHashAsync(fileInfo.FullName, blockSize, algorithm, parallelism,token,progress);
178 a27aa447 Panagiotis Kanavos
        }
179 0c02aa65 Panagiotis Kanavos
180 9c4346c9 Panagiotis Kanavos
181 c875d683 pkanavos
        public static TreeHash CalculateTreeHashAsync(string filePath, int blockSize,string algorithm, int parallelism,CancellationToken token,IProgress<double> progress )
182 9c4346c9 Panagiotis Kanavos
        {
183 1caef52e Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(filePath))
184 1caef52e Panagiotis Kanavos
                throw new ArgumentNullException("filePath");
185 9c4346c9 Panagiotis Kanavos
            if (blockSize <= 0)
186 9c4346c9 Panagiotis Kanavos
                throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero ");
187 9c4346c9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(algorithm))
188 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("algorithm");
189 9c4346c9 Panagiotis Kanavos
            Contract.EndContractBlock();
190 9c4346c9 Panagiotis Kanavos
191 174bbb6e Panagiotis Kanavos
            if (Log.IsDebugEnabled)
192 174bbb6e Panagiotis Kanavos
                Log.DebugFormat("Calc Signature [{0}]",filePath);
193 174bbb6e Panagiotis Kanavos
194 e1fa1d21 pkanavos
            if (filePath.Split('/').Contains(".pithos.cache"))
195 e1fa1d21 pkanavos
                throw new ArgumentException(String.Format("Trying to hash file from the cache folder: [{0}]",filePath));
196 e1fa1d21 pkanavos
197 1caef52e Panagiotis Kanavos
            //DON'T calculate hashes for folders
198 1caef52e Panagiotis Kanavos
            if (Directory.Exists(filePath))
199 437abfca Panagiotis Kanavos
                return new TreeHash(algorithm);
200 a64c87c8 Panagiotis Kanavos
            //The hash of a non-existent file is the empty hash
201 a64c87c8 Panagiotis Kanavos
            if (!File.Exists(filePath))
202 437abfca Panagiotis Kanavos
                return new TreeHash(algorithm);
203 1caef52e Panagiotis Kanavos
204 a27aa447 Panagiotis Kanavos
            //Calculate the hash of all blocks using a blockhash iterator
205 f5f9b225 pkanavos
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, BufferSize, true))
206 a27aa447 Panagiotis Kanavos
            {
207 db63c1ae pkanavos
                var md5 = new MD5BlockCalculator();
208 db63c1ae pkanavos
                Action<long, byte[], int> postAction = md5.PostBlock;
209 a27aa447 Panagiotis Kanavos
                //Calculate the blocks asyncrhonously
210 c875d683 pkanavos
                var hashes = BlockHashAlgorithms.CalculateBlockHashesInPlacePFor(stream, blockSize, algorithm, parallelism,postAction,token, progress).Result;                
211 437abfca Panagiotis Kanavos
212 a27aa447 Panagiotis Kanavos
                //And then proceed with creating and returning a TreeHash
213 437abfca Panagiotis Kanavos
                var length = stream.Length;
214 437abfca Panagiotis Kanavos
                var list = hashes.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToList();
215 a27aa447 Panagiotis Kanavos
216 a27aa447 Panagiotis Kanavos
                var treeHash = new TreeHash(algorithm)
217 a27aa447 Panagiotis Kanavos
                {
218 437abfca Panagiotis Kanavos
                    Bytes = length,
219 437abfca Panagiotis Kanavos
                    BlockSize = blockSize,
220 43dd02a8 pkanavos
                    Hashes = list,
221 a27aa447 Panagiotis Kanavos
                };
222 a27aa447 Panagiotis Kanavos
223 43dd02a8 pkanavos
                string fileHash;
224 db63c1ae pkanavos
225 db63c1ae pkanavos
                var md5Hash=md5.GetHash().Result;
226 db63c1ae pkanavos
/*
227 43dd02a8 pkanavos
                var hasher = HashAlgorithm.Create("MD5");
228 43dd02a8 pkanavos
                stream.Position = 0;
229 db63c1ae pkanavos
*/
230 db63c1ae pkanavos
                treeHash.MD5= md5Hash;
231 43dd02a8 pkanavos
232 437abfca Panagiotis Kanavos
                return treeHash;
233 a27aa447 Panagiotis Kanavos
            }
234 a27aa447 Panagiotis Kanavos
        }
235 9c4346c9 Panagiotis Kanavos
236 437abfca Panagiotis Kanavos
        
237 6e25cc48 Panagiotis Kanavos
        public static byte[] CalculateTopHash(IList<byte[]> hashMap, string algorithm)
238 1caef52e Panagiotis Kanavos
        {
239 1caef52e Panagiotis Kanavos
            if (hashMap == null)
240 1caef52e Panagiotis Kanavos
                throw new ArgumentNullException("hashMap");
241 1caef52e Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(algorithm))
242 1caef52e Panagiotis Kanavos
                throw new ArgumentNullException("algorithm");
243 6e25cc48 Panagiotis Kanavos
            Contract.EndContractBlock();            
244 1caef52e Panagiotis Kanavos
245 6e25cc48 Panagiotis Kanavos
            var hashCount = hashMap.Count;
246 6e25cc48 Panagiotis Kanavos
            //The tophash of an empty hashmap is an empty array
247 1caef52e Panagiotis Kanavos
            if (hashCount == 0)
248 6e25cc48 Panagiotis Kanavos
                return new byte[0];
249 6e25cc48 Panagiotis Kanavos
            //The tophash of a one-item hashmap is the hash itself
250 1caef52e Panagiotis Kanavos
            if (hashCount == 1)
251 6e25cc48 Panagiotis Kanavos
                return hashMap[0];
252 1caef52e Panagiotis Kanavos
253 6e25cc48 Panagiotis Kanavos
            //Calculate the required number of leaf nodes
254 5ce54458 Panagiotis Kanavos
            var leafs =(int)Math.Pow(2, Math.Ceiling(Math.Log(hashCount,2)));
255 6e25cc48 Panagiotis Kanavos
            //The size of all nodes is the same and equal to the size of the input hashes
256 6e25cc48 Panagiotis Kanavos
            var hashSize = hashMap[0].Length;
257 6e25cc48 Panagiotis Kanavos
258 6e25cc48 Panagiotis Kanavos
            //If the hashmap containes fewer nodes than the required leaf count, we need to fill
259 6e25cc48 Panagiotis Kanavos
            //the rest with empty blocks
260 6e25cc48 Panagiotis Kanavos
            byte[] empty=null;            
261 6e25cc48 Panagiotis Kanavos
            if (hashCount < leafs)
262 6e25cc48 Panagiotis Kanavos
                empty = new byte[hashSize];
263 6e25cc48 Panagiotis Kanavos
264 6e25cc48 Panagiotis Kanavos
            //New hashes will be stored in a dictionary keyed by their step to preserve order
265 6e25cc48 Panagiotis Kanavos
            var newHashes=new ConcurrentDictionary<int, byte[]>();            
266 6e25cc48 Panagiotis Kanavos
            
267 6e25cc48 Panagiotis Kanavos
            Parallel.For(0, leafs/2,
268 6e25cc48 Panagiotis Kanavos
                (step, state) =>
269 1caef52e Panagiotis Kanavos
                {
270 6e25cc48 Panagiotis Kanavos
                    using (var hasher = HashAlgorithm.Create(algorithm))
271 6e25cc48 Panagiotis Kanavos
                    {
272 6e25cc48 Panagiotis Kanavos
                        var i = step*2;
273 6e25cc48 Panagiotis Kanavos
                        var block1 = i <= hashCount - 1 ? hashMap[i] : empty;
274 6e25cc48 Panagiotis Kanavos
                        var block2 = i <= hashCount - 2 ? hashMap[i + 1] : empty;
275 6e25cc48 Panagiotis Kanavos
276 6e25cc48 Panagiotis Kanavos
                        hasher.TransformBlock(block1, 0, block1.Length, null, 0);
277 6e25cc48 Panagiotis Kanavos
                        hasher.TransformFinalBlock(block2, 0, block2.Length);
278 6e25cc48 Panagiotis Kanavos
279 6e25cc48 Panagiotis Kanavos
                        var finalHash = hasher.Hash;
280 6e25cc48 Panagiotis Kanavos
                        //Store the final value in its proper place
281 6e25cc48 Panagiotis Kanavos
                        newHashes[step] = finalHash;
282 6e25cc48 Panagiotis Kanavos
                    }
283 6e25cc48 Panagiotis Kanavos
                });
284 34bdb91d Panagiotis Kanavos
285 6e25cc48 Panagiotis Kanavos
            //Extract the hashes to a list ordered by their step 
286 6e25cc48 Panagiotis Kanavos
            var hashes = newHashes.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToList();
287 6e25cc48 Panagiotis Kanavos
            return CalculateTopHash(hashes, algorithm);                   
288 34bdb91d Panagiotis Kanavos
        }        
289 9c4346c9 Panagiotis Kanavos
    
290 9c4346c9 Panagiotis Kanavos
291 9c4346c9 Panagiotis Kanavos
        public static byte[] CalculateHash(byte[] buffer,string algorithm)
292 9c4346c9 Panagiotis Kanavos
        {
293 9c4346c9 Panagiotis Kanavos
            if (buffer == null)
294 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("buffer");
295 9c4346c9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(algorithm))
296 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("algorithm");
297 9c4346c9 Panagiotis Kanavos
            Contract.EndContractBlock();
298 9c4346c9 Panagiotis Kanavos
299 9c4346c9 Panagiotis Kanavos
            using (var hasher = HashAlgorithm.Create(algorithm))
300 9c4346c9 Panagiotis Kanavos
            {
301 9c4346c9 Panagiotis Kanavos
                var hash = hasher.ComputeHash(buffer, 0, buffer.Length);
302 9c4346c9 Panagiotis Kanavos
                return hash;
303 9c4346c9 Panagiotis Kanavos
            }        
304 0c02aa65 Panagiotis Kanavos
        }
305 0c02aa65 Panagiotis Kanavos
    }
306 9c4346c9 Panagiotis Kanavos
}
307 9c4346c9 Panagiotis Kanavos
308 0c02aa65 Panagiotis Kanavos
309 9c4346c9 Panagiotis Kanavos