Game Development Community

dev|Pro Game Development Curriculum

SHA1 in Torque

by Kyrah Abattoir · 04/08/2013 (5:28 pm) · 5 comments

This is resource will allow you to add to the engine the ability to produce SHA1 hashes and expose it to TorqueScript.

I want to give a BIG thank to the people at irc.maxgaming.net #garagegames , especially Tim-MGT and TRON who fixed my many rookie errors, without them I would never have managed to make it work.

EDIT: I added a second function to compute SHA1 digests on files, it's probably not the best way to load and read the file, but it will work even with very large files (about 5 seconds on my system for a 400Mb file) without having to load it in memory.

EDIT: I modified the file function to use a larger buffer a more elegant while loop, and removed the buffer pointer.

Step 1: getting the algorythm


Grab sha1.cc and sha1.h from gauss.ececs.uc.edu/Courses/c653/lectures/Hashing/sha1/

Place both files wherever it is convenient for you, personally i'm using the existing source folder in my project folder.

"My Projects/<projectname>/source/sha1/"

Step 2: Including it in the project


In visual C++ Open the solution explorer section "<projectname> DLL".
I tend to keep my files separated from the "core" files whenever i can, so in my case, i created a new filter si it looks like this:
"Source Files/<project>/sha1/" and then i added both sha1.cc and sha1.h to it. As far as i know the tree view in the solution explorer is only for "visual" tidyness.

Step 3: Exposing it to TorqueScript

In The solution explorer i created a new file "console_functions.cc". This is basically the "glue" that enable you to access the SHA1 code from the engine.

#include "console/engineAPI.h"	//This is mandatory to get access to DefineConsoleFunction.
#include "sha1/sha1.h"			//You might need to change this to reflect where you placed your sha1.h file.

//This function turn the binary returned by the sha1 hashing in exadecimal form
static char getHex(char c)
{
   if(c <= 9)
      return c + '0';
   return c - 10 + 'A';
}

//The actual TorqueScript function.
DefineConsoleFunction( getStringSHA1, const char*, ( const char* text ),,
"Generate SHA1 hash of string." )
{
	const size_t	hashSize = 20;
	sha1_context	ctx;
	unsigned char	sha1sum[hashSize];
	char			*strhash;
	size_t			i;


	// generate hash
	sha1_starts(&ctx);
	sha1_update(&ctx,(uint8 *)text, strlen(text));
	sha1_finish(&ctx, sha1sum);

	// get a string buffer to hold hash value to return to caller 
	strhash = Con::getReturnBuffer( (U32)(hashSize * 2) +1 );
	strhash[hashSize * 2] = 0;

	// convert hash sum into hexadecimal string
	for(i=0; i<hashSize; ++i)
	{
		strhash[i*2   ]	= getHex(sha1sum[i] >> 4  );
		strhash[i*2 +1]	= getHex(sha1sum[i] & 0x0F);
	}

	// return hash string to caller
	return strhash;
}

DefineConsoleFunction( getFileSHA1, const char*, ( const char* filepath ),,"Generate SHA1 hash of a file." )
{
	const size_t	hashSize = 20;
	const size_t	buffSize = 32000;
	sha1_context	ctx;
	unsigned char	sha1sum[hashSize];
	char			*strhash;
	size_t			i;
	size_t          size;
	char			buffer[buffSize];

	//we open the file, if the file couldn't be opened, we return NULL.
	FILE * myFile = fopen(filepath,"rb");
	if(myFile == NULL)
	{
		Con::errorf(ConsoleLogEntry::Script, "File not found: \"%s\".",filepath);
        return NULL;
	}

	sha1_starts(&ctx);
	while( true )
	{
		//as long as we haven't reached the end of the file, we loop.
		size = fread(buffer, 1, buffSize, myFile);
		sha1_update(&ctx,(uint8 *)buffer, size);
		if(size < buffSize) break;
	}
	sha1_finish(&ctx, sha1sum);

	// get a string buffer to hold hash value to return to caller 
	strhash = Con::getReturnBuffer( (U32)(hashSize * 2) +1 );
	strhash[hashSize * 2] = 0;

	// convert hash sum into hexadecimal string
	for(i=0; i<hashSize; ++i)
	{
		strhash[i*2   ]	= getHex(sha1sum[i] >> 4  );
		strhash[i*2 +1]	= getHex(sha1sum[i] & 0x0F);
	}

	// return hash string to caller
	return strhash;
}

Step 4: Using it!

The syntax to call this function is the following:
%hashedtext = getStringSHA1( %text );
And to get the sha1 checksum on a file:
%hashedfile = getFileSHA1( %filepath );
NOTE: Trying to sha a file that doesn't exist will return null.


There are numerous uses for such a hashing function, such as message signing, authentication systems and integrity checks.

Enjoy!

#1
04/09/2013 (1:45 pm)
Awesome resource. better security than md5 for sure. Now only if there was a getFileSha1... :P
#2
04/09/2013 (2:43 pm)
File hashing added :)
#3
04/11/2013 (6:03 am)
Nice addition thanks.
#4
04/17/2013 (4:02 pm)
woah, thanks so much!
~Jeff
#5
05/09/2013 (2:23 am)
You realize that's a gpl implementation of SHA-1 you're using, right? The original public domain implementation of the algorithm can be found here: http://www.faqs.org/rfcs/rfc3174.html