“char”的问题;“破折号”;在Java/Linux和.net/windows平台之间

“char”的问题;“破折号”;在Java/Linux和.net/windows平台之间,java,.net,encoding,hyphen,Java,.net,Encoding,Hyphen,这个问题会有点大,因为我会尽力提供尽可能多的信息。但是,直截了当地说,问题在于: 在客户端/发送方和服务器/接收方中计算包含“En破折号”的字符串的长度时,我们面临着一些问题。 客户端使用java/linux,服务器使用.net/windows。我们(服务器和客户端)使用字符集进行通信 在我的调查中,我发现它正被“windows”替换为a,这会导致散列发散。我怎样才能解决它 现在,一些调试信息 这是用于计算哈希的完整concat字符串: 验证电子版E12015-08-2417:38:351381

这个问题会有点大,因为我会尽力提供尽可能多的信息。但是,直截了当地说,问题在于:

在客户端/发送方和服务器/接收方中计算包含“En破折号”的字符串的长度时,我们面临着一些问题。 客户端使用java/linux,服务器使用.net/windows。我们(服务器和客户端)使用字符集进行通信

在我的调查中,我发现它正被“windows”替换为a,这会导致散列发散。我怎样才能解决它

现在,一些调试信息

这是用于计算哈希的完整concat字符串:

验证电子版E12015-08-2417:38:35138164703263053.02.0013816470 Intervalemed–集成医疗中心869612778 Nilsea MARIA MARTINS DA SILVA

我用Java做了一些测试,得到了下面的值。为了清晰起见,我将抑制该字符串:

默认编码

String default = new String("VERIFICA...D – CENTRO...A");
Sysout(default) = VERIFICA...D – CENTRO...A  // **(En Dash is present)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
来自UTF-8字节

String utf = new String("VERIFICA...D – CENTRO...A".getBytes("UTF-8"), "UTF-8");
sysout(utf) = VERIFICA...D – CENTRO...A // **(En Dash is present)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String iso = new String("VERIFICA...D – CENTRO...A".getBytes("ISO-8859-1"), "ISO-8859-1");
sysout(iso) = VERIFICA...D ? CENTRO...A // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String ascii = new String("VERIFICA...D – CENTRO...A".getBytes("ASCII"), "ASCII");
sysout(ascii) = VERIFICA...D ? CENTRO...A  // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String cp1252 = new String("VERIFICA...D – CENTRO...A".getBytes("CP1252"), "CP1252"); // Tests to predict behavior on windows platform
sysout(cp1252) = VERIFICA...D – CENTRO...A // **(En Dash IS PRESENT!!!!)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("CP1252") =     210730b031373620090b973cdb056a6f
来自ISO-8859-1字节

String utf = new String("VERIFICA...D – CENTRO...A".getBytes("UTF-8"), "UTF-8");
sysout(utf) = VERIFICA...D – CENTRO...A // **(En Dash is present)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String iso = new String("VERIFICA...D – CENTRO...A".getBytes("ISO-8859-1"), "ISO-8859-1");
sysout(iso) = VERIFICA...D ? CENTRO...A // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String ascii = new String("VERIFICA...D – CENTRO...A".getBytes("ASCII"), "ASCII");
sysout(ascii) = VERIFICA...D ? CENTRO...A  // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String cp1252 = new String("VERIFICA...D – CENTRO...A".getBytes("CP1252"), "CP1252"); // Tests to predict behavior on windows platform
sysout(cp1252) = VERIFICA...D – CENTRO...A // **(En Dash IS PRESENT!!!!)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("CP1252") =     210730b031373620090b973cdb056a6f
来自ASCII字节

String utf = new String("VERIFICA...D – CENTRO...A".getBytes("UTF-8"), "UTF-8");
sysout(utf) = VERIFICA...D – CENTRO...A // **(En Dash is present)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String iso = new String("VERIFICA...D – CENTRO...A".getBytes("ISO-8859-1"), "ISO-8859-1");
sysout(iso) = VERIFICA...D ? CENTRO...A // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String ascii = new String("VERIFICA...D – CENTRO...A".getBytes("ASCII"), "ASCII");
sysout(ascii) = VERIFICA...D ? CENTRO...A  // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String cp1252 = new String("VERIFICA...D – CENTRO...A".getBytes("CP1252"), "CP1252"); // Tests to predict behavior on windows platform
sysout(cp1252) = VERIFICA...D – CENTRO...A // **(En Dash IS PRESENT!!!!)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("CP1252") =     210730b031373620090b973cdb056a6f
来自CP1252字节

