Developers.Hash.Tiger: Difference between revisions
(Importing page from Tikiwiki) |
m (1 revision) |
(No difference)
|
Revision as of 20:06, 20 June 2009
Hashing Tiger and Donkey
I found some more code in Shareaza 2.0 that hashes data. Developers.Hash.Library
This is the clue to writing a sample that calculates hashes using Shareaza 2.0's tiger and donkey hashing objects. With those hashes computed, I can try to write code for camper's hashing system to get the same results.
I've started with CLibraryBuilder::HashFile from the Shareaza 2.0 code. Pulled out, the hashing calls look like this:
<source lang="c"> // Takes a pointer to some memory and the number of bytes of data there // Hashes the data using MD4, MD5, SHA1, TigerTree, and eDonkey2000 void HashData(byte* p, DWORD bytes) {
// Make objects that will compute the hashes CMD4 md4; CMD5 md5; CSHA sha1; CTigerTree tiger; CED2K donkey;
// For tiger and donkey, you have to call BeginFile first tiger.BeginFile(9, bytes); // Tell it the tiger height is 9, and the file size donkey.BeginFile(bytes); // Tell it the file size
// Give the objects the data we want hashed md4.Add(p, bytes); md5.Add(p, bytes); sha1.Add(p, bytes); tiger.AddToFile(p, bytes); // AddToFile, instead of Add donkey.AddToFile(p, bytes);
// Tell the objects that's all the data we have md4.Finish(); md5.Finish(); sha1.Finish(); tiger.FinishFile(); // FinishFile, instead of Finish donkey.FinishFile();
// Make local variables to hold the hash values MD4 md4value; MD5 md5value; SHA1 sha1value; TIGEROOT tigervalue; MD4 donkeyvalue;
// You can call sizeof on these DWORD size; size = sizeof(md4value); // CMD4 uses a 16 byte MD4 to hold its value size = sizeof(md5value); // CMD5 uses a 16 byte MD5 to hold its value size = sizeof(sha1value); // CSHA uses a 20 byte SHA1 to hold its value size = sizeof(tigervalue); // CTigerTree uses a 24 byte TIGEROOT to hold its value size = sizeof(donkeyvalue); // CED2K uses a 16 byte MD4 to hold its value, just like CMD4 does
// Have the objects write the hashes they computed into the hash value variables md4.GetHash(&md4value); md5.GetHash(&md5value); sha1.GetHash(&sha1value); tiger.GetRoot(&tigervalue); // GetRoot, instead of GetHash donkey.GetRoot(&donkeyvalue);
// Express the values as text using base 16 and base 32 CString md4base16 = tobase16byte*)(&md4value), sizeof(md4value; CString md4base32 = tobase32byte*)(&md4value), sizeof(md4value; CString md5base16 = tobase16byte*)(&md5value), sizeof(md5value; CString md5base32 = tobase32byte*)(&md5value), sizeof(md5value; CString sha1base16 = tobase16byte*)(&sha1value), sizeof(sha1value; CString sha1base32 = tobase32byte*)(&sha1value), sizeof(sha1value; CString tigerbase16 = tobase16byte*)(&tigervalue), sizeof(tigervalue; CString tigerbase32 = tobase32byte*)(&tigervalue), sizeof(tigervalue; CString donkeybase16 = tobase16byte*)(&donkeyvalue), sizeof(donkeyvalue; CString donkeybase32 = tobase32byte*)(&donkeyvalue), sizeof(donkeyvalue; } </source>
The tiger and donkey objects act differently from md5 and sha1 in several ways. At the start, you have to tell them how big the whole file is.
<source lang="c"> // For tiger and donkey, you have to call BeginFile first tiger.BeginFile(9, bytes); // Tell it the tiger height is 9, and the file size donkey.BeginFile(bytes); // Tell it the file size </source>
So, if you were going to hash a 100 KB file 1 KB at a time, you would tell BeginFile the whole file size. The TigerTree object needs another piece of information. In the 2.0 code, it gets the value Settings.Library.TigerHeight, which is 9.
Some methods are named differently. Add and AddToFile seem to be the same thing, as do Finish and FinishFile. GetHash is replaced by GetRoot for the tiger and donkey objects, because the hash we are getting is the root hash of the entire file.
Here are the hash value types:
<source lang="c"> // You can call sizeof on these DWORD size; size = sizeof(md4value); // CMD4 uses a 16 byte MD4 to hold its value size = sizeof(md5value); // CMD5 uses a 16 byte MD5 to hold its value size = sizeof(sha1value); // CSHA uses a 20 byte SHA1 to hold its value size = sizeof(tigervalue); // CTigerTree uses a 24 byte TIGEROOT to hold its value size = sizeof(donkeyvalue); // CED2K uses a 16 byte MD4 to hold its value, just like CMD4 does </source>
Both CMD4 and CED2K use 16-byte MD4 variables to hold the hashes they compute.
Results
Here are the results from hashing nothing, followed by hashing the 5 ASCII bytes that make up the word hello.
<source lang="c"> HashData(NULL, 0);
md4base16 31d6cfe0d16ae931b73c59d7e0c089c0 md4base32 ghlm7ygrnlutdnz4lhl6bqejya md5base16 d41d8cd98f00b204e9800998ecf8427e md5base32 2qoyzwmpaczaj2mabgmoz6ccpy sha1base16 da39a3ee5e6b4b0d3255bfef95601890afd80709 sha1base32 3i42h3s6nnfq2msvx7xzkyayscx5qbyj tigerbase16 000000000000000000000000000000000000000000000000 tigerbase32 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa donkeybase16 00000000000000000000000000000000 donkeybase32 aaaaaaaaaaaaaaaaaaaaaaaaaa
HashData[[byte*)"hello", 5);
md4base16 866437cb7a794bce2b727acc0362ee27 md4base32 qzsdps32pff44k3splgagyxoe4 md5base16 5d41402abc4b2a76b9719d911017c592 md5base32 lvauakv4jmvhnolrtwiraf6fsi sha1base16 aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d sha1base32 vl2mmho4yxukfwv63yhtwsbm3gxksq2n tigerbase16 398ef4d84353cbe0f831a64418f3012a5419494727186eed tigerbase32 hghpjwcdkpf6b6bruzcbr4ybfjkbsskhe4mg53i donkeybase16 866437cb7a794bce2b727acc0362ee27 donkeybase32 qzsdps32pff44k3splgagyxoe4 </source>
When there is no data to hash, the tiger and donkey objects produce hashes composed of zeroes. The other objects produce real-looking hash values even for no data.
Notice that donkeybase16 is the same as md4base16 - both end in ee27. The root hash of a file in eDonkey2000 is the same as the MD4 hash of its contents.
Here's the TigerTree and eDonkey2000 code grouped together:
<source lang="c"> void Test() {
// Compute the hash of the 5 bytes of the ASCII text "hello" HashTiger[[byte*)"hello", 5); HashDonkey[[byte*)"hello", 5); }
void HashTiger(byte* p, DWORD bytes) {
// Compute the TigerTree root hash for the file CTigerTree hash; // The object that will compute the hash hash.BeginFile(9, bytes); // Tell it the tiger height is 9, and the file size hash.AddToFile(p, bytes); // Give it the data to hash hash.FinishFile(); // That's all
// Get the TigerTree root hash value TIGEROOT value; // The variable that will store the hash value DWORD size = sizeof(value); // 24 bytes hash.GetRoot(&value); // Get the hash value from the object
// Express it in base 16 CString s = tobase16byte*)(&value), sizeof(value; }
void HashDonkey(byte* p, DWORD bytes) {
// Compute the root hash for the file using MD4 the way eDonkey2000 does CED2K hash; // The object that will compute the hash hash.BeginFile(bytes); // Tell it the file size hash.AddToFile(p, bytes); // Give it the data to hash hash.FinishFile(); // That's all
// Get the eDonkey2000 root hash value MD4 value; // The variable that will store the hash value DWORD donkeysize = sizeof(value); // 16 bytes hash.GetRoot(&value); // Get the hash value from the object
// Express it in base 16 CString s = tobase16byte*)(&value), sizeof(value; } </source>
The results are:
Tiger: 398ef4d84353cbe0f831a64418f3012a5419494727186eed Donkey: 866437cb7a794bce2b727acc0362ee27
Now, I'll try to get these two functions working with camper's code.
camper's code
Looking at how camper has updated CLibrayBuilder::HashFile in his code should make it easy to carry the changes he made into my sample function.
<source lang="c"> void Test() {
// Compute the hash of the 5 bytes of the ASCII text "hello" HashTiger[[byte*)"hello", 5); HashDonkey[[byte*)"hello", 5); }
void HashTiger(byte* p, DWORD bytes) {
// Compute the TigerTree root hash for the file CTigerTree hash; // The object that will compute the hash hash.BeginFile(9, bytes); // Tell it the tiger height is 9, and the file size hash.AddToFile(p, bytes); // Give it the data to hash hash.FinishFile(); // That's all
// Get the TigerTree root hash value Hashes::TigerHash value; // The object that will store the hash value DWORD size = Hashes::TigerHash::byteCount; // 24 bytes hash.GetRoot(value); // Get the hash value from the object
// Express it in base 16 CString s = tobase16(&value[0], Hashes::TigerHash::byteCount); }
void HashDonkey(byte* p, DWORD bytes) {
// Compute the root hash for the file using MD4 the way eDonkey2000 does CED2K hash; // The object that will compute the hash hash.BeginFile(bytes); // Tell it the file size hash.AddToFile(p, bytes); // Give it the data to hash hash.FinishFile(); // That's all
// Get the eDonkey2000 root hash value Hashes::Ed2kHash value; // The object that will store the hash value DWORD size = Hashes::Ed2kHash::byteCount; // 16 bytes hash.GetRoot(value); // Get the hash value from the object
// Express it in base 16 CString s = tobase16(&value[0], Hashes::Ed2kHash::byteCount); } </source>
The hashes it computes are unchanged.