ไทย

เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ · SHA เครื่องคำนวณแฮช

ข้อความเดียวกัน SHA-256 ต่างกัน: การขึ้นบรรทัดใหม่ การเข้ารหัส และไบต์ที่ซ่อนอยู่

· มันทำงานอย่างไร

sha-256 การเข้ารหัส การประมวลผลข้อความ การดีบัก

อินพุตข้อความที่ดูเหมือนกันสองรายการซึ่งสร้างส่วนย่อย SHA-256 ที่แตกต่างกัน โดยเน้นบรรทัดใหม่ที่ซ่อนอยู่และไบต์การเข้ารหัส
ภาพประกอบเวกเตอร์ต้นฉบับ ToolAcre

บรรทัดคำสั่งพูดสิ่งหนึ่งและเบราว์เซอร์พูดอีกอย่างหนึ่งสำหรับสิ่งที่ดูเหมือนข้อความเดียวกัน การขึ้นบรรทัดใหม่ต่อท้าย UTF-16 และ CRLF อธิบายเกือบทุกกรณี โพสต์นี้จะแสดงวิธีการค้นหาไบต์ที่ซ่อนอยู่

echo บอกว่าแฮชอันหนึ่ง เครื่องมือบอกอีกอัน - ความไม่ตรงกันในชีวิตประจำวันและเหตุใดจึงไม่ผิด

เทอร์มินัลรายงานการแยกย่อย SHA-256 หนึ่งรายการ และเบราว์เซอร์รายงานอีกรายการหนึ่งสำหรับสิ่งที่ดูเหมือนจะเป็นข้อความที่เหมือนกัน เครื่องมือบรรทัดคำสั่งไม่ได้เสียหาย และเบราว์เซอร์ก็ไม่ได้เช่นกัน ไบต์ที่ถูกแฮชไม่เหมือนกัน แม้ว่าอักขระที่มองเห็นจะดูเหมือนกันก็ตาม โพสต์นี้จะติดตามแหล่งที่มาที่พบบ่อยที่สุดของไบต์ที่ซ่อนอยู่เหล่านั้น และแสดงวิธีการค้นหาด้วยช่องข้อความและโปรแกรมดูเลขฐานสิบหก

ปัญหาแทบไม่เคยเกิดจากอัลกอริทึม SHA-256 เลย SHA-256 ถูกกำหนดไว้: ไบต์เดียวกันจะสร้างไดเจสต์เดียวกันเสมอ และการไดเจสต์นั้นถูกต้อง เมื่อเอาต์พุตต่างกัน ไบต์จะต่างกัน ความสับสนเกิดขึ้นเนื่องจาก "ข้อความเดียวกัน" มีความคลุมเครือ: บุคคลเห็นอักขระ แต่ฟังก์ชันแฮชมองเห็นไบต์ และการแปลระหว่างอักขระเหล่านั้นคือจุดที่ความแตกต่างที่ซ่อนอยู่ซ่อนอยู่

การขึ้นบรรทัดใหม่ต่อท้าย - echo ผนวกไบต์อย่างไรและ printf ไม่มี และสิ่งที่ส่งผลต่อการแยกย่อย

คำสั่ง echo ในเชลล์จะเพิ่มอักขระขึ้นบรรทัดใหม่ (U+000A, ไบต์ 0x0A) ต่อท้ายเอาต์พุต นี่คือการออกแบบ: แบบแผนใน Unix ที่ไฟล์ข้อความลงท้ายด้วยการขึ้นบรรทัดใหม่ทำให้สะท้อนงานง่ายๆ อย่างหนึ่ง เมื่อคุณพิมพ์ echo abc ลงในเทอร์มินัลแล้วไพพ์ไปที่ sha256sum ไบต์ที่แยกย่อยจะเป็น 61 62 63 0A (ที่ ASCII รหัสสำหรับ a, b, c และไบต์สำหรับการขึ้นบรรทัดใหม่) ไม่ใช่ 61 62 63. เครื่องมือ ToolAcre ใช้ในการคำนวณแฮชแฮชไบต์ 61 62 63 และให้ผลลัพธ์ที่แตกต่างออกไป

คำสั่ง printf จะไม่เพิ่มบรรทัดใหม่ เว้นแต่คุณจะเขียนบรรทัดใหม่ลงในสตริงรูปแบบ printf abc | sha256sum คำนวณการแยกย่อยของไบต์ 61 62 63 เพียงอย่างเดียว ซึ่งตรงกับเครื่องมือเบราว์เซอร์ นี่คือสาเหตุที่การเปรียบเทียบแฮชมักหมายถึงการรัน printf แทน echo หรือการไพพ์ไปที่ sha256sum ด้วยแฟล็ก -z หรือระบุอินพุตดิบในรูปแบบใดก็ตามที่เครื่องมือของคุณมีให้ การขึ้นบรรทัดใหม่ที่ซ่อนอยู่เป็นสาเหตุเดียวที่พบบ่อยที่สุดที่เครื่องมือเบราว์เซอร์และเครื่องมือบรรทัดคำสั่งไม่เห็นด้วย

UTF-8 กับ UTF-16 — เหตุใดอักขระเดียวกันจึงมีไบต์ที่แตกต่างกันในเชลล์และตัวแก้ไขบางตัว

UTF-8 และ UTF-16 เข้ารหัสอักขระเดียวกันกับลำดับไบต์ที่แตกต่างกัน อักขระ é (U+00E9 ซึ่งเป็น e ที่มีสำเนียงเฉียบพลัน) เข้ารหัสเป็น UTF-8 สองไบต์: 0xC3 0xA9 ใน UTF-16 ซึ่งเป็นวิธีที่ JavaScript แทนสตริงภายใน อักขระเดียวกันจะใช้พื้นที่สองไบต์ในลำดับที่แตกต่างกัน (ขึ้นอยู่กับความเป็นเอนเดียน) หรือรูปแบบอื่นทั้งหมดหากประกอบด้วยอักขระฐานและเครื่องหมายรวม เมื่อคุณคัดลอก cafe จากแอพพลิเคชั่น Windows และวางลงในเครื่องมือแฮชของเบราว์เซอร์ ไบต์ของแฮชของเครื่องมืออาจไม่ตรงกับแฮชของเทอร์มินัล Mac เนื่องจากระบบมีค่าเริ่มต้นเป็นการเข้ารหัสหรือรูปแบบการทำให้เป็นมาตรฐานที่แตกต่างกัน

เครื่องมือแฮช ToolAcre แปลงข้อความเป็น UTF-8 อย่างชัดเจนก่อนที่จะแฮชผ่าน TextEncoder นี่เป็นการเข้ารหัสเดียวกับที่บรรทัดคำสั่ง Unix ใช้เป็นค่าเริ่มต้น ซอร์สโค้ดใน apps/dev/src/lib/base64.js แสดงฟังก์ชัน textToBytes ที่เรียกใช้ TextEncoder().encode() ใหม่ ซึ่งรับประกัน UTF-8 หากระบบอื่นใช้ UTF-16 หรือ Latin-1 หรือการเข้ารหัสอื่นใด ไบต์ที่สร้างขึ้นจะแตกต่างออกไป เครื่องมือนี้จะแสดงจำนวนไบต์ควบคู่ไปกับไดเจสต์ ซึ่งเป็นสาเหตุที่การวางคาเฟ่และการเปรียบเทียบกับแฮชบรรทัดคำสั่งจะแสดงจำนวนไบต์ที่แตกต่างกันหากการเข้ารหัสแยกจากกัน

CRLF, BOM และการทำให้เป็นมาตรฐาน - การสิ้นสุดบรรทัด เครื่องหมายลำดับไบต์ และสำเนียงที่ประกอบด้วยและแบบแยกส่วนเป็นความแตกต่างของอินพุตที่มองไม่เห็น

CRLF (การขึ้นบรรทัดใหม่ + การป้อนบรรทัด, ไบต์ 0x0D 0x0A) เป็นรูปแบบการสิ้นสุดบรรทัดบน Windows LF (การป้อนบรรทัดเพียงอย่างเดียว ไบต์ 0x0A) เป็นรูปแบบ Unix ไฟล์ข้อความที่ดูเหมือนกันเมื่อเปิดในโปรแกรมแก้ไขข้อความสามารถลงท้ายบรรทัดได้ต่างกัน และไบต์เหล่านั้นเป็นส่วนหนึ่งของอินพุตของแฮช ไฟล์ที่แก้ไขบน Windows และตรวจสอบกับ SHA-256 ที่คำนวณบนระบบ Unix จะไม่ตรงกันหากระบบหนึ่งได้แปลงการสิ้นสุดบรรทัดและอีกระบบหนึ่งไม่ได้แปลง

เครื่องหมายลำดับไบต์ (BOM, ไบต์ 0xEF 0xBB 0xBF สำหรับ UTF-8) เป็นลำดับทางเลือกที่จุดเริ่มต้นของไฟล์ที่ส่งสัญญาณการเข้ารหัส บรรณาธิการบางคนเสริม; เครื่องมือบางอย่างถอดมันออก บางคนเพิกเฉยต่อมัน หากไฟล์มี BOM และคุณแฮชไฟล์แบบไบต์ต่อไบต์ ไบต์ BOM จะเป็นส่วนหนึ่งของการแยกย่อย จากนั้น หากคุณคัดลอกข้อความที่มองเห็นได้ (ซึ่งผู้ดูซ่อน BOM จาก) ลงในเครื่องมือที่ไม่เพิ่ม BOM การสรุปข้อมูลจะไม่ตรงกัน แบบฟอร์มการทำให้ข้อความเป็นมาตรฐาน (NFD เทียบกับ NFC สำหรับสำเนียงที่เรียบเรียงและแยกย่อย) เพิ่มอีกเลเยอร์: ตัวอักษรที่มีการเน้นเสียงเดียวกันสามารถแสดงเป็นอักขระที่เรียบเรียงไว้ล่วงหน้าตัวเดียวหรือเป็นอักขระฐานตามด้วยสำเนียงแบบรวม และลำดับไบต์จะแตกต่างกัน

