Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

how calculate a CRC32 hash like XBMC does? (C# code example)


  • Please log in to reply
7 replies to this topic
FP
  • Guests
  • Last active:
  • Joined: --
I'm trying to identify the thumbnails in my XBMC movie database. The manual says the names for the thumbnails are generated by doing a CRC32 hash of the path + filename in lowercase.

examples from the manual:
F:\Videos\Nosferatu.avi returns 2a6ec78d
smb://user:[email protected]/share/directory/ returns c5559f13
smb://user:[email protected]/share/directory/file.ext returns 8ce36055
123456789 returns 0376e6e7

The strange thing is, i tried the examples on various online sites and none returned the same result as in the examples...
(on a side note: every site returned a different result than the other, how can that be should be a hash always the same?)

http://crc32-checksum.waraxe.us/
http://hash.online-c...crc32-generator
http://zorc.breitbandkatze.de/crc.html

In the manual is a working code snippet posted which should return the exact same hash results like XBMC does calculate it. The Problem is, its in C# and i'm a total noob about C#.

public string Hash(string input)
{
   char[] chars = input.ToCharArray();
   for (int index = 0; index < chars.Length; index++)
   {
       if (chars[index] <= 127)
       {
          chars[index] = System.Char.ToLowerInvariant(chars[index]);
       }
   }
   input = new string(chars);
   uint m_crc = 0xffffffff;
   byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
   foreach (byte myByte in bytes)
   {
       m_crc ^= ((uint)(myByte) << 24);
       for (int i = 0; i < 8; i++)
       {
           if ((System.Convert.ToUInt32(m_crc) & 0x80000000) == 0x80000000)
           {
               m_crc = (m_crc << 1) ^ 0x04C11DB7;
           }
           else
           {
               m_crc <<= 1;
           }
       }
   }
   return String.Format("{0:x8}", m_crc);
}

Could somebody who actually understands C# transfer that code to ahk, if its possible? Would really appreciate it.

Thanks a lot.

FP

OnlyHuman
  • Members
  • 284 posts
  • Last active: Aug 22 2015 10:11 PM
  • Joined: 18 Feb 2011
Check this out...> .NET Framework Interop

Key Features:

Load the Common Language Runtime into the script's process.
Load .NET assemblies (dll files) by full name, partial name, or path.
Instantiate objects and call instance methods or properties.
Compile C# or VB code on the fly or to file.


Docs
I use AHK 1.1.20.03 32-bit ~~ Windows 10 (64 bit) ~~ Firefox


Rseding91
  • Members
  • 703 posts
  • Last active: Apr 02 2016 05:05 AM
  • Joined: 07 Jun 2010
You could also use this existing library that can do all kinds of hashes.

<!-- m -->http://www.autohotke...topic23584.html<!-- m -->

MD5, SHA1 or CRC32

I modified it to be a standalone function for my own needs so I didn't have to include a bunch of extra code in my script. So, if you need help with getting it working I could help (just post what you've tried so far and what's not working).

FP
  • Guests
  • Last active:
  • Joined: --
@OnlyHuman
That looks very interesting and i guess would be useful for this case. But the problem is since i have no clue about C# and its syntax i'm not sure what needs to be written to actually make this thing work. Would appreciate any help.

@rseding91
I found that library post by a forums search beforehand and i also tried it out, but the results didn't turned out like described in the XBMC examples above.

According to the examples of the XBMC manual 123456789 should return 0376e6e7, but did actually return CBF43926.
And f:\videos\nosferatu.avi should return 2a6ec78d, but actually returns BB9A6DBF.

I double checked the results of the CRC32 library function with the results of the online site http://crc32-checksum.waraxe.us/ and they output the same. I have no clue why XBMC gets a different CRC32 checksum out. And therefore i was asking about the C# code example above, because with that code it should calculate exactly the same results as XBMC does.

here is my quick and dirty test (needs file.ahk):

; 123456789 should return 0376e6e7
FileAppend, 123456789, test.txt

sFile := A_WorkingDir "\test.txt"	; Specify the real path

MsgBox, % "CRC32:`t"	. File_Hash2(sFile, "CRC32")	. "`n"
	. "MD5:`t"	. File_Hash(sFile, "MD5")	. "`n"
	. "SHA1:`t"	. File_Hash(sFile, "SHA1")	. "`n"

FileDelete, test.txt

Return


File_Hash2(sFile, SID = "CRC32")
{
	nSize:=	File_WriteMemory(sFile, sData)
	Return	Crypt_Hash2(&sData, nSize, SID)
}

Crypt_Hash2(pData, nSize, SID = "CRC32", nInitial = 0)
{
	CALG_SHA := CALG_SHA1 := 1 + CALG_MD5 := 0x8003
	If Not	CALG_%SID%
	{
		FormatI := A_FormatInteger
		SetFormat, Integer, H
		sHash := DllCall("ntdll\RtlComputeCrc32", "Uint", nInitial, "Uint", pData, "Uint", nSize, "Uint")
		SetFormat, Integer, %FormatI%
		StringUpper,	sHash, sHash
		StringReplace,	sHash, sHash, X, 000000
		Return	SubStr(sHash,-7)
	}

	DllCall("advapi32\CryptAcquireContextA", "UintP", hProv, "Uint", 0, "Uint", 0, "Uint", 1, "Uint", 0)
	DllCall("advapi32\CryptCreateHash", "Uint", hProv, "Uint", CALG_%SID%, "Uint", 0, "Uint", 0, "UintP", hHash)
	DllCall("advapi32\CryptHashData", "Uint", hHash, "Uint", pData, "Uint", nSize, "Uint", 0)
	DllCall("advapi32\CryptGetHashParam", "Uint", hHash, "Uint", 2, "Uint", 0, "UintP", nSize, "Uint", 0)
	VarSetCapacity(HashVal, nSize, 0)
	DllCall("advapi32\CryptGetHashParam", "Uint", hHash, "Uint", 2, "Uint", &HashVal, "UintP", nSize, "Uint", 0)
	DllCall("advapi32\CryptDestroyHash", "Uint", hHash)
	DllCall("advapi32\CryptReleaseContext", "Uint", hProv, "Uint", 0)

	FormatI := A_FormatInteger
	SetFormat, Integer, H
	Loop,	%nSize%
		sHash .= SubStr(*(&HashVal + A_Index - 1), -1)
	SetFormat, Integer, %FormatI%
	StringReplace,	sHash, sHash, x, 0, All
	StringUpper,	sHash, sHash
	Return	sHash
}

Any idea what needs to be changed?

Thanks
FP

Frankie
  • Members
  • 2930 posts
  • Last active: Feb 05 2015 02:49 PM
  • Joined: 02 Nov 2008
I can tell you the problem... but not how to fix it. The C# line that ends with "GetBytes(input)" gets bytes for each character in the string and stores it in an array. In AutoHotkey the closest way to do this is using NumGet. The problem is: what are the correct parameters for offset and data size (uchar is one byte, short is two etc.) If you can find that, you can find the answer.

The reason online services are unreliable is that one may use ANSI and another may use UTF8 or UTF16. Each encoding gives different byte data and a different resulting hash.
aboutscriptappsscripts
Request Video Tutorials Here or View Current Tutorials on YouTube
Any code ⇈ above ⇈ requires AutoHotkey_L to run

VxE
  • Moderators
  • 3622 posts
  • Last active: Dec 24 2015 02:21 AM
  • Joined: 07 Oct 2006
Wikipedia seems to suggest that there are many implementations of so-called "crc32" checksum algorithms, so it's no surprise that <insert crc32 generator here> does not produce the correct hash.

Anyways, this topic finally got a lucky die roll, so here's the code (tested in AHK-Basic, lightly tested in AHK-L-unicode).
CRC32_XBMC( string ) {
If ( A_IsUnicode )
{
	tempstr := string, pty := A_PtrSize = "" ? "UInt" : "Ptr"
	len := DllCall("WideCharToMultiByte", "UInt", 65001, "UInt", 0, pty, &tempstr, "Int", -1, pty, 0, "Int", 0, pty, 0, pty, 0 )
	VarSetCapacity( string, len, 0 )
	DllCall("WideCharToMultiByte", "UInt", 65001, "UInt", 0, pty, &tempstr, "Int", -1, pty, &string, "Int", len--, pty, 0, pty, 0 )
	VarSetCapacity( tempstr, 0 )
}
Else StringLen, len, string
crc := 0xFFFFFFFF
Loop, % len
{
	char := *( &string + A_Index - 1 )
	crc ^= char + ( 65 <= char && char <= 90 ? 32 : 0 ) << 24
	Loop, 8
		crc := ( ( crc & 0x7fffffff ) << 1 ) ^ ( crc >> 31 ? 0x04C11DB7 : 0 )
}
Loop, 8
	char := ( crc >> ( 8 - A_Index << 2 ) ) & 15, tempstr .= Chr( 48 + char + 39 * ( 9 < char ) )
Return tempstr
}


FP
  • Guests
  • Last active:
  • Joined: --
Great! Thank you so much! Works nicely :)

FP

pleez
  • Guests
  • Last active:
  • Joined: --
i've been using xbmc for years and always wondered how the crc32 values are calculated. i am not to familiar with auto hotkey. i can't get the script to work. i open a new text file, paste that code in, save it, rename to xbmc.ahk, but when i double click it the tray icon appears for a spit second and then disappears and nothing happens. any help on how to get it to work? what other files do i need?

thanks!