String utf = new String("VERIFICA...D – CENTRO...A".getBytes("UTF-8"), "UTF-8");
sysout(utf) = VERIFICA...D – CENTRO...A // **(En Dash is present)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String iso = new String("VERIFICA...D – CENTRO...A".getBytes("ISO-8859-1"), "ISO-8859-1");
sysout(iso) = VERIFICA...D ? CENTRO...A // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String ascii = new String("VERIFICA...D – CENTRO...A".getBytes("ASCII"), "ASCII");
sysout(ascii) = VERIFICA...D ? CENTRO...A  // **(En Dash is missing)**
md5 with getBytes("UTF-8") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
String cp1252 = new String("VERIFICA...D – CENTRO...A".getBytes("CP1252"), "CP1252"); // Tests to predict behavior on windows platform
sysout(cp1252) = VERIFICA...D – CENTRO...A // **(En Dash IS PRESENT!!!!)**
md5 with getBytes("UTF-8") =      62a06113d11099697a13771702afa8d1
md5 with getBytes("ISO-8859-1") = 0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("ASCII") =      0bf4fc8dd2d44916104a92749c881353
md5 with getBytes("CP1252") =     210730b031373620090b973cdb056a6f
我在研究中发现,“En-Dash”字符在“ISO-8859-1”字符集中不存在。这解释了在该编码上构建字符串时的问号(?)。 我还发现这个字符确实存在于cp1252/windows字符集中

不知何故,这就是客户端和服务器之间哈希不匹配的原因。但我们无法确定正在发生什么

服务器人员坚持生成的ISO-8859-1哈希应该是:96c08fb1737251d37d25dd4fdcd4524f

请注意,我尝试过的任何组合中都不会出现此哈希

深入挖掘,我发现如果用hypen(-)替换“En-Dash”,就会生成这个散列。但是,没有人明确地这样做

但服务器端的人员尝试了以下.NET代码:

var dash = "–"; // En Dash
var encoding = "iso-8859-1";
var result = System.Text.Encoding.GetEncoding(encoding).GetString(Encoding.GetEncoding(encoding).GetBytes(dash));
他们得到了和连字符

这就是他们得到96c08fb1737251d37d25dd4fdcd4524f散列的原因

发生了什么事?就像“windows”说:“我没有这么大的宣传,所以我会给你这个小的”。我在想,如果他没有找到字符,windows是否会用o替换ö

我们如何解决这个问题?我在客户那里做错什么了吗?他们在服务器上做错什么了吗

首先,他们使用下面的代码:

public static string CalculateMD5Hash(string input)
{
    byte[] buffer = new MD5CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(input));
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < buffer.Length; i++)
    {
        builder.Append(buffer[i].ToString("X2"));
    }
    return builder.ToString().ToLower();
}
publicstaticstringcalculatemd5hash(字符串输入)
{
byte[]buffer=new MD5CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(input));
StringBuilder=新的StringBuilder();
for(int i=0;i
但我建议不要使用默认编码,因为他们声称他们已经将此代码更改为硬代码“ISO-8859-1”字符集

如有任何建议,我们将不胜感激


谢谢。

它正在执行回退-看不清楚你所说的“修复这个”是什么意思,因为我不能确切地说出所需的行为是什么…然后告诉他们在计算哈希时硬编码一些可以表示Unicode的东西,比如UTF-8或UTF-16,而不是ISO-8859-1,并在Java端使用相同的东西。@JonSkeet,所需的行为,简单地说,服务器也会得到缺少的字符(问号),并且能够计算与客户端相同的散列。在两侧使用相同的替换字符的想法并不好。替换字符表示信息丢失。将来可能会得到一个字符串,其中包含许多非拉丁字符,这些字符都将被翻译成
。在这种情况下,这些字符串很有可能产生相同的md5,这是不好的。您需要使用保留信息的编码。它正在执行回退-看不清楚“修复此问题”是什么意思,因为我无法确切说出所需的行为…然后告诉他们在计算哈希时硬编码一些可以表示Unicode的内容,如UTF-8或UTF-16,而不是ISO-8859-1,在Java端使用相同的方法。@JonSkeet,理想的行为,以一种天真的方式,就是服务器也会得到缺少的字符(问号),并且能够计算与客户端相同的哈希值。在两侧使用相同的替换字符的想法并不好。替换字符表示信息丢失。将来可能会得到一个字符串,其中包含许多非拉丁字符,这些字符都将被翻译成
。在这种情况下,这些字符串很有可能产生相同的md5,这是不好的。您需要使用保留信息的编码。