ตัวอย่างการทำงาน - หนึ่งสตริงถูกแฮชโดยมีและไม่มีบรรทัดใหม่ จากนั้นมีการเข้ารหัสสองครั้ง โดยแสดงความแตกต่างแต่ละไบต์

วิธีการวินิจฉัยที่หนึ่ง: ใช้เครื่องมือการถ่ายโอนข้อมูลฐานสิบหกหรือตัวแปลงออนไลน์เพื่อดูว่าเครื่องมือของคุณทำงานบนไบต์ใด วางข้อความลงในตัวเข้ารหัส base64 เข้ารหัส แล้วคุณจะได้บันทึกข้อความของไบต์ จากนั้นถอดรหัส base64 บนบรรทัดคำสั่งด้วย base64 -d และไพพ์ไปที่ od -A x -t x1z เพื่อดูลำดับไบต์ฐานสิบหก หากไบต์ตรงกัน แสดงว่าอัลกอริทึมถูกต้อง ถ้าไม่เช่นนั้นก็จะมองเห็นความแตกต่างได้

วิธีการวินิจฉัยที่สอง: ใช้เครื่องคำนวณแฮช ToolAcre SHA เพื่อแฮชอินพุตที่ยาวขึ้นเรื่อยๆ โดยเริ่มจากอักขระตัวเดียว เพิ่มบรรทัดใหม่ (ซึ่งหมายถึงการพิมพ์ Enter ในกล่องข้อความ) เพิ่มช่องว่าง เพิ่มข้อความเดียวกันด้วย UTF-16 Escape Sequence หากอินพุตมาจากแหล่งที่ไม่ใช่ ASCII ดูการเปลี่ยนแปลงสรุปเมื่อมีการเพิ่มแต่ละครั้ง จำนวนไบต์ที่แสดงอยู่ข้างไดเจสต์จะบอกคุณว่าเครื่องมือกำลังแฮชจำนวนกี่ไบต์ ซึ่งทำให้การค้นหาแคบลงอย่างมาก

ตัวพิมพ์ฐานสิบหกและช่องว่างในเอาต์พุต — ความแตกต่างที่เป็นเพียงความสวยงามเท่านั้น

การแสดงเลขฐานสิบหกของการแยกย่อยไม่คำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ ตัวอักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กแสดงถึงไบต์เดียวกัน: A = 10, a = 10 เครื่องมือบางตัวปล่อยตัวพิมพ์ใหญ่, ตัวพิมพ์เล็กบางตัว, บางตัวอนุญาตเช่นกัน ถ้าไดเจสต์ตัวหนึ่งเป็นตัวพิมพ์เล็กและอีกตัวเป็นตัวพิมพ์ใหญ่ จะเป็นไดเจสต์เดียวกัน ช่องว่างในจอแสดงผลสรุปเป็นเพียงการตกแต่งเท่านั้น ข้อมูลสรุปที่แสดงเป็น ba78 16bf กับ ba7816bf จะเหมือนกัน พื้นที่เป็นเพียงตัวเลือกการจัดรูปแบบ ความไม่ตรงกันที่เกิดจากตัวพิมพ์เล็กและตัวพิมพ์ใหญ่นั้นไม่ใช่ความไม่ตรงกันที่แท้จริง

ความแตกต่างในการจัดรูปแบบความกว้างคงที่จะมองไม่เห็นในระดับไบต์เช่นกัน ข้อมูลสรุปที่แสดงด้วยยัติภังค์ ช่องว่าง หรือโคลอน (เช่น ba-78-16-bf) เป็นรูปแบบการจัดรูปแบบที่ช่วยให้มนุษย์อ่านได้ง่ายขึ้น ไม่ใช่การเปลี่ยนแปลงไบต์จริง เครื่องมือ ToolAcre จะส่งเสียงตัวพิมพ์เล็กโดยไม่มีตัวคั่น ซึ่งเป็นรูปแบบที่เครื่องมือบรรทัดคำสั่งส่วนใหญ่พิมพ์ หากคุณกำลังเปรียบเทียบกับเครื่องมือที่ส่งเสียงต่างกัน ให้แปลงเป็นตัวแทนเดียวกันก่อน

