Як я можу отримати sha1 хеш рядка в node.js?


108

Я намагаюся створити сервер websocket, написаний на node.js

Для того, щоб сервер працював, мені потрібно отримати хеш-рядку 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, щоб дати значення "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", яке буде повернуто у "Sec-WebSocket-Accept"заголовку.


9
Я б дуже рекомендував використовувати відмінну бібліотеку socket.io замість того, щоб прокручувати власну. Це не тільки було випробувано та виправлено, але воно підтримує більшість браузерів (події, які не мають API WebSocket) різними методами.
Алекс Турпін

1
Хороша довідка для майбутніх відвідувачів: stackoverflow.com/questions/9407892/…
Дамодаран

Відповіді:



32

Обов’язково: SHA1 зламаний , ви можете обчислити зіткнення SHA1 за 45 000 доларів . Ви повинні використовувати 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
Гарна ідея. Однак зауважте, що всі об'єкти (крім масивів та null) матимуть однакове значення sha1sum з моменту Object.toString()повернення [object Object]за замовчуванням. Отже sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1})тощо
maerics

sha1 (JSON.stringify ("деяка рядок")) => sha1 ("\" деяка рядок \ ""), що абсолютно не очікується і не є крос-платформою. Іноді краще ворог добра.
П’єр

3
Очікується, що sha1 даного рядка буде однаковим на будь-якій платформі. Ваша реалізація з допомогою JSON.stringify змінює вихідну рядок і sha1sum ( «ABCD») дає f805c8fb0d5c466362ce9f0dc798bd5b3b32d512 , де кожен буде очікувати 81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre

2
@Pierre Це прекрасний момент. Я думаю, що іменування функції sha1sumє неточним з огляду на те, що ви сказали - це, очевидно, робить більше, ніж те, що звичайний ша1. Я перейменував функцію у відповіді.
mikemaccana

Існує на сьогоднішній день невідомо зіткнення для стандартної 80-раундовому SHA-1 в відповідно до stackoverflow.com/a/3476791/1236215
kzahel


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

Вузли:

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

1
'binary'- Псевдонім для 'latin1' nodejs.org/api/…
Йосеф Харуш

1
^^ Надзвичайно важливе зауваження там @JossefHarush! Якщо вам не потрібно кодувати текст як latin1 перед хешированием (наприклад, саме для сумісності з PHP), і є будь-який шанс, що ваш текст містить символи Unicode за межами діапазону latin1 (наприклад, emoji!), Не використовуйте binary! Використання binaryабо latin1кодування втратить інформацію та підвищить ймовірність зіткнень! Спробуйте фрагмент, описаний вище, наприклад з цими двома: а
cbr

Усі хеші робляться на двійкових даних. Проблема, яку ви відчуваєте, полягає в тому, що інші мови, які ви згадуєте, не використовують UTF-8, а не навпаки. Це стане дуже очевидним, коли ви спробуєте зробити хеш щось поза латинським1. У випадку з PHP, зокрема, кодування повністю визначається джерелом, таким як сам текстовий файл для жорстко закодованого тексту. Perl може знадобитися важкий підйом, щоб використовувати UTF-8.
Райан Ханекамп

3

Ви можете використовувати:

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

Для встановлення:

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

Привіт, користувач944550, ласкаво просимо. Просимо розглянути можливість додавання додаткової інформації.
Tiago Martins Peres 李大仁
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.