JavaScript 的简单(非安全)哈希函数?

IT技术 javascript hash md5 sha1
2021-03-02 11:36:27

可能的重复:
从 Javascript/jQuery 中的字符串生成哈希

谁能建议一个用(浏览器兼容的)JavaScript 编写的简单(即数十行代码,而不是数百行)散列函数?理想情况下,我想要一些东西,当将字符串作为输入传递时,会产生类似于 32 个字符的十六进制字符串的东西,这是 MD5、SHA1 等的典型输出。它不必加密安全,只需合理地抵抗冲突. (我最初的用例是 URL,但我将来可能想在其他字符串上使用它。)

6个回答

我自己没有验证这一点,但您可以查看Java 的 String.hashCode() 方法的 JavaScript 实现似乎相当短。

使用这个原型,您可以简单地调用.hashCode()任何字符串,例如"some string".hashCode(),并接收数字哈希代码(更具体地说,Java 等效代码),例如 1395333309。

String.prototype.hashCode = function() {
    var hash = 0;
    if (this.length == 0) {
        return hash;
    }
    for (var i = 0; i < this.length; i++) {
        var char = this.charCodeAt(i);
        hash = ((hash<<5)-hash)+char;
        hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
}
在一行中:(字符串Array.from(str).reduce((hash, char) => 0 | (31 * hash + char.charCodeAt(0)), 0)在哪里str
2021-04-23 11:36:27
微优化:删除if (this.length == 0) {return hash}块,因为它无论如何for都是多余的(长度为正时执行,否则默认返回 0)。我错过了什么吗?
2021-05-01 11:36:27
真的很酷!唯一的一点是这种污染prototypeString与非的EcmaScript法。我会将它重写为一个独立的函数,也许将它放在您的 util 库中。
2021-05-09 11:36:27
SHA1 和 MD5 非常慢。我做了一堆比较测试,证明 Java 哈希的这种实现速度最快,并且与我尝试过的任何其他实现一样,冲突(在相对统一的数据上)很少。很短很甜。
2021-05-16 11:36:27
另一件事是它创建了一个全局变量i,因为他忘记var了循环中关键字。但这些问题很容易解决。
2021-05-19 11:36:27

有很多用JS编写的哈希函数的实现。例如:

如果你不需要安全性,你也可以使用 base64,它不是哈希函数,没有固定输出,可以简单地由用户解码,但看起来更轻量级,可以用于隐藏值:http://www。 webtoolkit.info/javascript-base64.html

字符串的 base64 编码或多或少与原始字符串的长度相同;我想要更短的东西,比如哈希。
2021-05-09 11:36:27
base64 甚至比输入还要长,顺便澄清一下。
2021-05-09 11:36:27
OP 询问非安全、非加密哈希,MD5 和 SHA-1 是旨在确保安全的加密哈希。
2021-05-13 11:36:27

简单的对象哈希器:

(function () {
    Number.prototype.toHex = function () {
        var ret = ((this<0?0x8:0)+((this >> 28) & 0x7)).toString(16) + (this & 0xfffffff).toString(16);
        while (ret.length < 8) ret = '0'+ret;
        return ret;
    };
    Object.hashCode = function hashCode(o, l) {
        l = l || 2;
        var i, c, r = [];
        for (i=0; i<l; i++)
            r.push(i*268803292);
        function stringify(o) {
            var i,r;
            if (o === null) return 'n';
            if (o === true) return 't';
            if (o === false) return 'f';
            if (o instanceof Date) return 'd:'+(0+o);
            i=typeof o;
            if (i === 'string') return 's:'+o.replace(/([\\\\;])/g,'\\$1');
            if (i === 'number') return 'n:'+o;
            if (o instanceof Function) return 'm:'+o.toString().replace(/([\\\\;])/g,'\\$1');
            if (o instanceof Array) {
                r=[];
                for (i=0; i<o.length; i++) 
                    r.push(stringify(o[i]));
                return 'a:'+r.join(';');
            }
            r=[];
            for (i in o) {
                r.push(i+':'+stringify(o[i]))
            }
            return 'o:'+r.join(';');
        }
        o = stringify(o);
        for (i=0; i<o.length; i++) {
            for (c=0; c<r.length; c++) {
                r[c] = (r[c] << 13)-(r[c] >> 19);
                r[c] += o.charCodeAt(i) << (r[c] % 24);
                r[c] = r[c] & r[c];
            }
        }
        for (i=0; i<r.length; i++) {
            r[i] = r[i].toHex();
        }
        return r.join('');
    }
}());

这里的主要内容是 stringifier,它简单地将任何对象转换为唯一的字符串。hashCode 然后在对象上运行,将字符串化对象的字符散列在一起。

对于额外的点,导出字符串化器并创建一个解析器。

2012 年 3 月。当时我无法假设 JSON 在某个浏览器中正常工作。此外,JSON 会删除函数,因此无法使用 JSON 作为字符串来对它们进行哈希处理。
2021-04-24 11:36:27
有什么理由不使用 JSON.stringify?
2021-05-10 11:36:27
// Simple but unreliable function to create string hash by Sergey.Shuchkin [t] gmail.com
// alert( strhash('http://www.w3schools.com/js/default.asp') ); // 6mn6tf7st333r2q4o134o58888888888
function strhash( str ) {
    if (str.length % 32 > 0) str += Array(33 - str.length % 32).join("z");
    var hash = '', bytes = [], i = j = k = a = 0, dict = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','1','2','3','4','5','6','7','8','9'];
    for (i = 0; i < str.length; i++ ) {
        ch = str.charCodeAt(i);
        bytes[j++] = (ch < 127) ? ch & 0xFF : 127;
    }
    var chunk_len = Math.ceil(bytes.length / 32);   
    for (i=0; i<bytes.length; i++) {
        j += bytes[i];
        k++;
        if ((k == chunk_len) || (i == bytes.length-1)) {
            a = Math.floor( j / k );
            if (a < 32)
                hash += '0';
            else if (a > 126)
                hash += 'z';
            else
                hash += dict[  Math.floor( (a-32) / 2.76) ];
            j = k = 0;
        }
    }
    return hash;
}
是的,JS 写得不好,但它似乎直接解决了 OP 的问题并提供了示例代码。谢谢!
2021-04-22 11:36:27
此脚本将使用以下变量污染全局范围:j, k, a. 这样做的原因是因为它们不是var语句的一部分,而只是被评估为 的表达式的一部分var i相反,使用var i, j, k, a; i = j = k = a = 0;.
2021-05-18 11:36:27