JavaScript的简单(非安全)哈希函数? [复制]

Posted

技术标签:

【中文标题】JavaScript的简单(非安全)哈希函数? [复制]【英文标题】:Simple (non-secure) hash function for JavaScript? [duplicate] 【发布时间】:2011-09-01 15:05:20 【问题描述】:

可能重复:Generate a Hash from string in javascript/jQuery

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

【问题讨论】:

您不想使用 sha1 有什么特别的原因吗? js中有很多这样的例子 我想将它与其他一些大约 50 行长的代码一起打包;我不希望我的哈希函数是“有趣”位的 10 倍。 我想我现在明白你的意思了。您是否有理由不能使用包含?你真的只需要使用一个文件吗? 是的,我可以,如有必要,我准备这样做,但我更希望有一些独立的东西,我可以在 github 或类似网站上作为要点发布。 Jenkins's one-at-a-time hashwindow.hashJoaat=function(b)for(var a=0,c=b.length;c--;)a+=b.charCodeAt(c),a+=a<<10,a^=a>>6;a+=a<<3;a^=a>>11;return((a+(a<<15)&4294967295)>>>0).toString(16);的实现 【参考方案1】:

我自己没有验证这一点,但你可以看看这个JavaScript implementation of Java's String.hashCode() method。看起来相当短。

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

String.prototype.hashCode = function() 
    var hash = 0;
    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;

【讨论】:

SHA1 和 MD5 慢得离谱。我做了一堆比较测试,证明 Java 哈希的这种实现是最快的,并且与我尝试的任何其他方法一样,冲突(在相对统一的数据上)很少。很短很甜。 真的很酷!唯一的问题是,这会使用非 Ecmascript 方法污染 Stringprototype。我会把它重写为一个独立的函数,也许把它放在你的 util 库中。 另外,它创建了一个全局变量i,因为他忘记了循环中的var关键字。但这些问题很容易解决。 微优化:删除 if (this.length == 0) return hash 块,因为它无论如何都是多余的(for 在长度为正时执行,否则默认返回 0)。我错过了什么吗? 一行:Array.from(str).reduce((hash, char) =&gt; 0 | (31 * hash + char.charCodeAt(0)), 0)(其中str是字符串)【参考方案2】:

用JS写的hash函数的实现有很多。例如:

SHA-1:http://www.webtoolkit.info/javascript-sha1.html SHA-256:http://www.webtoolkit.info/javascript-sha256.html MD5:http://www.webtoolkit.info/javascript-md5.html

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

【讨论】:

字符串的base64编码与原始字符串的长度或多或少相同;我想要一些更短的东西,比如哈希。 base64 比输入还要长,顺便澄清一下。【参考方案3】:

查看这些实现

http://www.movable-type.co.uk/scripts/sha1.html(SHA-1 算法) http://pajhome.org.uk/crypt/md5/(SHA-1、MD5、HMAC 等的实现)

【讨论】:

OP 询问非安全、非加密哈希,MD5 和 SHA-1 是旨在确保安全的加密哈希。【参考方案4】:

简单的对象哈希:

(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('');
    
());

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

要加分,请导出字符串化器并创建解析器。

【讨论】:

有什么理由不使用 JSON.stringify? 2012 年 3 月。当时我无法假设 JSON 在某个浏览器中正常工作。此外,JSON 丢弃了函数,因此使用 JSON 作为您的字符串化器,它们不会被散列。【参考方案5】:

看看这个MD5 implementation for JavaScript。它的 BSD 许可并且非常易于使用。示例:

md5 = hex_md5("message to digest")

【讨论】:

我发现了它,它会起作用,但我希望有更小更简单的东西。另外,“消息摘要”不是hex_md5(message)的结果吗? Yes digest 是结果,参数是你想要消化的消息 - 因此是“message to digest”。 但是无论如何你希望实现更简单?该实现是一个不到 400 行的简单 JavaScript 文件。你只想要一个函数还是什么? 这对我来说更有意义了;以前你有类似hex_md5("message_digest") = "fb6cecc85a100197ae3ad68d1f9f2886" 的东西,对吧? (找不到您的答案的修订版。) 是的,我更正了。但是您能否详细说明简单性问题:您想要一个更简单的库?【参考方案6】:
// 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;

【讨论】:

此脚本将使用以下变量污染全局范围:jka。这样做的原因是因为它们不是var 语句的一部分,而只是评估为var i 的表达式的一部分。相反,请使用var i, j, k, a; i = j = k = a = 0; 是的,JS 写得不好,但它似乎直接解决了 OP 的问题并提供了 example 代码。谢谢!

以上是关于JavaScript的简单(非安全)哈希函数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

简单(编码)安全散列函数

哈希算法是什么?非对称加密是什么?

JavaScript 哈希映射是如何实现的?

公钥、私钥、哈希、加密算法基础概念

如何设计并实现一个线程安全的 Map

简单的密码加密