Bagaimana saya bisa mendapatkan hash sha1 dari sebuah string di node.js?

108

Saya mencoba membuat server websocket yang ditulis di node.js

Agar server bekerja, saya perlu mendapatkan hash SHA1 dari sebuah string.

Apa yang harus saya lakukan dijelaskan di Bagian 5.2.2 halaman 35 dokumen .

CATATAN: Sebagai contoh, jika nilai "Sec-WebSocket-Key" tajuk di jabat tangan klien adalah "dGhlIHNhbXBsZSBub25jZQ==", server akan menambahkan tes "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"untuk membentuk string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11". Server kemudian akan mengambil hash SHA-1 dari string ini, memberikan nilai 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. Nilai ini kemudian dikodekan base64, untuk memberikan nilai "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", yang akan dikembalikan di "Sec-WebSocket-Accept"header.

Eric
sumber
9
Saya akan sangat merekomendasikan menggunakan pustaka socket.io yang sangat baik daripada menggulung milik Anda sendiri. Ini tidak hanya telah diuji dan ditambal secara ekstensif, tetapi juga mendukung sebagian besar browser (bahkan yang tidak memiliki API WebSocket) melalui berbagai metode.
Alex Turpin
1
Referensi yang baik untuk pengunjung masa depan: stackoverflow.com/questions/9407892/…
Damodaran

Jawaban:

32

Wajib: SHA1 rusak , Anda dapat menghitung tabrakan SHA1 seharga 45.000 USD . Anda harus menggunakan sha256:

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

Untuk menjawab pertanyaan Anda dan membuat hash SHA1:

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

Kemudian:

getSHA256ofJSON('whatever')

atau

getSHA256ofJSON(['whatever'])

atau

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

Dokumen node resmi pada crypto.createHash()

mikemaccana
sumber
7
Ide bagus. Perhatikan, bagaimanapun, bahwa semua objek (kecuali array dan null) akan memiliki nilai sha1sum yang sama karena Object.toString()dikembalikan [object Object]secara default. Jadi sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1}), dll.
maerics
sha1 (JSON.stringify ("some string")) => sha1 ("\" some string \ "") yang sama sekali tidak diharapkan dan tidak lintas platform. Terkadang yang lebih baik adalah musuh kebaikan.
Pierre
3
sha1 dari string yang diberikan diharapkan sama di semua platform. Implementasi Anda menggunakan JSON.stringify mengubah string asli dan sha1sum ("abcd") memberikan f805c8fb0d5c466362ce9f0dc798bd5b3b32d512 yang diharapkan semua orang akan 81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre
2
@ Pierre Itu poin yang sangat bagus. Saya pikir penamaan fungsi sha1sumtidak akurat mengingat apa yang Anda katakan - ini jelas melakukan lebih dari apa yang dilakukan sha1 normal. Saya telah mengganti nama fungsi di jawaban.
mikemaccana
Sampai
8

Silakan baca dan pertimbangkan saran saya di komentar posting Anda. Karena itu, jika Anda masih memiliki alasan bagus untuk melakukan ini, lihat daftar modul kripto untuk Node . Ini memiliki modul untuk menangani sha1 dan base64.

Alex Turpin
sumber
7

Tips untuk mencegah masalah (hash buruk):

Saya mengalami bahwa NodeJS melakukan hashing pada representasi UTF-8 dari string tersebut. Bahasa lain (seperti Python, PHP atau PERL ...) melakukan hashing pada string byte.

Kita dapat menambahkan argumen biner untuk menggunakan string byte.

const crypto = require("crypto");

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

sha1("Your text ;)");

Anda dapat mencoba dengan: "\ xac", "\ xd1", "\ xb9", "\ xe2", "\ xbb", "\ x93", dll ...

Bahasa lain (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
A-312
sumber
1
'binary'- Alias ​​untuk 'latin1' nodejs.org/api/…
Jossef Harush
1
^^ Komentar yang sangat penting oleh @JossefHarush! Jika Anda tidak secara khusus perlu menyandikan teks sebagai latin1 sebelum melakukan hashing (mis. Tepatnya untuk kompatibilitas dengan PHP), dan ada kemungkinan teks Anda berisi simbol Unicode di luar kisaran latin1 (mis. Emoji!), Jangan gunakan binary! Menggunakan binaryatau latin1dalam penyandian akan kehilangan informasi dan meningkatkan kemungkinan tabrakan! Coba cuplikan di atas dengan dua contoh berikut: dan
cbr
Semua hash dilakukan pada data biner. Masalah yang Anda alami adalah bahasa lain yang Anda sebutkan tidak menggunakan UTF-8, bukan sebaliknya. Ini akan menjadi sangat jelas setelah Anda mencoba mencirikan sesuatu di luar Latin1. Dalam kasus PHP khususnya, pengkodean sepenuhnya ditentukan oleh sumbernya, seperti file teks itu sendiri untuk teks hard-code. Perl mungkin perlu beberapa pekerjaan berat untuk menggunakan UTF-8.
Ryan Hanekamp
3

Kamu bisa memakai:

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

Untuk menginstal:

  sudo npm install -g sha1
  npm install sha1 --save
pengguna944550
sumber
Halo pengguna944550, selamat datang. Harap pertimbangkan untuk menambahkan lebih banyak informasi.
Tiago Martins Peres 李大仁