สิ่งนี้ไม่ครอบคลุมถึง — ไฟล์แฮช ซึ่งใช้หลักการเดียวกันแต่ไบต์มาจากดิสก์แทนที่จะเป็นช่องข้อความ

เครื่องคำนวณแฮช ToolAcre SHA ทำการแปลง UTF-8 ก่อนที่จะแฮช แสดงจำนวนไบต์อินพุต และเสนอรูปแบบเอาต์พุตฐาน 64 และเลขฐานสิบหก ไฟล์ต้นฉบับ apps/dev/src/lib/hash.js แสดงฟังก์ชัน hashText ที่เรียก digestBytes ซึ่งส่ง bytes.slice().buffer ไปยัง crypto.subtle.digest ความคิดเห็นในไฟล์นั้นระบุไว้อย่างชัดเจนว่าขั้นตอน UTF-8 นั้นเป็นไปโดยเจตนา และสังเกตความแตกต่างระหว่างการเข้ารหัสที่แตกต่างกัน การทดสอบอินพุตของคุณกับเวกเตอร์ที่รู้จัก (แฮช abc ถึง ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad ในฐานสิบหก) จะถือว่าเครื่องมือเบราว์เซอร์ทำงานอย่างถูกต้อง ค่าเบี่ยงเบนใด ๆ ชี้ไปที่ความแตกต่างของไบต์ในอินพุต

การแฮชไฟล์เป็นไปตามหลักการเดียวกัน ไบต์ในไฟล์มีความสำคัญ: ความแตกต่างในการสิ้นสุดบรรทัดเมื่อคุณส่งออกจากระบบหนึ่งแล้วนำเข้าไปยังอีกระบบหนึ่งสามารถเปลี่ยนการสรุปข้อมูลทุกครั้งได้ เครื่องมือบางอย่างมีตัวเลือกในการจัดการการสิ้นสุดบรรทัดระหว่างการเปรียบเทียบ คนอื่นแฮชไฟล์ตามที่เป็นอยู่ การรู้ว่าเครื่องมือของคุณแฮชไฟล์เป็นไบนารี่หรือทำการปรับมาตรฐานข้อความก่อนนั้นถือเป็นสิ่งสำคัญสำหรับความสามารถในการทำซ้ำ

ประเด็นสำคัญ: ไบต์แฮช ไม่ใช่ข้อความ — เครื่องคำนวณแฮช ToolAcre SHA แฮชไบต์ที่คุณวาง ดังนั้นให้ตรวจสอบสิ่งที่คุณวางก่อน

การเปรียบเทียบและการตรวจสอบจะทำงานเฉพาะเมื่อคุณแฮชไบต์เดียวกันเท่านั้น เริ่มต้นด้วยการยืนยันว่าคุณกำลังแฮชอินพุตเดียวกันทุกประการ: เรียกใช้ echo -n (หรือ printf) แทน echo เพื่อหลีกเลี่ยงการขึ้นบรรทัดใหม่ ระบุการเข้ารหัส UTF-8 อย่างชัดเจนหากเครื่องมือของคุณอนุญาต ตรวจสอบว่า CRLF ไม่ได้ถูกแทรกโดยโปรแกรมแก้ไขหรือยูทิลิตีระบบ จากนั้นแฮชด้วยเครื่องคิดเลข ToolAcre และเครื่องมือบรรทัดคำสั่งเคียงข้างกัน หากการย่อยตรงกัน ไบต์จะเหมือนกัน หากไม่เป็นเช่นนั้น ให้ใช้จอแสดงผลจำนวนไบต์และวิธีการดัมพ์ฐานสิบหกเพื่อค้นหาความแตกต่างที่ซ่อนอยู่

เมื่อคุณเข้าใจว่าไบต์แยกจากกันตรงไหน คุณสามารถเลือกได้ว่าจะทำให้ไบต์เหล่านั้นเป็นมาตรฐานสำหรับการเปรียบเทียบหรือไม่ เช็คซัมบางอย่างมีไว้เพื่อตรวจสอบความสมบูรณ์ของไฟล์ทุกประการตามที่มีอยู่ในดิสก์ ซึ่งในกรณีนี้คือเป้าหมายของการแฮชแบบไบต์ต่อไบต์ ส่วนอื่นๆ มีไว้เพื่อตรวจสอบว่าเนื้อหาที่มองเห็นนั้นเหมือนกัน ซึ่งในกรณีนี้การปรับการสิ้นสุดบรรทัดและการเข้ารหัสให้เป็นมาตรฐานนั้นถูกต้อง ไม่มีอะไรผิด พวกเขาตอบคำถามที่แตกต่างกัน อัลกอริทึม SHA-256 นั้นถูกต้องเสมอ คำถามคือว่าคุณขอให้แฮชอินพุตเดียวกันในทั้งสองกรณีหรือไม่