lucka
lucka

Reputation: 13

Generate MD5 String in java

i try to ganerate md5 string in java.I wrote some code an i can ganerate md5 string,but i have problem first time i show you my code

public class MD5Hash
{

    public static void main(String args[])
    {

        computeMD5Hash("dbox#service" + "2014-12-24T18:34:49");
    }

    public static void computeMD5Hash(String password)
    {
        try
        {
            // Create MD5 Hash
            MessageDigest digest = java.security.MessageDigest.getInstance("MD5");

            digest.update(password.getBytes("UTF-16"));
            digest.update(password.getBytes());

            byte messageDigest[] = digest.digest();
            StringBuffer MD5Hash = new StringBuffer();

            for (int i = 0; i < messageDigest.length; i++)
            {
                String h = Integer.toHexString(0xFF & messageDigest[i]);

                while (h.length() < 2)
                    h = "0" + h;

                MD5Hash.append(h);
            }

            // result.setText("MD5 hash generated is: " + " " + MD5Hash);
            System.out.println("MD5 hash generated is: " + " " + MD5Hash);

        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
    }
}

as i said i can recive md5 string but my friend is .net developer and he also wrote code and my md5 string is different .this is a his C# code

 public static string CreateMD5(string plain)
 {
     MD5 md5 = MD5.Create();
     byte[] inputBytes = Encoding.Unicode.GetBytes(plain);
     byte[] hashBytes = md5.ComputeHash(inputBytes);
     StringBuilder sb = new StringBuilder();

    for (int i = 0; i < hashBytes.Length; i++)
    {
        sb.Append(hashBytes[i].ToString("x2"));
    }

    return sb.ToString();
}

somethink is a wrong in my Java code because i want my Md5 string to send server and when i send my md5 string to server i have error -my friend has not... what is a wrong in my code if anyone knows solution please help me thanks

Upvotes: 1

Views: 3304

Answers (2)

Christian Hujer
Christian Hujer

Reputation: 17935

Reason for the difference: Encoding

The difference between the programs is in the encoding used to convert the characters of the String into bytes.

C# program used UTF-16LE

Your friend's C# program is using Encoding.Unicode.GetBytes() which defaults to UTF-16LE and thus produces ea15fbcf2123906e6fcb9f2a3b243492.

Java program used something else

Your Java program is using String.getBytes() which defaults to your current Locale's encoding (probably something like UTF-8 or Windows-1252, but obviously something which is backwards compatible to US-ASCII-7) and thus produces 70F00E5BD872BD73EC6A8B4B8C8C9FEF.

Agree on something

You have to decide which encoding actually should be used. I'd say that for such use cases, using UTF-8 is most common and suggest that you both agree on UTF-8. But no matter what, you need to agree on something.

How to use a specific encoding like UTF-8 or UTF-16LE in Java

Replace the line

digest.update(password.getBytes());

with

digest.update(password.getBytes(StandardCharsets.UTF_16LE));

or

digest.update(password.getBytes(StandardCharsets.UTF_8));

You can also use charsets beyond those defined in StandardCharsets. In that case you need to use the String argument version of String.getBytes() and deal with UnsupportedEncodingException, like this:

try {
    digest.update(password.getBytes("ISO-8859-15"));
} catch (final UnsupportedEncodingException e) {
    throw new AssertionError(e);
}

Nicer version of the program

  • Use varargs for main() so it can be called with Md5Sum.main() instead of Md5Sum.main(new String[0]); when testing it.
  • Refactored print into return.
  • Use a Formatter for converting bytes to hex String because it's far more convenient: It uses a StringBuilder which is faster than a StringBuffer, and it offers a format() method which makes the conversion much simpler.
  • Make variables final because we intend to never reassign them.
  • Replace for-loop with foreach-loop because we don't use the index variable.
  • Instead of printing the stack trace and continuing, we say we expect MD5 to be available, and if it is not, it is an internal error of our program and abort. A crashed program causes less damage than a crippled one.
public class Md5Sum {
    public static void main(final String... args) {
        final String md5sum = md5sum("dbox#service" + "2014-12-24T18:34:49");
        System.out.println("MD5 hash generated is: " + md5sum);
    }
    public static String md5sum2(final String plaintext) {
        try {
            final Formatter formatter = new Formatter();
            final MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(plaintext.getBytes(StandardCharsets.UTF_16LE));
            for (final byte b : digest.digest())
                formatter.format("%02x", b);
            return formatter.toString();
        } catch (final NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        }
    }
}

Even nicer version of the program

  • Split the function into multiple functions so that they can be used (tested, reused) separately.
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;

import static java.nio.charset.StandardCharsets.UTF_16LE;

public class Md5Sum {
    public static void main(final String... args) {
        final String md5sum = md5sum("dbox#service" + "2014-12-24T18:34:49");
        System.out.println("MD5 hash generated is: " + md5sum);
    }

    public static String md5sum(final String plaintext) {
        return toHexString(md5sum(plaintext.getBytes(UTF_16LE)));
    }

    private static byte[] md5sum(final byte... bytes) {
        final MessageDigest digest = createMD5();
        digest.update(bytes);
        return digest.digest();
    }

    private static MessageDigest createMD5() {
        try {
            return MessageDigest.getInstance("MD5");
        } catch (final NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        }
    }

    private static String toHexString(final byte... bytes) {
        final Formatter formatter = new Formatter();
        for (final byte b : bytes)
            formatter.format("%02X", b);
        return formatter.toString();
    }
}

Upvotes: 2

lonewasp
lonewasp

Reputation: 106

On C# sample Encoding.Unicode gives you UTF-16 string to pass to digest, while on Java side UTF-8 string is passed to digest.

Upvotes: 1

Related Questions