Developers.Hash.RoundTrip20
Hash to text and back again
Same thing, now in the 2.0 code. Here, it's easy to see what methods each class offers by looking at their .h files. I want to test:
MD4.h (There are no text methods here)
MD5.h HashToString(const MD5* pHash, BOOL bURN = FALSE); HashFromString(LPCTSTR pszHash, MD5* pMD5); HashFromURN(LPCTSTR pszHash, MD5* pMD5);
SHA.h GetHashString(BOOL bURN = FALSE); HashToString(const SHA1* pHash, BOOL bURN = FALSE); HashToHexString(const SHA1* pHash, BOOL bURN = FALSE); HashFromString(LPCTSTR pszHash, SHA1* pHash); HashFromURN(LPCTSTR pszHash, SHA1* pHash);
TigerTree.h RootToString();
ED2K.h HashToString(const MD4* pHash, BOOL bURN = FALSE); HashFromString(LPCTSTR pszHash, MD4* pHash); HashFromURN(LPCTSTR pszHash, MD4* pHash);
Here they all are in action:
MD4
<source lang="c"> // Takes a pointer to some memory and the number of bytes of data there // Computes MD4 hashes of the information and converts it to and from text void HashMD4(byte* p, DWORD bytes) {
// Hash the data CMD4 hash; // Make the object that will compute the hash hash.Add(p, bytes); // Give the object the data to hash hash.Finish(); // Tell the hash object that is all the data we are going to add
// Get the hash value MD4 value; // Make a local instance of a structure to hold the hash value DWORD size = sizeof(value); // The value is 16 bytes, 128 bits, 32 hex characters hash.GetHash(&value); // Get the hash value
// Convert it to text CString direct; direct = tobase16byte*)(&value), sizeof(value; // "866437cb7a794bce2b727acc0362ee27" for "hello" } </source>
MD4 doesn't have any methods that express a hash as text. The Shareaza code borrows the static method MD5::HashToString to do it because both MD4 and MD5 are 16 bytes.
MD5
<source lang="c"> // Takes a pointer to some memory and the number of bytes of data there // Computes MD5 hashes of the information and converts it to and from text void HashMD5(byte* p, DWORD bytes) {
// Hash the data CMD5 hash; // Make the object that will compute the hash hash.Add(p, bytes); // Give the object the data to hash hash.Finish(); // Tell the hash object that is all the data we are going to add
// Get the hash value MD5 value; // Make a local instance of a structure to hold the hash value DWORD size = sizeof(value); // The value is 16 bytes, 128 bits, 32 hex characters hash.GetHash(&value); // Get the hash value
// Convert it to text CString direct, tostring, tourn; direct = tobase16byte*)(&value), sizeof(value; // "5d41402abc4b2a76b9719d911017c592" for "hello" tostring = CMD5::HashToString(&value, false); // "5d41402abc4b2a76b9719d911017c592" tourn = CMD5::HashToString(&value, true); // "md5:5d41402abc4b2a76b9719d911017c592"
// Turn the text back into hash values MD5 value1, value2; CMD5::HashFromString(tostring, &value1); // Takes just base 16 characters CMD5::HashFromURN(tourn, &value2); // Takes "md5:" followed by base 16 characters
// Make sure that didn't change anything CString direct2, direct3; direct2 = CMD5::HashToString(&value1, false); direct3 = CMD5::HashToString(&value2, false); } </source>
MD5 is using base 32 lowercase, and has a header md5:
SHA1
<source lang="c"> // Takes a pointer to some memory and the number of bytes of data there // Computes SHA1 hashes of the information and converts it to and from text void HashSHA1(byte* p, DWORD bytes) {
// Hash the data CSHA hash; // Make the object that will compute the hash hash.Add(p, bytes); // Give the object the data to hash hash.Finish(); // Tell the hash object that is all the data we are going to add
// Get the hash value SHA1 value; // Make a local instance of a structure to hold the hash value DWORD size = sizeof(value); // The value is 20 bytes, 160 bits, 40 hex characters hash.GetHash(&value); // Get the hash value
// You can have the hash object tell us the base 32 text directly CString s1, s2, s3, s4, s5, s6, s7, s8, s9, s10; s1 = hash.GetHashString(false); // "VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N" for "hello" s2 = hash.GetHashString(true); // "urn:sha1:VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N"
// Access the memory of the hash value directly and express it in base 16 and 32 text s3 = tobase16byte*)(&value), sizeof(value.MakeUpper(); // "AAF4C61DDCC5E8A2DABEDE0F3B482CD9AEA9434D" s4 = tobase32byte*)(&value), sizeof(value.MakeUpper(); // "VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N"
// Use static methods to generate base 16 and base 32 text with and without the "urn:sha1:" header s5 = CSHA::HashToHexString(&value, false); // "AAF4C61DDCC5E8A2DABEDE0F3B482CD9AEA9434D" s6 = CSHA::HashToHexString(&value, true); // "urn:sha1:AAF4C61DDCC5E8A2DABEDE0F3B482CD9AEA9434D" s7 = CSHA::HashToString(&value, false); // "VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N" s8 = CSHA::HashToString(&value, true); // "urn:sha1:VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N"
// Use static methods to turn those strings back into hash values SHA1 value1, value2; CSHA::HashFromString(s7, &value1); // Takes just base 32 characters CSHA::HashFromURN(s8, &value2); // Takes "urn:sha1:" followed by base 32 characters
// Convert those hash values back into strings, make sure you get the same thing s9 = CSHA::HashToString(&value1, false); // "VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N" s10 = CSHA::HashToString(&value2, false); // "VL2MMHO4YXUKFWV63YHTWSBM3GXKSQ2N" } </source>
For SHA1, the Shareaza 2.0 code offers both base 16 and base 32 as options. Uppercase base 32 seems to be the default, and the header is urn:sha1:
TigerTree
<source lang="c"> // Takes a pointer to some memory and the number of bytes of data there // Computes the TigerTree root hash of the information and converts it to and from text 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
// Convert it to text CString direct, root; direct = tobase32byte*)(&value), sizeof(value.MakeUpper(); // "HGHPJWCDKPF6B6BRUZCBR4YBFJKBSSKHE4MG53I" for "hello" root = hash.RootToString(); // "HGHPJWCDKPF6B6BRUZCBR4YBFJKBSSKHE4MG53I" } </source>
TigerTree is using uppercase base 32. The code doesn't have an option to stick on a URN header.
eDonkey2000
<source lang="c"> // Takes a pointer to some memory and the number of bytes of data there // Computes the eDonkey2000 root hash of the information and converts it to and from text 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 size = sizeof(value); // 16 bytes hash.GetRoot(&value); // Get the hash value from the object
// Convert it to text CString direct, tostring, tourn; direct = tobase16byte*)(&value), sizeof(value; // "866437cb7a794bce2b727acc0362ee27" for "hello" tostring = CED2K::HashToString(&value, false); // "866437cb7a794bce2b727acc0362ee27" tourn = CED2K::HashToString(&value, true); // "urn:ed2khash:866437cb7a794bce2b727acc0362ee27"
// Turn it back into hash values MD4 value2, value3; CED2K::HashFromString(tostring, &value2); CED2K::HashFromURN(tourn, &value3);
// Make sure that didn't change anything CString direct2, direct3; direct2 = tobase16byte*)(&value2), sizeof(value2; direct3 = tobase16byte*)(&value3), sizeof(value3; } </source>
eDonkey2000 is using lowercase base 16. The header is urn:ed2khash: