Làm cách nào để lấy băm sha1 của một chuỗi trong node.js?


108

Tôi đang cố tạo một máy chủ websocket được viết bằng node.js

Để máy chủ hoạt động, tôi cần lấy hàm băm SHA1 của một chuỗi.

Những gì tôi phải làm được giải thích trong Phần 5.2.2 trang 35 của tài liệu .

LƯU Ý: Ví dụ: nếu giá trị của "Sec-WebSocket-Key" tiêu đề trong bắt tay của khách hàng là "dGhlIHNhbXBsZSBub25jZQ==", máy chủ sẽ nối chuỗi "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"để tạo thành chuỗi "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11". Sau đó, máy chủ sẽ lấy hàm băm SHA-1 của chuỗi này, tạo ra giá trị 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. Giá trị này sau đó được mã hóa base64, để cung cấp giá trị "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", giá trị này sẽ được trả về trong "Sec-WebSocket-Accept"tiêu đề.


9
Tôi sẽ đánh giá cao đề nghị sử dụng tuyệt vời socket.io thư viện thay vì cán của riêng bạn. Điều này không chỉ đã được thử nghiệm và vá lỗi rộng rãi mà còn hỗ trợ hầu hết các trình duyệt (trường hợp không có API WebSocket) thông qua nhiều phương pháp khác nhau.
Alex Turpin

1
Một tài liệu tham khảo tốt cho những khách truy cập trong tương lai: stackoverflow.com/questions/9407892/…
Damodaran

Câu trả lời:



32

Bắt buộc: SHA1 bị hỏng , bạn có thể tính các va chạm của SHA1 với giá 45.000 USD . Bạn nên sử dụng sha256:

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

Để trả lời câu hỏi của bạn và tạo hàm băm SHA1:

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

Sau đó:

getSHA256ofJSON('whatever')

hoặc là

getSHA256ofJSON(['whatever'])

hoặc là

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

Tài liệu về nút chính thức trên crypto.createHash()


7
Ý tưởng tốt. Tuy nhiên, lưu ý rằng tất cả các đối tượng (ngoại trừ mảng và null) sẽ có cùng giá trị sha1sum vì Object.toString()trả về [object Object]theo mặc định. Vì vậy, sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1}), v.v.
maerics

sha1 (JSON.stringify ("một số chuỗi")) => sha1 ("\" một số chuỗi \ "") hoàn toàn không được mong đợi và không phải là nền tảng chéo. Đôi khi tốt hơn là kẻ thù của tốt.
Pierre

3
sha1 của một chuỗi đã cho sẽ giống nhau trên bất kỳ nền tảng nào. Việc triển khai của bạn bằng cách sử dụng JSON.stringify đang thay đổi chuỗi gốc và sha1sum ("abcd") mang lại f805c8fb0d5c466362ce9f0dc798bd5b3b32d512 trong đó bất kỳ ai cũng mong đợi 81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre

2
@Pierre Đó là một điểm tuyệt vời. Tôi nghĩ rằng việc đặt tên cho hàm sha1sumlà không chính xác với những gì bạn đã nói - điều này rõ ràng làm được nhiều hơn những gì một sha1 bình thường sẽ làm. Tôi đã đổi tên hàm trong câu trả lời.
mikemaccana

Có đến ngày hôm nay không biết va chạm cho các tiêu chuẩn 80-vòng SHA-1 theo stackoverflow.com/a/3476791/1236215
kzahel


7

Mẹo để ngăn chặn sự cố (băm xấu):

Tôi đã trải nghiệm rằng NodeJS đang băm biểu diễn UTF-8 của chuỗi. Các ngôn ngữ khác (như Python, PHP hoặc PERL ...) đang băm chuỗi byte.

Chúng ta có thể thêm đối số nhị phân để sử dụng chuỗi byte.

const crypto = require("crypto");

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

sha1("Your text ;)");

Bạn có thể thử với: "\ xac", "\ xd1", "\ xb9", "\ xe2", "\ xbb", "\ x93", v.v.

Các ngôn ngữ khác (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'- Bí danh cho 'latin1' nodejs.org/api/…
Jossef Harush

1
^^ Nhận xét cực kỳ quan trọng ở đó bởi @JossefHarush! Nếu bạn không cần đặc biệt mã hóa văn bản dưới dạng latin1 trước khi băm (ví dụ: chính xác để tương thích với PHP) và có bất kỳ khả năng nào mà văn bản của bạn chứa các ký hiệu Unicode bên ngoài phạm vi latin1 (ví dụ: biểu tượng cảm xúc!), Đừng sử dụng binary! Sử dụng binaryhoặc latin1trong bảng mã sẽ làm mất thông tin và tăng khả năng va chạm! Hãy thử đoạn mã ở trên với hai đoạn mã này chẳng hạn:
cbr

Tất cả các băm được thực hiện trên dữ liệu nhị phân. Vấn đề bạn đang gặp phải là các ngôn ngữ khác mà bạn đề cập không sử dụng UTF-8 chứ không phải ngược lại. Điều này sẽ trở nên rất rõ ràng khi bạn cố gắng băm một thứ gì đó bên ngoài Latin1. Trong trường hợp của PHP nói riêng, mã hóa hoàn toàn được xác định bởi nguồn, chẳng hạn như chính tệp văn bản đối với văn bản được mã hóa cứng. Perl có thể cần một số công việc nặng nhọc để sử dụng UTF-8.
Ryan Hanekamp

3

Bạn có thể dùng:

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

Để cài đặt:

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

Xin chào user944550, chào mừng bạn. Vui lòng xem xét bổ sung thêm thông tin.
Tiago Martins Peres 李大仁
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.