我正在实现一个名为 Suomen Verkkomaksut 的数字支付服务接口(interface)。有关付款的信息通过 HTML 格式发送给他们。为确保在传输过程中没有人弄乱信息,在两端使用不发送给它们的特殊 key 计算 MD5 哈希值。
我的问题是,出于某种原因,他们似乎决定传入的数据是用 ISO-8859-1 而不是 UTF-8 编码的。我发送给他们的哈希是用 UTF-8 字符串计算的,因此它与他们计算的哈希不同。
我用下面的代码试过了:
String prehash = "6pKF4jkv97zmqBJ3ZL8gUw5DfT2NMQ|13466|123456||Testitilaus|EUR|http://www.esimerkki.fi/success|http://www.esimerkki.fi/cancel|http://www.esimerkki.fi/notify|5.1|fi_FI|0412345678|0412345678|esimerkki@esimerkki.fi|Matti|Meikäläinen||Testikatu 1|40500|Jyväskylä|FI|1|2|Tuote #101|101|1|10.00|22.00|0|1|Tuote #202|202|2|8.50|22.00|0|1";
String prehashIso = new String(prehash.getBytes("ISO-8859-1"), "ISO-8859-1");
String hash = Crypt.md5sum(prehash).toUpperCase();
String hashIso = Crypt.md5sum(prehashIso).toUpperCase();
不幸的是,这两个哈希值与值 C83CF67455AF10913D54252737F30E21 相同。根据 Suomen Verkkomaksut 的文档,此示例案例的正确值为 975816A41B9EB79B18B3B4526569640E。
有没有办法在 Java 中使用 ISO-8859-1 字符串计算 MD5 哈希值?
更新:在等待 Suomen Verkkomaksut 的答复时,我找到了另一种制作哈希的方法。 Michael Borgwardt 纠正了我对字符串和编码的理解,我寻找了一种从 byte[] 生成散列的方法。
Apache Commons 是一个很好的库来源,我发现他们的 DigestUtils 类有一个 md5hex 函数,它接受 byte[] 输入并返回一个 32 个字符的十六进制字符串。
出于某种原因,这仍然不起作用。这两个都返回相同的值:
DigestUtils.md5Hex(prehash.getBytes());
DigestUtils.md5Hex(prehash.getBytes("ISO-8859-1"));
最佳答案
您似乎误解了字符串编码的工作原理,并且您的 Crypt
类的 API 值得怀疑。
字符串实际上并没有“编码”——编码是您用来在字符串和字节之间进行转换的。
Java 字符串在内部存储为 UTF-16,但这并不重要,因为 MD5 适用于字节,而不适用于字符串。您的 Crypt.md5sum()
方法必须首先将传递给它的字符串转换为字节 - 它使用什么编码来做到这一点?这可能是您问题的根源。
您的示例代码非常荒谬,因为这一行的唯一效果是:
String prehashIso = new String(prehash.getBytes("ISO-8859-1"), "ISO-8859-1");
是用问号代替ISO-8859-1不能表示的字符。
关于java - Java 中 ISO-8859-1 字符串的 MD5 哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1839003/