从c#到Javascript的哈希函数转换存在位数学问题

Conversion of a hash function from C# to Javascript has issues with bitwise math

本文关键字:存在 问题 转换 函数 Javascript 哈希      更新时间:2023-09-26

我有以下c#哈希函数(也在SO上找到!),我在一堆应用程序中使用,涵盖几个不同的平台:

public static int GetStableHash(string s, int hashlength)
{
    uint hash = 0;
    var bytes = System.Text.Encoding.ASCII.GetBytes(s);
    foreach (byte b in bytes)
    {
        hash += b;
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
    // final avalanche
    hash += (hash << 3);
    hash ^= (hash >> 11);
    hash += (hash << 15);
    return (int)(hash % hashlength);
}

我试图将其移植到Javascript,另一个应用程序将生成匹配的哈希值。唯一的问题是JS没有int类型,并且在执行位数学之前似乎在内部将int转换为float。这会导致这个移植函数出现问题:

function getStableHash(s, hashlength)
{
    var hash = 0;
    var bytes = stringToBytes(s);   // this function just grabs a byte array for the given input string
    for (var i = 0; i < bytes.length; i++)
    {
        hash += bytes[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
    // final avalanche
    hash += (hash << 3);
    hash ^= (hash >> 11);
    hash += (hash << 15);
    return Math.round(hash % hashlength);
}

在上面的代码中,由于存在签名位,移位最终会导致问题,并且产生的哈希值与c#版本的输出不匹配。从其他各种SO帖子(例如,参见大整数的按位操作)中不清楚解决这个问题的最佳方法是什么。

已经有代码在c#和c++中使用哈希方法,所以不能在其他地方修改哈希方法来适应Javascript的缺点。

我怎么能工作围绕JS的内部类型转换?

尝试如下:

  1. 使用无符号右移>>>代替有符号的

  2. 在取模之前,使用>>> 0将最终结果转换为无符号 32位整型;

    return (hash >>> 0) % hashlength;