Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 反向工程String.GetHashCode_C#_Gethashcode - Fatal编程技术网

C# 反向工程String.GetHashCode

C# 反向工程String.GetHashCode,c#,gethashcode,C#,Gethashcode,GetHashCode的行为取决于程序体系结构。因此,它将在x86中返回一个值,在x64中返回一个值。我有一个必须在x86中运行的测试应用程序,它必须预测必须在x64上运行的应用程序的哈希代码输出 下面是mscorwks中String.GetHashCode实现的反汇编 public override unsafe int GetHashCode() { fixed (char* text1 = ((char*) this)) { char* ch

GetHashCode的行为取决于程序体系结构。因此,它将在x86中返回一个值,在x64中返回一个值。我有一个必须在x86中运行的测试应用程序,它必须预测必须在x64上运行的应用程序的哈希代码输出

下面是mscorwks中String.GetHashCode实现的反汇编

public override unsafe int GetHashCode()
{
      fixed (char* text1 = ((char*) this))
      {
            char* chPtr1 = text1;
            int num1 = 0x15051505;
            int num2 = num1;
            int* numPtr1 = (int*) chPtr1;
            for (int num3 = this.Length; num3 > 0; num3 -= 4)
            {
                  num1 = (((num1 << 5) + num1) + (num1 >≫ 0x1b)) ^ numPtr1[0];
                  if (num3 <= 2)
                  {
                        break;
                  }
                  num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr1[1];
                  numPtr1 += 2;
            }
            return (num1 + (num2 * 0x5d588b65));
      }
}
public覆盖不安全的int-GetHashCode()
{
已修复(char*text1=((char*)this))
{
char*chPtr1=text1;
int num1=0x15051505;
int num2=num1;
int*numPtr1=(int*)chPtr1;
对于(int num3=此长度;num3>0;num3-=4)
{
num1=((num1≫ 0x1b))^numPtr1[0];
如果(num3 0x1b))^numPtr1[1];
numPtr1+=2;
}
返回值(num1+(num2*0x5d588b65));
}
}

任何人都可以将此函数移植到安全的实现中吗?

哈希代码不能跨平台重复,甚至不能在同一系统上多次运行同一程序你走错了路。如果你不改变方向,你的人生道路将很艰难,总有一天会以眼泪告终。


你想解决的真正问题是什么?您是否可以编写自己的哈希函数,或者作为扩展方法,或者作为包装类的
GetHashCode
实现,并改用该类?

首先,Jon是正确的;这是愚蠢的差事。我们用来“吃我们自己的狗粮”的框架的内部调试构建每天都会更改哈希算法,以防止人们构建依赖于不可靠的实现细节的系统,甚至是测试系统,这些细节在任何时候都会被记录为可能发生更改

我的建议是退后一步,问问自己为什么要尝试做这样危险的事情,而不是将一个被证明不适合仿真的系统的仿真纳入其中。这真的是一个要求吗


其次,StackOverflow是一个技术问答网站,而不是一个“免费为我做我的工作”的网站。如果你下定决心要做这件危险的事情,并且你需要一个能将不安全代码重写成同等安全代码的人,那么我建议你雇用一个能为你做到这一点的人

虽然这里给出的所有警告都是有效的,但它们不能回答问题。我遇到过这样一种情况:GetHashCode()不幸地已经被用于生产中的持久值,我别无选择,只能使用默认的.NET 2.0 32位x86(little endian)算法重新实现。我在没有不安全的情况下重新编码,如下所示,这似乎是可行的。希望这对别人有帮助

// The GetStringHashCode() extension method is equivalent to the Microsoft .NET Framework 2.0
// String.GetHashCode() method executed on 32 bit systems.
public static int GetStringHashCode(this string value)
{
    int hash1 = (5381 << 16) + 5381;
    int hash2 = hash1;

    int len = value.Length;
    int intval;
    int c0, c1;
    int i = 0;
    while (len > 0)
    {
        c0 = (int)value[i];
        c1 = (int)value[i + 1];
        intval = c0 | (c1 << 16);
        hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ intval;
        if (len <= 2)
        {
            break;
        }
        i += 2;
        c0 = (int)value[i];
        c1 = len > 3 ? (int)value[i + 1] : 0;
        intval = c0 | (c1 << 16);
        hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ intval;
        len -= 4;
        i += 2;
    }

    return hash1 + (hash2 * 1566083941);
}
//GetStringHashCode()扩展方法相当于Microsoft.NET Framework 2.0
//在32位系统上执行的String.GetHashCode()方法。
公共静态int GetStringHashCode(此字符串值)
{
int hash1=(5381 0)
{
c0=(int)值[i];
c1=(int)值[i+1];
intval=c0 |(c127))^intval;
如果(len3?(int)值[i+1]:0;
intval=c0 |(c127))^intval;
len-=4;
i+=2;
}
返回hash1+(hash2*1566083941);
}

