如何在node.js中获取字符串的sha1哈希?


108

我正在尝试创建一个用node.js编写的websocket服务器

为了使服务器正常工作,我需要获取字符串的SHA1哈希。

我必须要做的是在文档的第5.2.2节第35页中进行了说明

注意:例如,如果"Sec-WebSocket-Key" 客户端握手"dGhlIHNhbXBsZSBub25jZQ=="中标头的值是,则服务器会附加字符串"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"以形成字符串"dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"。然后,服务器将采用此字符串的SHA-1哈希值,给出值0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea 然后将此值进行base64编码,以给出value "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",该值将在"Sec-WebSocket-Accept"标头中返回。


9
强烈建议您使用出色的socket.io库,而不要自己动手使用。它不仅经过了广泛的测试和修补,而且还通过各种方法支持大多数浏览器(即使没有WebSocket API的浏览器)。
亚历克斯·图尔平

1
:未来游客一个很好的参考stackoverflow.com/questions/9407892/...
达莫达伦

Answers:



32

必须:SHA1损坏,您可以计算SHA1碰撞为45,000 USD。您应该使用sha256

var getSHA256ofJSON = function(input){
    return crypto.createHash('sha256').update(JSON.stringify(input)).digest('hex')
}

要回答您的问题并进行SHA1哈希:

const INSECURE_ALGORITHM = 'sha1'
var getInsecureSHA1ofJSON = function(input){
    return crypto.createHash(INSECURE_ALGORITHM).update(JSON.stringify(input)).digest('hex')
}

然后:

getSHA256ofJSON('whatever')

要么

getSHA256ofJSON(['whatever'])

要么

getSHA256ofJSON({'this':'too'})

的官方节点文档 crypto.createHash()


7
好主意。但是请注意,由于默认情况下Object.toString()返回,因此所有对象(数组和null除外)将具有相同的sha1sum值[object Object]。所以sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1})
-maerics

sha1(JSON.stringify(“ some string”))=> sha1(“ \” some string \“”)这绝对是不期望的,并且不会跨平台。有时候,更好是好的敌人。
Pierre

3
在任何平台上,给定字符串的sha1均应相同。您使用JSON.stringify的实现会更改原始字符串,并且sha1sum(“ abcd”)给出f805c8fb0d5c466362ce9f0dc798bd5b3b32d512,有人会期望其中81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre

2
@Pierre这是一个很好的观点。我认为sha1sum给定您所说的功能命名是不准确的-这显然比常规sha1的功能要多。我已经在答案中重命名了该函数。
mikemaccana



7

防止问题的提示(错误的哈希):

我体验到NodeJS正在哈希字符串的UTF-8表示形式。其他语言(例如Python,PHP或PERL ...)正在对字节字符串进行哈希处理。

我们可以添加二进制参数来使用字节字符串。

const crypto = require("crypto");

function sha1(data) {
    return crypto.createHash("sha1").update(data, "binary").digest("hex");
}

sha1("Your text ;)");

您可以尝试使用:“ \ xac”,“ \ xd1”,“ \ xb9”,“ \ xe2”,“ \ xbb”,“ \ x93”等。

其他语言(Python,PHP等):

sha1("\xac") //39527c59247a39d18ad48b9947ea738396a3bc47

Nodejs:

sha1 = crypto.createHash("sha1").update("\xac", "binary").digest("hex") //39527c59247a39d18ad48b9947ea738396a3bc47
//without:
sha1 = crypto.createHash("sha1").update("\xac").digest("hex") //f50eb35d94f1d75480496e54f4b4a472a9148752


1
^^ @JossefHarush的那句话非常重要!如果您在哈希之前不需要特别地将文本编码为latin1(例如,完全与PHP兼容),并且您的文本中可能包含latin1范围以外的Unicode符号(例如,表情符号!),请不要使用binary!在编码中使用binarylatin1丢失信息并增加发生冲突的可能性!尝试使用上面的两个代码作为示例:
cbr

所有散列都对二进制数据进行。您遇到的问题是您提到的其他语言没有使用UTF-8,反之亦然。一旦您尝试对Latin1以外的内容进行哈希处理,这将变得非常明显。特别是在PHP的情况下,编码完全由源决定,例如用于硬编码文本的文本文件本身。Perl可能需要繁重的工作才能使用UTF-8。
Ryan Hanekamp

3

您可以使用:

  const sha1 = require('sha1');
  const crypt = sha1('Text');
  console.log(crypt);

要安装:

  sudo npm install -g sha1
  npm install sha1 --save

嗨,user944550,欢迎您。请考虑添加更多信息。
Tiago Martins Peres李大仁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.