ฉันจะรับแฮช sha1 ของสตริงใน node.js ได้อย่างไร


109

ฉันกำลังพยายามสร้างเซิร์ฟเวอร์ websocket ที่เขียนด้วย node.js

เพื่อให้เซิร์ฟเวอร์ทำงานได้ฉันต้องได้รับแฮช SHA1 ของสตริง

สิ่งที่ผมต้องทำคือการอธิบายในมาตรา 5.2.2 หน้า 35 ของเอกสาร

หมายเหตุ: ตัวอย่างเช่นถ้าค่าของ"Sec-WebSocket-Key" ส่วนหัวในการจับมือกันของลูกค้าเป็น"dGhlIHNhbXBsZSBub25jZQ=="เซิร์ฟเวอร์จะผนวก theString ในรูปแบบสตริง"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 ที่ยอดเยี่ยมแทนการหมุนของคุณเอง ไม่เพียง แต่ได้รับการทดสอบและแก้ไขอย่างกว้างขวาง แต่ยังรองรับเบราว์เซอร์ส่วนใหญ่ (ในกรณีที่ไม่มี WebSocket API) ด้วยวิธีการต่างๆ
Alex Turpin

1
ข้อมูลอ้างอิงที่ดีสำหรับผู้มาเยือนในอนาคต: stackoverflow.com/questions/9407892/…
Damodaran

คำตอบ:



33

บังคับ: 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 ("some string")) => sha1 ("\" some string \ "") ซึ่งเป็นสิ่งที่ไม่คาดคิดและไม่ใช่ข้ามแพลตฟอร์ม บางครั้งความดีก็เป็นศัตรูกับความดี
ปิแอร์

3
sha1 ของสตริงที่กำหนดคาดว่าจะเหมือนกันบนทุกแพลตฟอร์ม การใช้งานของคุณโดยใช้ JSON.stringify กำลังแก้ไขสตริงดั้งเดิมและ sha1sum ("abcd") ให้ f805c8fb0d5c466362ce9f0dc798bd5b3b32d512 ซึ่งใคร ๆ ก็คาดหวัง 81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre

2
@ ปิแอร์นั่นเป็นจุดที่ยอดเยี่ยม ฉันคิดว่าการตั้งชื่อฟังก์ชั่นsha1sumนั้นไม่ถูกต้องตามสิ่งที่คุณพูด - สิ่งนี้ทำได้มากกว่าที่ sha1 ปกติจะทำ ฉันเปลี่ยนชื่อฟังก์ชันในคำตอบแล้ว
mikemaccana

ณ วันนี้ยังไม่มีการชนกันของ SHA-1 มาตรฐาน 80 รอบตามstackoverflow.com/a/3476791/1236215
kzahel

8

โปรดอ่านและพิจารณาคำแนะนำของฉันในความคิดเห็นของโพสต์ของคุณ ดังที่กล่าวไว้หากคุณยังมีเหตุผลที่ดีในการทำเช่นนี้โปรดดูรายการโมดูลการเข้ารหัสลับสำหรับโหนดนี้ มีโมดูลสำหรับจัดการกับทั้ง sha1 และ base64


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/…
Jossef Harush

1
^^ คำพูดที่สำคัญมากโดย @JossefHarush! หากคุณไม่จำเป็นต้องเข้ารหัสข้อความเป็น latin1 โดยเฉพาะก่อนทำการแฮช (เช่นเพื่อให้เข้ากันได้กับ PHP) และมีโอกาสใด ๆ ก็ตามที่ข้อความของคุณมีสัญลักษณ์ Unicode นอกช่วง latin1 (เช่นอิโมจิ!) อย่าใช้binary! การใช้binaryหรือlatin1ในการเข้ารหัสจะสูญเสียข้อมูลและเพิ่มโอกาสในการชนกัน! ลองใช้ตัวอย่างข้อมูลด้านบนกับสองตัวอย่างนี้: และ
cbr

แฮชทั้งหมดทำกับข้อมูลไบนารี ปัญหาที่คุณพบคือภาษาอื่น ๆ ที่คุณพูดถึงไม่ได้ใช้ UTF-8 ไม่ใช่วิธีอื่น สิ่งนี้จะชัดเจนมากเมื่อคุณพยายามแฮชบางอย่างนอกละติน 1 ในกรณีของ PHP โดยเฉพาะการเข้ารหัสจะถูกกำหนดโดยแหล่งที่มาทั้งหมดเช่นไฟล์ข้อความสำหรับข้อความแบบฮาร์ดโค้ด Perl อาจต้องยกของหนักเพื่อใช้ UTF-8
Ryan Hanekamp

4

คุณสามารถใช้ได้:

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

สำหรับการติดตั้ง:

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

สวัสดีผู้ใช้ 944550 ยินดีต้อนรับ โปรดพิจารณาเพิ่มข้อมูลเพิ่มเติม
Tiago Martins Peres 李大仁
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.