以下内容准确地再现了.NET 4.7(可能更早)上的版本。这是由以下公式给出的哈希代码:

  • 字符串
    实例的默认值:
    “abc”.GetHashCode()
  • StringComparer.Ordinal.GetHashCode(“abc”)
  • 采用
    StringComparison.Ordinal
    枚举的各种
    String
    方法
  • System.Globalization.CompareInfo.GetStringComparer(CompareOptions.Ordinal)
通过对发布版本进行全面的JIT优化测试,这些版本的性能略优于内置的.NET代码,并且已经过大量的单元测试,以确保与
.NET
行为完全等效。请注意,x86和x64有不同的版本。你的计划通常应该包括这两个方面;在相应的代码清单下面是一个调用工具,它在运行时选择适当的版本

x86-(.NET以32位模式运行)

static unsafe int GetHashCode_x86_NET(int* p, int c)
{
    int h1, h2 = h1 = 0x15051505;

    while (c > 2)
    {
        h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++;
        h2 = ((h2 << 5) + h2 + (h2 >> 27)) ^ *p++;
        c -= 4;
    }

    if (c > 0)
        h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++;

    return h1 + (h2 * 0x5d588b65);
}
static unsafe int GetHashCode_x64_NET(Char* p)
{
    int h1, h2 = h1 = 5381;

    while (*p != 0)
    {
        h1 = ((h1 << 5) + h1) ^ *p++;

        if (*p == 0)
            break;

        h2 = ((h2 << 5) + h2) ^ *p++;
    }
    return h1 + (h2 * 0x5d588b65);
}
readonly static int _hash_sz = IntPtr.Size == 4 ? 0x2d2816fe : 0x162a16fe;

public static unsafe int GetStringHashCode(this String s)
{
    /// Note: x64 string hash ignores remainder after embedded '\0'char (unlike x86)
    if (s.Length == 0 || (IntPtr.Size == 8 && s[0] == '\0'))
        return _hash_sz;

    fixed (char* p = s)
        return IntPtr.Size == 4 ?
            GetHashCode_x86_NET((int*)p, s.Length) :
            GetHashCode_x64_NET(p);
}

您可以使用索引器访问字符串中的字符。为什么需要哈希代码匹配?不要出于任何目的存储哈希代码,因为实现可以随时更改。向下滚动至“规则:GetHashCode的使用者不能依赖它随时间或跨appdomains保持稳定”。还有“安全问题:不要使用GetHashCode”一节“标签外”也看到了我没有意识到GetHashCode是如此柔韧。所以,是的,傻瓜们的差事。我同意。很好的建议。我将继续使用一种可重复的、与体系结构无关的散列算法。Kenn:作为将来的参考,您可能会感兴趣。当你可以只看实际的、完全注释的源代码时,为什么要反汇编.NETFramework代码呢?天哪!Eric,你真的很生气:)我没意识到gethashcode是如此柔韧。所以,是的,傻瓜们的差事。我同意。很好的建议。我将继续使用可重复的、与体系结构无关的哈希算法。@Konstantin:我一点也不生气;作为我的客户,我希望Kenn成功。因此,我在声明中坚定地认为:(1)这是一个坏主意,可能会导致未来的高成本;(2)StackOverflow是一个询问事实的好地方,也是一个要求免费工作的坏地方。知道这一点的人更有可能成功地使用StackOverflow。@配置器:我不清楚。算法每天都在变化,因为算法的内部版本考虑到了当前版本号,而当前版本号每天都在变化。读取String.cs的文本让我笑了<代码>/。。。这些都是代码中的错误\n hash1^=thissembly.DailyBuildNumber只能以眼泪结束@巴卡尔: