I inherited a DLL that the project uses to generate a checksum. The DLL does this by building a list of project files and calculating the MD5 hash for each. There are excluded files, such as anything subversion(SVN) uses to track version. These calculated MD5 hash values get saved to a text file. They also get sent to a roll up hash function that we built that 'and' s each into one overall hash.
Later we run, using the same DLL, a verify hash which uses the exact same MD5 hash generator function to do a string comparison (strncmp() to be specific), the source of the 'known hash' is the text file from earlier.
Here is where I found something unexpected, the CVI .c source files inside the project have a changing hash. Specifically it is just the .c source files that generate both a DLL and an EXE but everything else in that workspace is matching and that includes the generated files, i.e. the DLL/EXE.
I tried making all the files read only using the SetAttrib() and performing that before a MD5 is calculated. Then I ran the generate and the verify, it still changed. Ran the generate again, thinking well now they are all read only and it should not change and it still changed when I ran the verify.
I am using CVI 2013 SP2 and dotnet version is 4.5.2, we are not using FIPS compliant algorithms. Pasted the function that gets the MD5 hash below.
I am wondering if anyone has some ideas where this behavior is coming from, I could always add the .c files to the ignore list but I would rather understand what is going on before I do that.
char* getFileMD5(const char* filePath)
{
Initialize_mscorlib();
System_IO_FileStream fileStream = NULL;
System_Text_StringBuilder sbInstance = NULL;
System_Security_Cryptography_MD5 cryptoInstance = NULL;
char* hashString = NULL;
unsigned char* hash = NULL;
ssize_t hashLength = 0;
// Create a new instance to the cryptography class
System_Security_Cryptography_MD5_Create(&cryptoInstance, NULL);
System_Security_Cryptography_MD5_Initialize(cryptoInstance, NULL);
// Open a file stream to the provided file path, probably need to handle any exceptions raised
System_IO_File_OpenRead(filePath, &fileStream, NULL);
// Computer the MD5 hash of the file
System_Security_Cryptography_MD5_ComputeHash(cryptoInstance, (System_IO_Stream) fileStream, &hash, &hashLength, NULL);
// Convert the MD5 hash from a byte array to string readable format
System_BitConverter_ToString_1(hash, hashLength, &hashString, NULL);
// Replace hyphens with an empty character
System_Text_StringBuilder__Create_2(&sbInstance, hashString, NULL);
System_Text_StringBuilder_Get_Length(sbInstance, &hashLength, NULL);
System_Text_StringBuilder_Replace(sbInstance, "-", "", 0, strlen(hashString), &sbInstance, NULL);
System_Text_StringBuilder_ToString(sbInstance, &hashString, NULL);
StringLowerCase(hashString);
// Clean up
CDotNetFreeMemory(hash);
CDotNetDiscardHandle(sbInstance);
CDotNetDiscardHandle(fileStream);
CDotNetDiscardHandle(cryptoInstance);
Close_mscorlib();
return hashString;
}