⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thex.cs

📁 Tiger Tree Hash is constructed from two parts, the Tiger Hash Algorithm and Merkle Tree. The origina
💻 CS
字号:
/*
 * 
 * Tiger Tree Hash - by Gil Schmidt.
 * 
 *  - this code was writtin based on:
 *    "Tree Hash EXchange format (THEX)" 
 *    http://www.open-content.net/specs/draft-jchapweske-thex-02.html
 * 
 *  - the tiger hash class was converted from visual basic code called TigerNet:
 *    http://www.hotpixel.net/software.html
 * 
 *  - Base32 class was taken from:
 *    http://msdn.microsoft.com/msdnmag/issues/04/07/CustomPreferences/default.aspx
 *    didn't want to waste my time on writing a Base32 class.
 * 
 *  [ contact me at Gil_Smdt@hotmali.com ]
 * 
 */

using System;
using System.Text;
using System.IO;
using System.Collections;

namespace ThexCS
{
	public class Thex
	{
		const   int        Block_Size = 1024;
		private int        Leaf_Count;
		private ArrayList  LeafCollection;
		private FileStream FilePtr;

		private struct HashHolder
		{
			public byte[] HashValue;

			public HashHolder(byte[] HashValue)
			{
				this.HashValue = HashValue;
			}
		}

		public byte[] GetTTH(string Filename) 
		{
			HashHolder Result;

			try
			{
				FilePtr = new FileStream(Filename,FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
			
				//if there's only one block in file use SmallFile().
				if (FilePtr.Length <= Block_Size) return SmallFile();

				//get how many leafs are in file.
				Leaf_Count = (int) FilePtr.Length / Block_Size;
				if (FilePtr.Length % Block_Size > 0) Leaf_Count++;
			
				//load blocks of data and get tiger hash for each one.
				LoadLeafHash();
			
				//get root hash from blocks hash.
				Result = GetRootHash();

				return Result.HashValue;
			}
			catch (Exception e)
			{
				System.Diagnostics.Debug.WriteLine("error while trying to get TTH for file: " + 
					Filename + ". (" + e.Message + ")");
				return null;
			}
		}

		private byte[] SmallFile()
		{
			Tiger TG = new Tiger();
			byte[] Block = new byte[Block_Size];

			int BlockSize = FilePtr.Read(Block,0,1024);
			FilePtr.Close();

			//gets hash for a single block file.
			return LH(ByteExtract(Block,BlockSize));
		}

		private void LoadLeafHash()
		{
			LeafCollection = new ArrayList();

			for (int i = 0; i < (int) Leaf_Count / 2; i++)
			{
				byte[] BlockA = new byte[Block_Size],BlockB = new byte[Block_Size];
				
				FilePtr.Read(BlockA,0,1024);
				int DataSize = FilePtr.Read(BlockB,0,1024);

				//check if the block isn't big enough.
				if (DataSize < Block_Size)
					BlockB = ByteExtract(BlockB,DataSize);

				BlockA = LH(BlockA);
				BlockB = LH(BlockB);

				//add combined leaf hash.
				LeafCollection.Add(new HashHolder(IH(BlockA,BlockB)));
			}

			//leaf without a pair.
			if (Leaf_Count % 2 != 0)
			{
				byte[] Block = new byte[Block_Size];
				int DataSize = FilePtr.Read(Block,0,1024);

				if (DataSize < 1024)
					Block = ByteExtract(Block,DataSize);

				LeafCollection.Add(new HashHolder(LH(Block)));
			}

			FilePtr.Close();
		}

		private HashHolder GetRootHash()
		{
			ArrayList InternalCollection = new ArrayList();

			do
			{
				InternalCollection = new ArrayList(LeafCollection);
				LeafCollection.Clear();

				while (InternalCollection.Count > 1)
				{
					//load next two leafs.
					byte[] HashA = ((HashHolder) InternalCollection[0]).HashValue;
					byte[] HashB = ((HashHolder) InternalCollection[1]).HashValue;
					
					//add their combined hash.
					LeafCollection.Add(new HashHolder(IH(HashA,HashB)));

					//remove the used leafs.
					InternalCollection.RemoveAt(0);
					InternalCollection.RemoveAt(0);
				}

				//if this leaf can't combine add him at the end.
				if (InternalCollection.Count > 0)
					LeafCollection.Add(InternalCollection[0]);
			} while (LeafCollection.Count > 1);

			return (HashHolder) LeafCollection[0];
		}

		private byte[] IH(byte[] LeafA,byte[] LeafB) //internal hash.
		{ 
			byte[] Data = new byte[LeafA.Length + LeafB.Length + 1];

			Data[0] = 0x01; //internal hash mark.

			//combines two leafs.
			LeafA.CopyTo(Data,1);
			LeafB.CopyTo(Data,LeafA.Length + 1);

			//gets tiger hash value for combined leaf hash.
			Tiger TG = new Tiger();
			TG.Initialize();
			return TG.ComputeHash(Data);			
		}

		private byte[] LH(byte[] Raw_Data) //leaf hash.
		{ 
			byte[] Data = new byte[Raw_Data.Length + 1];

			Data[0] = 0x00; //leaf hash mark.
			Raw_Data.CopyTo(Data,1);

			//gets tiger hash value for leafs blocks.
			Tiger TG = new Tiger();
			TG.Initialize();
			return TG.ComputeHash(Data);
		}

		private byte[] ByteExtract(byte[] Raw_Data,int Data_Length) //copy 
		{
			//return Data_Length bytes from Raw_Data.
			byte[] Data = new byte[Data_Length];

			for (int i = 0; i < Data_Length; i++)
				Data[i] = Raw_Data[i];

			return Data;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -