Getting different MD5 hashes in cryptoAPI and java messageDigest

Hi,

I am writing a java application to produce a hash value for a string

which should give me the same hash value as a c++ code which uses CryptoAPI.

I am including code snippets of the c++ and the java codes...Plese tell me

if the reason i am getting different hash values is because the java code is

using a different provider. If so where do i get the provider and how do i use it

in this code.

try

{

if (0==::CryptAcquireContext(&hProv,NULL,MS_DEF_PROV, PROV_RSA_FULL,CRYPT_MACHINE_KEYSET))

{

//throwing exception

}

// Create the hash object...

if (0==::CryptCreateHash(hProv,CALG_MD5,0,0,&hHash))

{

//throwing exception

}

// Actually hash the data

if (0==::CryptHashData(hHash,reinterpret_cast<CONST BYTE *>(bsData),::SysStringByteLen(bsData),0))

{

//throwing exception

}

// Extract the actual hash value from the hash object

// But first get the buffer size required to store the same...

if (0==::CryptGetHashParam(hHash,HP_HASHVAL,NULL,&dwLen,0))

{

//throwing exception

}

// Try allocating memory for the buffer...

pBuffer=static_cast<BYTE *>(::malloc(dwLen));

if (NULL==pBuffer)

{

//throwing exception

}

memset(pBuffer,'\0',sizeof(pBuffer));

// Now extract the hash value into this buffer

if (0==::CryptGetHashParam(hHash,HP_HASHVAL,pBuffer,&dwLen,0))

{

//throwing exception

}

// Capture the hash value into a BSTR

::SysFreeString(*pbsHashValue);

*pbsHashValue=NULL;

// Allocate the new string

*pbsHashValue=::SysAllocStringLen((unsignedshort *)pBuffer,dwLen/2);

if (NULL==*pbsHashValue)

{

//throwing exception

}

}catch(char *e){

//cleanup and show error if any.

}

The hash i get for "srikanth" is "b*.DB宕ξ.遫铀.." or

" 98 42 46 68 66 229 180 166 206 46 223 111 211 203 46 46 0"

The java Code:

{

MessageDigest messageDigest;

byte []l_bytes=null;

String p_password ="srikanth";

try{

messageDigest = MessageDigest.getInstance("MD5");

messageDigest.update(p_password.getBytes (),0,p_password.length ());

l_bytes= messageDigest.digest();

BigInteger hash =new BigInteger( 1, l_bytes );

System.out.println("hash :"+hash);

String hpassword = hash.toString( 16 );

System.out.println(hpassword);

}catch(NoSuchAlgorithmException e){

System.out.println("No Such Algorithm Exception");

return;

}

}

and output here is :

hash :98295845500620623440969102971712815427

49f3175a93cd22f5e345bca772f7c143

Please let me know where am i going wrong.

Thanks,

Srik.

[4665 byte] By [srika] at [2007-10-2 6:28:42]
# 1
Your C++ code is suspect because using openssl I getecho -n srikanth | openssl md5gives49f3175a93cd22f5e345bca772f7c143and my Java gives the same result.
sabre150a at 2007-7-16 13:30:36 > top of Java-index,Security,Cryptography...
# 2

Hi,

I do not want to change the c++ side code(unless i am doing a mistake there). I want to use cryptoAPI and am sure there has to be some way we can configure the provider to give the same hash as the c++ code. I also tried some common solutions like "put an empty byte after each byte of the Java message", " putting a '\0' after java string" but to no use. Can someone suggest the different providers available in java and where i can find them so that i can try out if i get the same hash.

Thanks,

Srik.

srika at 2007-7-16 13:30:36 > top of Java-index,Security,Cryptography...
# 3
Like you I tried appending to the string to try to see what is different. I tried \0 \r\n \r\n\0 \n\r \n\r\0 \r \n \r\0 \n\0 but none give your C++ result!The question I have to ask is why to don't want to change the C++?
sabre150a at 2007-7-16 13:30:36 > top of Java-index,Security,Cryptography...
# 4

I think your C++ code is not right, particularly your CryptGetHashParam logic. You should first set dwLen = 0 prior to the first call, then malloc, then re-call CryptGetHashParam. For example.

DWORD dwLen = 0;

::CryptGetHashParam(hHash,HP_HASHVAL,NULL,&dwLen,0); // should return FALSE

BYTE *pBuffer = new BYTE[dwLen];

// Now extract the hash value into this buffer

if (0==::CryptGetHashParam(hHash,HP_HASHVAL,pBuffer,&dwLen,0))

{

//throwing exception

}

ghstarka at 2007-7-16 13:30:36 > top of Java-index,Security,Cryptography...
# 5

I was setting dwLen to zero in the declaration part which i did not paste. Rest of it seems fine. What I meant when I said i dont want to change the c++ code is I have to use CryptoAPI. I can tweak the code to get the same hash as what i get from the java code if that is what u has asked for. If some one has a working code using CryptoAPI in c++ and verifying it using java can u pls fw it along with the hash produced by them for a sample string..

srika at 2007-7-16 13:30:36 > top of Java-index,Security,Cryptography...
# 6
Finally figured out the problem. We can get the same hash as what we are getting in the c++ code by getting the bytes from the string in little endian formp_password.getBytes("UTF-16LE");Anyways thanks for all your replies...Srik.
srika at 2007-7-16 13:30:36 > top of Java-index,Security,Cryptography...