我需要将字符串转换为某种形式的哈希。这在JavaScript中是可能的吗?

我没有使用服务器端语言,所以我不能这样做。


当前回答

如果这对任何人都有帮助的话,我将前两个答案组合成一个更老的浏览器容忍版本,如果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();

其他回答

我基于FNV的乘法+Xor方法的快速(非常长)一行:

my_string.split('').map(v=>v.charCodeAt(0)).reduce((a,v)=>a+((a<<7)+(a<<3))^v).toString(16);

UUID v3和UUID v5实际上是给定输入字符串的散列。

UUID v3基于MD5,UUID v5基于SHA-1。

因此,最明显的选择是使用UUIDv5。

幸运的是,有一个流行的npm包,其中包括所有UUID算法。

npm install uuid

要实际生成UUIDv5,您需要一个唯一的命名空间。这个名称空间就像种子,应该是常量,以确保给定输入的输出始终相同。具有讽刺意味的是,您应该生成UUID v4作为命名空间。最简单的方法是使用一些在线工具。

一旦你有了一个名称空间,你就一切就绪了。

import { v5 as uuidv5 } from 'uuid';

const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
const hash = uuidv5('input', MY_NAMESPACE);

例如,如果输入字符串始终是URL,则可以使用一些默认名称空间。

const hashForURL = uuidv5('https://www.w3.org/', uuidv5.URL);

我尝试了将字符代码转换为十六进制字符串的简单串联。这有一个相对狭窄的目的,即只需要与服务器端交换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/

我参加派对有点晚了,但你可以使用这个模块:加密:

const crypto = require('crypto');

const SALT = '$ome$alt';

function generateHash(pass) {
  return crypto.createHmac('sha256', SALT)
    .update(pass)
    .digest('hex');
}

此函数的结果始终是64个字符的字符串;类似于:“aa54e7563b1964037849528e7ba068eb7767b1fab74a8d80fe300828b996714a”