我需要将字符串转换为某种形式的哈希。这在JavaScript中是可能的吗?
我没有使用服务器端语言,所以我不能这样做。
我需要将字符串转换为某种形式的哈希。这在JavaScript中是可能的吗?
我没有使用服务器端语言,所以我不能这样做。
当前回答
函数hashCode(str){return str.split(“”).reduce((prevHash,currVal)=>(((prevHash<<5)-previvHash)+currVal.charCodeAt(0))|0,0);}//测试console.log(“hashCode(\“Hello!\”):“,hashCode('Hello!'));
其他回答
我尝试了将字符代码转换为十六进制字符串的简单串联。这有一个相对狭窄的目的,即只需要与服务器端交换SHORT字符串(例如标题、标签)的哈希表示,因为不相关的原因,服务器端无法轻松实现接受的hashCode Java端口。显然,这里没有安全应用程序。
String.prototype.hash = function() {
var self = this, range = Array(this.length);
for(var i = 0; i < this.length; i++) {
range[i] = i;
}
return Array.prototype.map.call(range, function(i) {
return self.charCodeAt(i).toString(16);
}).join('');
}
这可以通过Undercore变得更加简洁和浏览器宽容。例子:
"Lorem Ipsum".hash()
"4c6f72656d20497073756d"
我想,如果你想以类似的方式对更大的字符串进行散列,你可以减少字符代码并对结果进行十六进制,而不是将单个字符连接在一起:
String.prototype.hashLarge = function() {
var self = this, range = Array(this.length);
for(var i = 0; i < this.length; i++) {
range[i] = i;
}
return Array.prototype.reduce.call(range, function(sum, i) {
return sum + self.charCodeAt(i);
}, 0).toString(16);
}
'One time, I hired a monkey to take notes for me in class. I would just sit back with my mind completely blank while the monkey scribbled on little pieces of paper. At the end of the week, the teacher said, "Class, I want you to write a paper using your notes." So I wrote a paper that said, "Hello! My name is Bingo! I like to climb on things! Can I have a banana? Eek, eek!" I got an F. When I told my mom about it, she said, "I told you, never trust a monkey!"'.hashLarge()
"9ce7"
当然,与此方法冲突的风险更大,尽管您可以在reduce中摆弄算法,但您希望多样化并延长哈希。
我需要一个类似的函数(但不同)来根据用户名和当前时间生成一个唯一的ish ID。因此:
window.newId = ->
# create a number based on the username
unless window.userNumber?
window.userNumber = 0
for c,i in window.MyNamespace.userName
char = window.MyNamespace.userName.charCodeAt(i)
window.MyNamespace.userNumber+=char
((window.MyNamespace.userNumber + Math.floor(Math.random() * 1e15) + new Date().getMilliseconds()).toString(36)).toUpperCase()
生产:
2DVFXJGEKL
6IZPAKFQFL
ORGOENVMG
... etc
编辑2022年7月:正如@canRau指出的那样,shortid的作者现在更喜欢nanoidhttps://github.com/ai/nanoid/
如果您想避免冲突,您可能需要使用SHA-256这样的安全散列。有几个JavaScript SHA-256实现。
我编写了测试来比较几个哈希实现,请参见https://github.com/brillout/test-javascript-hash-implementations.
或转到http://brillout.github.io/test-javascript-hash-implementations/,以运行测试。
如果这对任何人都有帮助的话,我将前两个答案组合成一个更老的浏览器容忍版本,如果reduce可用,则使用快速版本,如果不可用,则返回到esmiralha的解决方案。
/**
* @see http://stackoverflow.com/q/7616461/940217
* @return {number}
*/
String.prototype.hashCode = function(){
if (Array.prototype.reduce){
return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
}
var hash = 0;
if (this.length === 0) return hash;
for (var i = 0; i < this.length; i++) {
var character = this.charCodeAt(i);
hash = ((hash<<5)-hash)+character;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
用法如下:
var hash = "some string to be hashed".hashCode();
詹金斯一次一哈希非常好:
//Credits (modified code): Bob Jenkins (http://www.burtleburtle.net/bob/hash/doobs.html)
//See also: https://en.wikipedia.org/wiki/Jenkins_hash_function
//Takes a string of any size and returns an avalanching hash string of 8 hex characters.
function jenkinsOneAtATimeHash(keyString)
{
let hash = 0;
for (charIndex = 0; charIndex < keyString.length; ++charIndex)
{
hash += keyString.charCodeAt(charIndex);
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
//4,294,967,295 is FFFFFFFF, the maximum 32 bit unsigned integer value, used here as a mask.
return (((hash + (hash << 15)) & 4294967295) >>> 0).toString(16)
};
示例:
jenkinsOneAtATimeHash('test')
"31c25ec1"
jenkinsOneAtATimeHash('a')
"ca2e9442"
jenkinsOneAtATimeHash('0')
"6e3c5c6b"
您还可以删除末尾的.toString(16)部分以生成数字:
jenkinsOneAtATimeHash2('test')
834821825
jenkinsOneAtATimeHash2('a')
3392050242
jenkinsOneAtATimeHash2('0')
1849449579
请注意,如果您不需要对字符串或键进行哈希,而只需要凭空生成哈希,则可以使用:
window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16)
示例:
window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16)
"6ba9ea7"
window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16)
"13fe7edf"
window.crypto.getRandomValues(new Uint32Array(1))[0].toString(16)
"971ffed4"
与上面相同,您可以删除末尾的`.toString(16)部分以生成数字:
window.crypto.getRandomValues(new Uint32Array(1))[0]
1154752776
window.crypto.getRandomValues(new Uint32Array(1))[0]
3420298692
window.crypto.getRandomValues(new Uint32Array(1))[0]
1781389127
注意:您也可以使用此方法一次生成多个值,例如:
window.crypto.getRandomValues(new Uint32Array(3))
Uint32Array(3) [ 2050530949, 3280127172, 3001752815 ]