【问题标题】:Java equivalent of php pack('H*', str)Java 等价于 php pack('H*', str)
【发布时间】:2013-09-22 23:50:28
【问题描述】:

编辑

我将$checksum = md5($someString+$bkey); 更改为$checksum = md5($someString.$bkey);

我需要在 Java 中执行以下操作:

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

我无法在 Java 中将 hexString 转换为 bkey 以获得与 php 脚本相同的结果。除了bkey 一切正常。

如果我删除 bkey 那么:

PHP:

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

结果: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);

结果:76d80224611fc919a5d54f0ff9fba446

如您所见,它有效

与bkey:

PHP:

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

结果: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();
    }

结果:44bb634dee436833dd65caa5043ffeb9

如您所见,结果不同。

如何将hex String 转换为String 以获得相同的结果?

【问题讨论】:

  • @Joni 它也给出了不同的结果,所以它不是重复的。
  • String.getBytes() 的输出取决于默认字符集。您应该直接处理字节数组。
  • @nwellnhof 你是什么意思?如果作为 md5 的输入,我使用 byte[] result=ArrayUtils.addAll(someString.getBytes(), bkey); ,其中 bkey 是字节数组,那么我也会得到错误的结果。为了计算bkey,我使用了 Joni 评论中的Convert a string representation of a hex dump to a byte array using Java?
  • 不,您首先将十六进制字符串转换为另一个字符串,然后再转换为字节数组。尝试将其直接转换为字节数组,如另一个问题中所述。

标签: java php string


【解决方案1】:

问题实际上不在于您的 Java 代码,而在于 PHP 代码。

$checksum = md5($someString+$bkey); 行并没有像你认为的那样做,应该是:

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

虽然,这提供了更好的 PHP MD5,但无助于使 Java 代码与 PHP 匹配

编辑

Java 方面的问题在于字符编码。 90aa 的 inoacked 版本的 Java char 值不是有效的 unicode 字符。因此 toByteArray() 方法并没有做伟大的事情。如果您在字节级别处理所有 Java 代码(并忽略 Java 中任何字符中的任何高字节),那么您将获得与 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;
}

上面的 Java 代码生成 MD5sum 18f5f1a9bf898131945dd9e315759fe4,这也是 PHP 提供的

【讨论】:

  • 非常感谢,您的评论很重要。
  • 这个答案不完整,所以我不能接受。如果您可以编辑您的答案,我应该使用 nwellnhof 的评论,那么我会接受您的答案。
  • 是的,这个问题让我很感兴趣……我不是 PHP 程序员,所以我把它作为一个学习练习……结果现在匹配
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 2011-10-12
  • 1970-01-01
  • 2011-09-04
相关资源
最近更新 更多