Come posso ottenere l'hash sha1 di una stringa in node.js?


108

Sto cercando di creare un server websocket scritto in node.js

Per far funzionare il server devo ottenere l'hash SHA1 di una stringa.

Quello che devo fare è spiegato nella sezione 5.2.2 a pagina 35 dei documenti .

NOTA: Ad esempio, se il valore "Sec-WebSocket-Key" dell'intestazione "dGhlIHNhbXBsZSBub25jZQ=="nell'handshake del client fosse , il server aggiungerebbe "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"la stringa per formare la stringa "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11". Il server quindi prenderebbe l'hash SHA-1 di questa stringa, fornendo il valore 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. Questo valore viene quindi codificato in base64, per fornire il valore "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", che verrebbe restituito "Sec-WebSocket-Accept"nell'intestazione.


9
Vorrei altamente consiglia di utilizzare l'ottimo socket.io libreria, invece di installare il proprio. Non solo è stato ampiamente testato e corretto, ma supporta la maggior parte dei browser (anche quelli senza l'API WebSocket) attraverso vari metodi.
Alex Turpin

1
Un buon riferimento per i futuri visitatori: stackoverflow.com/questions/9407892/…
Damodaran

Risposte:



32

Obbligatorio: SHA1 non funziona , puoi calcolare collisioni SHA1 per 45.000 USD . Dovresti usare sha256:

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

Per rispondere alla tua domanda e creare un hash SHA1:

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

Poi:

getSHA256ofJSON('whatever')

o

getSHA256ofJSON(['whatever'])

o

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

Documenti ufficiali del nodo su crypto.createHash()


7
Buona idea. Si noti, tuttavia, che tutti gli oggetti (eccetto array e null) avranno lo stesso valore sha1sum poiché Object.toString()restituisce [object Object]per impostazione predefinita. Quindi sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1}), ecc.
maeria

sha1 (JSON.stringify ("some string")) => sha1 ("\" some string \ "") che è assolutamente non previsto e non multipiattaforma. A volte il meglio è nemico del bene.
Pierre

3
sha1 di una determinata stringa dovrebbe essere lo stesso su qualsiasi piattaforma. L'implementazione che utilizza JSON.stringify sta alterando la stringa originale e sha1sum ("abcd") restituisce f805c8fb0d5c466362ce9f0dc798bd5b3b32d512 dove chiunque si aspetterebbe 81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre

2
@ Pierre Questo è un punto eccellente. Penso che nominare la funzione sha1sumsia impreciso dato quello che hai detto - questo chiaramente fa più di quello che farebbe un normale sha1. Ho rinominato la funzione nella risposta.
mikemaccana

V'è ad oggi non noto collisione per lo standard 80-tutto l'SHA-1 secondo stackoverflow.com/a/3476791/1236215
kzahel


7

Suggerimenti per prevenire problemi (hash errato):

Ho riscontrato che NodeJS sta eseguendo l'hashing della rappresentazione UTF-8 della stringa. Altri linguaggi (come Python, PHP o PERL ...) stanno eseguendo l'hashing della stringa di byte.

Possiamo aggiungere un argomento binario per usare la stringa di byte.

const crypto = require("crypto");

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

sha1("Your text ;)");

Puoi provare con: "\ xac", "\ xd1", "\ xb9", "\ xe2", "\ xbb", "\ x93", ecc ...

Altri linguaggi (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
'binary'- Alias ​​per 'latin1' nodejs.org/api/…
Jossef Harush

1
^^ Commento estremamente importante di @JossefHarush! Se non hai specificamente bisogno di codificare il testo come latin1 prima dell'hashing (es. Esattamente per compatibilità con PHP), e c'è qualche possibilità che il tuo testo contenga simboli Unicode al di fuori dell'intervallo latin1 (es. Emoji!), Non usare binary! L'utilizzo di binaryo latin1nella codifica perderà le informazioni e aumenterà la probabilità di collisioni! Prova lo snippet sopra con questi due ad esempio: e
cbr

Tutti gli hash vengono eseguiti su dati binari. Il problema che stai riscontrando è che le altre lingue menzionate non usano UTF-8, non il contrario. Questo diventerà molto evidente una volta che proverai ad eseguire l'hashing di qualcosa al di fuori di Latin1. Nel caso di PHP in particolare, la codifica è interamente determinata dalla fonte, come il file di testo stesso per il testo hard-coded. Perl potrebbe aver bisogno di un po 'di lavoro pesante per usare UTF-8.
Ryan Hanekamp

3

Puoi usare:

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

Per l'installazione:

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

Ciao user944550, benvenuto. Si prega di considerare l'aggiunta di ulteriori informazioni.
Tiago Martins Peres 李大仁
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.