Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java equivalent of php pack('H*', str)

Tags:

java

string

php

EDIT

I changed $checksum = md5($someString+$bkey); to $checksum = md5($someString.$bkey);

I need to perform the following operations in Java:

$hexString = '90aa';#sample value
$bkey = pack('H*',$hexString);
$someString='qwe';#sample value
$checksum  = md5($someString.$bkey);
echo $checksum;

I can't convert hexString to bkey in Java to get the same result as php script. Except bkey everything is working properly.

If I remove bkey then:

PHP:

$someString='qwe';#sample value
$checksum  = md5($someString);
echo $checksum;

result: 76d80224611fc919a5d54f0ff9fba446

Java:

String someString = "qwe";
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        String checksum = new BigInteger(1, messageDigest.digest(someString
                .getBytes())).toString(16);
        System.out.println(checksum);

result: 76d80224611fc919a5d54f0ff9fba446

As you can see, it works

With bkey:

PHP:

$hexString = '90aa';#sample value
$bkey = pack('H*',$hexString);
$someString='qwe';#sample value
$checksum  = md5($someString.$bkey);
echo $checksum;

result: 18f5f1a9bf898131945dd9e315759fe4

Java:

public static void main(String[] args) throws NoSuchAlgorithmException {
        String hexString = "90aa";
        String bkey = hexToString(hexString);
        String someString = "qwe";
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        String input = someString + bkey;
        String checksum = new BigInteger(1, messageDigest.digest(input
                .getBytes())).toString(16);
        System.out.println(checksum);
    }
    public static String hexToString(String hex) {
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < hex.length(); i += 2) {
            String str = hex.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }

result: 44bb634dee436833dd65caa5043ffeb9

As you can see results are different.

How to convert hex String to String to get the same result?

like image 308
Mariusz Avatar asked Sep 22 '13 13:09

Mariusz


1 Answers

The problem is not actually in your Java code, but in the PHP code.

The line $checksum = md5($someString+$bkey); does not do what you think it does, it should be:

$checksum  = md5($someString . $bkey);  # use concatenate, not sum

Although, that gives abetter PHP MD5, but does not help make the Java code match the PHP

EDIT

The problem on the Java side is in the character encoding. The Java char values for the inoacked versions of 90aa are not valid unicode characters. Thus the toByteArray() ,ethods ar enot doing great things. If you treat all of the Java code at a byte level (and ignore any high-bytes in any chars in the Java), then you get the same result as the PHP:

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    String hexString = "90aa";
    byte[] bkey = hexToString(hexString);
    String someString = "qwe";
    MessageDigest messageDigest = MessageDigest.getInstance("MD5");
    byte[] input = join(stringToBytes(someString), bkey);
    String checksum = new BigInteger(1, messageDigest.digest(input)).toString(16);
    System.out.println(checksum);
    System.out.println(Charset.defaultCharset().displayName());
}

private static byte[] join(byte[] a, byte[] b) {
    // join two byte arrays
    final byte[] ret = new byte[a.length + b.length];
    System.arraycopy(a, 0, ret, 0, a.length);
    System.arraycopy(b, 0, ret, a.length, b.length);
    return ret;
}

public static byte[] hexToString(String hex) {
    // hexToString that works at a byte level, not a character level
    byte[] output = new byte[(hex.length() + 1) / 2];
    for (int i = hex.length() - 1; i >= 0; i -= 2) {
        int from = i - 1;
        if (from < 0) {
            from = 0;
        }
        String str = hex.substring(from, i + 1);
        output[i/2] = (byte)Integer.parseInt(str, 16);
    }
    return output;
}
public static byte[] stringToBytes(final String input) {
    // unlike Stirng.toByteArray(), we ignore any high-byte values of the characters.
    byte[] ret = new byte[input.length()];
    for (int i = input.length() - 1; i >=0; i--) {
        ret[i] = (byte)input.charAt(i);
    }
    return ret;
}

The above Java code produces the MD5sum 18f5f1a9bf898131945dd9e315759fe4 which is what PHP gives too

like image 64
rolfl Avatar answered Sep 22 '22 21:09

rolfl