ตรงกันข้ามกับสิ่งที่คำตอบที่ได้รับการโหวตมากที่สุดที่นี่เน้นย้ำการไม่ฉีด (กล่าวคือมีหลายสตริงที่แฮชเป็นค่าเดียวกัน) ของฟังก์ชันแฮชการเข้ารหัสที่เกิดจากความแตกต่างระหว่างขนาดอินพุตขนาดใหญ่ (อาจไม่มีที่สิ้นสุด) และขนาดเอาต์พุตคงที่ไม่ได้ ประเด็นสำคัญ - จริงๆแล้วเราชอบฟังก์ชันแฮชที่การชนเหล่านั้นเกิดขึ้นน้อยที่สุด
พิจารณาฟังก์ชันนี้ (ในสัญกรณ์ PHP เป็นคำถาม):
function simple_hash($input) {
return bin2hex(substr(str_pad($input, 16), 0, 16));
}
สิ่งนี้ต่อท้ายช่องว่างบางส่วนหากสตริงสั้นเกินไปจากนั้นใช้ 16 ไบต์แรกของสตริงจากนั้นเข้ารหัสเป็นเลขฐานสิบหก มีขนาดเอาต์พุตเท่ากับแฮช MD5 (อักขระเลขฐานสิบหก 32 ตัวหรือ 16 ไบต์หากเราไม่ใส่ส่วน bin2hex)
print simple_hash("stackoverflow.com");
สิ่งนี้จะส่งออก:
737461636b6f766572666c6f772e636f6d
ฟังก์ชั่นนี้ยังมีคุณสมบัติที่ไม่ใช่การฉีดเช่นเดียวกับที่ไฮไลต์โดยคำตอบของ Cody สำหรับ MD5: เราสามารถส่งสตริงขนาดใดก็ได้ (ตราบเท่าที่มันพอดีกับคอมพิวเตอร์ของเรา) และจะส่งออกเพียง 32 หลักฐานสิบหก แน่นอนว่าไม่สามารถฉีดได้
แต่ในกรณีนี้การค้นหาสตริงที่แมปกับแฮชเดียวกันเป็นเรื่องเล็กน้อย (เพียงแค่ใช้hex2bin
กับแฮชของคุณเท่านี้ก็มีได้) หากสตริงเดิมของคุณมีความยาว 16 (ดังตัวอย่างของเรา) คุณจะได้สตริงเดิมนี้ MD5 แบบนี้ไม่ควรเป็นไปได้เลยแม้ว่าคุณจะรู้ว่าความยาวของอินพุตนั้นค่อนข้างสั้นก็ตาม (นอกเหนือจากการลองอินพุตที่เป็นไปได้ทั้งหมดจนกว่าเราจะพบสิ่งที่ตรงกันเช่นการโจมตีด้วยกำลังดุร้าย)
สมมติฐานที่สำคัญสำหรับฟังก์ชันแฮชการเข้ารหัสคือ:
- มันยากที่จะหาสตริงใด ๆ ที่สร้างแฮชที่กำหนด (ความต้านทานก่อนภาพ)
- เป็นการยากที่จะหาสตริงอื่นใดที่สร้างแฮชเหมือนกันกับสตริงที่กำหนด (ความต้านทานของภาพที่สอง)
- ยากที่จะหาคู่สายที่มีแฮชเดียวกัน (ความต้านทานการชนกัน)
เห็นได้ชัดว่าsimple_hash
ฟังก์ชั่นของฉันไม่เป็นไปตามเงื่อนไขเหล่านี้ (อันที่จริงถ้าเรา จำกัด พื้นที่อินพุตไว้ที่ "16-byte strings" ฟังก์ชันของฉันจะกลายเป็นแบบฉีดดังนั้นจึงสามารถพิสูจน์ได้ถึงความทนทานต่อภาพที่สองและความต้านทานการชนกัน)
ขณะนี้มีการโจมตีแบบชนกับ MD5 (เช่นเป็นไปได้ที่จะสร้างสตริงคู่หนึ่งแม้จะมีคำนำหน้าเหมือนกันซึ่งมีแฮชเหมือนกัน แต่ก็ไม่สามารถใช้งานได้มากนัก) ดังนั้นคุณไม่ควรใช้ MD5 สำหรับทุกสิ่งที่สำคัญ ยังไม่มีการโจมตีก่อนภาพ แต่การโจมตีจะดีขึ้น
เพื่อตอบคำถามจริง:
มันเกี่ยวกับฟังก์ชันเหล่านี้ที่ทำให้สตริงผลลัพธ์ไม่สามารถย้อนกลับได้?
สิ่งที่ MD5 (และฟังก์ชันแฮชอื่น ๆ ที่สร้างขึ้นจากโครงสร้าง Merkle-Damgard) ทำได้อย่างมีประสิทธิภาพคือการใช้อัลกอริทึมการเข้ารหัสที่มีข้อความเป็นคีย์และค่าคงที่บางส่วนเป็น "ข้อความธรรมดา" โดยใช้ไซเฟอร์เท็กซ์ที่เป็นผลลัพธ์เป็นแฮช (ก่อนหน้านั้นอินพุตจะถูกหุ้มและแยกเป็นบล็อกแต่ละบล็อกนี้ใช้เพื่อเข้ารหัสเอาต์พุตของบล็อกก่อนหน้าโดย XORed กับอินพุตเพื่อป้องกันการคำนวณย้อนกลับ)
อัลกอริธึมการเข้ารหัสสมัยใหม่ (รวมถึงที่ใช้ในฟังก์ชันแฮช) ถูกสร้างขึ้นเพื่อให้ยากต่อการกู้คืนคีย์แม้จะได้รับทั้งข้อความธรรมดาและรหัสลับ (หรือแม้กระทั่งเมื่อฝ่ายตรงข้ามเลือกหนึ่งในนั้น) พวกเขาทำสิ่งนี้โดยทั่วไปโดยทำการดำเนินการสับบิตจำนวนมากในลักษณะที่บิตเอาต์พุตแต่ละบิตถูกกำหนดโดยแต่ละคีย์บิต (หลาย ๆ ครั้ง) และบิตอินพุตแต่ละบิต ด้วยวิธีนี้คุณสามารถย้อนกลับสิ่งที่เกิดขึ้นภายในได้อย่างง่ายดายหากคุณรู้คีย์เต็มและอินพุตหรือเอาต์พุต
สำหรับฟังก์ชันแฮชแบบ MD5 และการโจมตีพรีอิมเมจ (ด้วยสตริงแฮชบล็อกเดียวเพื่อให้ง่ายขึ้น) คุณมีเพียงอินพุตและเอาต์พุตของฟังก์ชันการเข้ารหัสเท่านั้น แต่ไม่ใช่คีย์ (นี่คือสิ่งที่คุณกำลังมองหา)