Duplicate Microsoft FCIV MD5 file hash ?

G

Guest

I have a VB 5 module that duplicates the FCIV.exe from Microsoft. I need to
move an application forward to C#, but the samples for MD5 hash using the
framework I tried gave different hashes. What do I feed the framework and
how do I get the same values ??

The following code DOES NOT GIVE THE FCIV value:

public string getFileHash(string filePath)
{
string retVal = "";
// open file
try
{
FileInfo fi = new FileInfo(filePath);
long fileLength = fi.Length;
string fileString = Convert.ToString(fileLength);
retVal = Md5Hash(fileString); // method 1
string retVal2 = Md5Hash2(fileString); // method 2
retVal = retVal + " : " + retVal2;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
retVal = "";
}
return retVal;

}

public static string Md5Hash(string pass)
{
MD5 md5 = MD5CryptoServiceProvider.Create();
byte[] dataMd5 = md5.ComputeHash(Encoding.Default.GetBytes(pass));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5);
return sb.ToString();

}
public static string Md5Hash2(string str)
{

// Create a buffer large enough to hold the string
byte[] unicodeText = new byte[str.Length * 2];
Encoder enc = System.Text.Encoding.Unicode.GetEncoder();


// Now that we have a byte array we can ask the CSP to hash it
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(unicodeText);

// Build the final string by converting each byte
// into hex and appending it to a StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.Length; i++)
{
sb.Append(result.ToString("X2"));
}

// And return it
return sb.ToString();

}
 
J

Jon Skeet [C# MVP]

andrewcw said:
I have a VB 5 module that duplicates the FCIV.exe from Microsoft. I need to
move an application forward to C#, but the samples for MD5 hash using the
framework I tried gave different hashes. What do I feed the framework and
how do I get the same values ??

You're producing two hashes from the same string, but you're encoding
the string in a different way. (In fact, in one case you're not
encoding it at all - you're just getting the hash of an array of 0s.)
Why would you expect that to give the same result?

It's not at all clear why you're trying to get a hashcode of a
representation of the length of the file though - for one thing, that's
bound to be precisely representable in less data than the hash itself.

Are you aware that neither of your hash mechanisms is actually looking
at the *contents& of the file?
 
G

Guest

Jon,

Thanks for pointing out my misunderstanding. Does anyone know how the hash
would be created as MS does in FCIV ? The VB code does but exactly what it
is doing and how that maps to the .NET frameworks - I dont know. Any idea ??
 
G

Guest

Jon,

Here's how I re-wrote the code based on my limited understanding - but it
still is different - ideas ?? It seems odd to me that the encoding wants a
char array, so I go through some contortions to the file read as a char
array. I am also uneasy that when I read, I am coercing the value to be an
integer ( the file length ).

public string getFileHash(string filePath)
{
string retVal = "";
try
{
FileInfo fi = new FileInfo(filePath);
long fileLength = fi.Length;
char[] chars = new char[fileLength * 2];
TextReader streamReader = new StreamReader(filePath);
streamReader.Read(chars, 0, (int)fileLength);
MD5 md5 = MD5CryptoServiceProvider.Create();
//Encoding.Default.GetBytes(chars);
byte[] dataMd5 =
md5.ComputeHash(Encoding.Default.GetBytes(chars));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5);
return sb.ToString();
retVal = Md5Hash(filePath);
}
 
G

Guest

I guess that was a good enough shove to get me thinking - here's the code
that duplicate the FCIV program for binary file ( too ).

public string getFileHashBinary(string filePath)
{
string retVal = "";
try
{ // this works for binary files
FileInfo fi = new FileInfo(filePath);
long fileLength = fi.Length;
MD5 md5 = MD5CryptoServiceProvider.Create();
FileStream fs = new FileStream(filePath, FileMode.Open);
Byte[] bBuffer = new byte[fileLength];
int something= fs.Read(bBuffer, 0,(int)fileLength);
byte[] dataMd5 = md5.ComputeHash(bBuffer);
fs.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5);
retVal= sb.ToString();

}
catch (Exception e)
{
Console.WriteLine(e.Message);
retVal = "";
}
return retVal;

}



--
Andrew


andrewcw said:
Jon,

Here's how I re-wrote the code based on my limited understanding - but it
still is different - ideas ?? It seems odd to me that the encoding wants a
char array, so I go through some contortions to the file read as a char
array. I am also uneasy that when I read, I am coercing the value to be an
integer ( the file length ).

public string getFileHash(string filePath)
{
string retVal = "";
try
{
FileInfo fi = new FileInfo(filePath);
long fileLength = fi.Length;
char[] chars = new char[fileLength * 2];
TextReader streamReader = new StreamReader(filePath);
streamReader.Read(chars, 0, (int)fileLength);
MD5 md5 = MD5CryptoServiceProvider.Create();
//Encoding.Default.GetBytes(chars);
byte[] dataMd5 =
md5.ComputeHash(Encoding.Default.GetBytes(chars));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5);
return sb.ToString();
retVal = Md5Hash(filePath);
}


--
Andrew


Jon Skeet said:
You're producing two hashes from the same string, but you're encoding
the string in a different way. (In fact, in one case you're not
encoding it at all - you're just getting the hash of an array of 0s.)
Why would you expect that to give the same result?

It's not at all clear why you're trying to get a hashcode of a
representation of the length of the file though - for one thing, that's
bound to be precisely representable in less data than the hash itself.

Are you aware that neither of your hash mechanisms is actually looking
at the *contents& of the file?
 
J

Jon Skeet [C# MVP]

andrewcw said:
I guess that was a good enough shove to get me thinking - here's the code
that duplicate the FCIV program for binary file ( too ).

public string getFileHashBinary(string filePath)
{
string retVal = "";
try
{ // this works for binary files
FileInfo fi = new FileInfo(filePath);
long fileLength = fi.Length;
MD5 md5 = MD5CryptoServiceProvider.Create();
FileStream fs = new FileStream(filePath, FileMode.Open);

Once you've done that, just use md5.ComputeHash (fs);
There's no need for you to read all the data in yourself.

Note that you should use a "using" statement for your stream to make
sure it gets closed even if there's an exception.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top