Reputation: 6611
I am trying to generate C# MD5CryptoServiceProvider
to encode string and Java MessageDigest.getInstance("MD5")
to encode string, but both outputs are different. There are so many sample are already available on stackoverlflow
but still stuck on some where.
Following is my C# code:
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
Byte[] hashedDataBytes = null;
UTF8Encoding encoder = new UTF8Encoding();
hashedDataBytes = md5Hasher.ComputeHash(encoder.GetBytes("NSI#1234@"));
string strPassword = string.Empty;
foreach (byte b in hashedDataBytes)
{
strPassword = strPassword + b.ToString();
}
return strPassword;
The C#
code is freeze code, i have not permission to change this code.
Following is my Java code:
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] digest = messageDigest.digest("NSI#1234@".getBytes("UTF-8"));
String hash = new BigInteger(1, digest).toString();
System.out.println(hash);
C# code output: 158163028351382321031971922721528189209213
Java Code output: 210864369951346339831795420458152481237
C# generate 42 number and java generate 39 number. if i change the value of new BigInteger(1, digest).toString(8)
it generates 43 number and if i change new BigInteger(1, digest).toString(9)
it generates 41 number.
Upvotes: 0
Views: 723
Reputation: 8932
I have checked the correct value on the console:
$ export LC_ALL=en_US.UTF-8
$ export LANG=en_US.UTF-8
$ export LANGUAGE=en_US.UTF-8
$ echo -n "NSI#1234@" | md5sum.exe
9ea3001c238ae867c5c01bd71cbdd1d5 *-
So the result from your Java code is right, it's just not presented correctly (see below).
Your Java code is OK, it just formats the result wrong: It shows the result as a decimal number instead of the hexadecimal representation that is commonly used for hashes.
You should convert the number to hex before displaying it:
// [your code from above]
String hex=new BigInteger(1, digest).toString(16); // Hex, but without leading zeros
String fill=String.format("%0" + 32 + "d", 0) // This is ugly...
String hash=(fill+hex).substring(hex.length()) // ... and this is a hack to add leading zeros
Your C# code concatenated the decimal representation of each byte. While this works with hex numbers (as long as you add leading zeros in each step!), it doesn't work with decimal numbers at all. So the C# code is wrong, you must fix it.
Better use the converter provided by .NET, it's faster and it works correctly:
// [your code from above]
string hex = BitConverter.ToString(hashedDataBytes).Replace("-", string.Empty);
Upvotes: 3
Reputation: 1502526
Neither your C# code nor your Java code are good ways to convert a hash to a string. I strongly suspect you've got the same bytes in both cases, but you're converting them to strings differently.
Your C# code is just converting each byte to its decimal representation. (It's also doing so with repeated string concatenation. Ick.) Your Java code will ignore leading 0s and is currently using decimal. You can call toString(16)
to produce hex, but it will still ignore leading zeroes.
If you definitely want hex, you can use BitConverter.ToString(byte[])
to get a hex representation in .NET, although you may want to remove the -
it will place between each byte; in Java there are various libraries available such as Apache Commons Codec (Hex
) or Guava (BaseEncoding.base16()
). Or use some code from one of the many answers to hex encoding in Java on Stack Overflow, such as this one.
Alternatively, you could use Base64 - again, there are multiple options available, such as BitConverter.ToBase64String
in .NET and the iharder public domain library for Java.
If your C# code is truly frozen (run to the hills!) then the equivalent (well, slightly cleaner) Java code would be something like:
StringBuilder builder = new StringBuilder();
for (byte b : digest) {
builder.append(b & 0xff); // Convert signed to unsigned
}
I'd also urge you to use StandardCharsets.UTF_8
if you're using Java 7+.
But I would strongly advise fixing the C# code if you possibly can. Even if you're in "code freeze" that presumably doesn't prohibit you from fixing important bugs - and if you're storing these values, it'll be a lot easier to fix this now than it will to do so later.
Upvotes: 3