บทช่วยสอนนี้จะสอนวิธีสร้างแฮชที่ปลอดภัยโดยใช้ฟังก์ชันในตัวจากโมดูลแฮชลิบของ Python
การทำความเข้าใจความสำคัญของการแฮชและวิธีคำนวณแฮชที่ปลอดภัยทางโปรแกรมจะมีประโยชน์ แม้ว่าคุณจะไม่ได้ทำงานในด้านการรักษาความปลอดภัยแอปพลิเคชันก็ตาม แต่ทำไม?
เมื่อทำงานในโครงการ Python คุณอาจเจอกรณีที่คุณกังวลเกี่ยวกับการจัดเก็บรหัสผ่านและข้อมูลที่ละเอียดอ่อนอื่นๆ ในฐานข้อมูลหรือไฟล์ซอร์สโค้ด ในกรณีเช่นนี้ การเรียกใช้อัลกอริทึมแฮชกับข้อมูลที่ละเอียดอ่อนจะปลอดภัยกว่าและจัดเก็บแฮชไว้แทนข้อมูล
ในคู่มือนี้ เราจะอธิบายว่าการแฮชคืออะไรและแตกต่างจากการเข้ารหัสอย่างไร เราจะพูดถึงคุณสมบัติของฟังก์ชันแฮชที่ปลอดภัยด้วย จากนั้น เราจะใช้อัลกอริธึมแฮชทั่วไปเพื่อคำนวณแฮชของข้อความธรรมดาใน Python ในการทำเช่นนี้ เราจะใช้โมดูลแฮชลิบในตัว
ทั้งหมดนี้และอื่น ๆ มาเริ่มกันเลย!
การแฮชคืออะไร?
กระบวนการของการแฮชใช้สตริงข้อความและให้เอาต์พุตที่มีความยาวคงที่ซึ่งเรียกว่าแฮช ความหมายของความยาวของแฮชเอาต์พุตสำหรับอัลกอริธึมการแฮชที่กำหนดนั้นคงที่ – โดยไม่คำนึงถึงความยาวของอินพุต แต่มันแตกต่างจากการเข้ารหัสอย่างไร?
ในการเข้ารหัส ข้อความหรือข้อความธรรมดาจะถูกเข้ารหัสโดยใช้อัลกอริทึมการเข้ารหัสที่ให้เอาต์พุตที่เข้ารหัส จากนั้นเราสามารถเรียกใช้อัลกอริทึมการถอดรหัสบนเอาต์พุตที่เข้ารหัสเพื่อรับสตริงข้อความกลับ
อย่างไรก็ตาม การแฮชทำงานแตกต่างกัน เราเพิ่งเรียนรู้ว่ากระบวนการเข้ารหัสสามารถย้อนกลับได้ โดยคุณสามารถเปลี่ยนจากข้อความที่เข้ารหัสเป็นข้อความที่ไม่ได้เข้ารหัส และในทางกลับกัน
ซึ่งแตกต่างจากการเข้ารหัส การแฮชไม่ใช่กระบวนการที่เปลี่ยนกลับไม่ได้ หมายความว่าเราไม่สามารถเปลี่ยนจากแฮชเป็นข้อความอินพุตได้
คุณสมบัติของฟังก์ชันแฮช
มาดูคุณสมบัติบางอย่างที่ฟังก์ชันแฮชควรตอบสนองอย่างรวดเร็ว:
- กำหนด: ฟังก์ชันแฮชถูกกำหนด จากข้อความ m แฮชของ m จะเท่ากันเสมอ
- Preimage Resistant: เราได้กล่าวถึงเรื่องนี้แล้วเมื่อเรากล่าวว่าการแฮชไม่ใช่การดำเนินการที่ย้อนกลับได้ คุณสมบัติการต้านทานของพรีอิมเมจระบุว่าเป็นไปไม่ได้ที่จะค้นหาข้อความ m จากเอาต์พุตแฮช
- ป้องกันการชนกัน: การค้นหาสตริงข้อความ m1 และ m2 ที่แตกต่างกันควรเป็นเรื่องยาก (หรือไม่สามารถคำนวณได้) ซึ่งแฮชของ m1 เท่ากับแฮชของ m2 คุณสมบัตินี้เรียกว่าความต้านทานการชน
- Second Preimage Resistant: หมายความว่าเมื่อได้รับข้อความ m1 และแฮช m2 ที่สอดคล้องกัน เป็นไปไม่ได้ที่จะค้นหาข้อความอื่น m2 ในลักษณะที่แฮช(m1) = แฮช(m2)
โมดูล hashlib ของ Python
โมดูล hashlib ในตัวของ Python ให้การใช้งานอัลกอริธึมการแฮชและการแยกย่อยข้อความต่างๆ รวมถึงอัลกอริทึม SHA และ MD5
หากต้องการใช้คอนสตรัคเตอร์และฟังก์ชันในตัวจากโมดูล Python hashlib คุณสามารถอิมพอร์ตเข้าสู่สภาพแวดล้อมการทำงานได้ดังนี้:
import hashlib
โมดูล hashlib จัดเตรียมอัลกอริทึม_พร้อมใช้งานและอัลกอริทึม_รับประกันค่าคงที่ ซึ่งแสดงถึงชุดของอัลกอริทึมที่มีการใช้งานและรับประกันบนแพลตฟอร์มตามลำดับ
ดังนั้น algorithms_guaranteed จึงเป็นชุดย่อยของ algorithms_available
เริ่ม Python REPL นำเข้า hashlib และเข้าถึงค่าคงที่ algorithms_available และ algorithms_guaranteed:
>>> hashlib.algorithms_available
# Output {'md5', 'md5-sha1', 'sha3_256', 'shake_128', 'sha384', 'sha512_256', 'sha512', 'md4', 'shake_256', 'whirlpool', 'sha1', 'sha3_512', 'sha3_384', 'sha256', 'ripemd160', 'mdc2', 'sha512_224', 'blake2s', 'blake2b', 'sha3_224', 'sm3', 'sha224'}
>>> hashlib.algorithms_guaranteed
# Output {'md5', 'shake_256', 'sha3_256', 'shake_128', 'blake2b', 'sha3_224', 'sha3_384', 'sha384', 'sha256', 'sha1', 'sha3_512', 'sha512', 'blake2s', 'sha224'}
เราพบว่า algorithms_guaranteed เป็นส่วนย่อยของ algorithms_available
วิธีสร้างวัตถุแฮชใน Python
ต่อไปมาเรียนรู้วิธีสร้างวัตถุแฮชใน Python เราจะคำนวณแฮช SHA256 ของสตริงข้อความโดยใช้วิธีการต่อไปนี้:
- ตัวสร้าง new() ทั่วไป
- ตัวสร้างเฉพาะอัลกอริทึม
การใช้ตัวสร้างใหม่ ()
มาเริ่มต้นสตริงข้อความกัน:
>>> message = "admintrick.com is awesome!"
ในการยกตัวอย่างวัตถุแฮช เราสามารถใช้ตัวสร้าง new() และส่งผ่านชื่อของอัลกอริทึมดังที่แสดง:
>>> sha256_hash = hashlib.new("SHA256")
ตอนนี้เราสามารถเรียกใช้เมธอด update() บนวัตถุแฮชด้วยสตริงข้อความเป็นอาร์กิวเมนต์:
>>> sha256_hash.update(message)
หากคุณทำเช่นนั้น คุณจะพบข้อผิดพลาดเนื่องจากอัลกอริทึมการแฮชสามารถทำงานกับสตริงไบต์เท่านั้น
Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Unicode-objects must be encoded before hashing
ในการรับสตริงที่เข้ารหัส คุณสามารถเรียกเมธอด encode() บนเมธอด string แล้วใช้ในการเรียกเมธอด update() หลังจากทำเช่นนั้น คุณสามารถเรียกใช้เมธอด hexdigest() เพื่อรับแฮช sha256 ที่สอดคล้องกับสตริงข้อความ
sha256_hash.update(message.encode()) sha256_hash.hexdigest() # Output:'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
แทนที่จะเข้ารหัสสตริงข้อความโดยใช้เมธอด encode() คุณยังสามารถกำหนดเป็นสตริงไบต์ได้ด้วยการใส่ b นำหน้าสตริงดังนี้:
message = b"admintrick.com is awesome!" sha256_hash.update(message) sha256_hash.hexdigest() # Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
แฮชที่ได้รับจะเหมือนกับแฮชก่อนหน้า ซึ่งยืนยันลักษณะที่กำหนดขึ้นของฟังก์ชันแฮช
นอกจากนี้ การเปลี่ยนแปลงเล็กน้อยในสตริงข้อความควรทำให้แฮชเปลี่ยนแปลงอย่างมาก (หรือที่เรียกว่า “เอฟเฟกต์หิมะถล่ม”)
เพื่อยืนยันสิ่งนี้ ลองเปลี่ยน ‘a’ ใน ‘awesome’ เป็น ‘A’ แล้วคำนวณแฮช:
message = "admintrick.com is Awesome!" h1 = hashlib.new("SHA256") h1.update(message.encode()) h1.hexdigest() # Output: '3c67f334cc598912dc66464f77acb71d88cfd6c8cba8e64a7b749d093c1a53ab'
เราเห็นว่าแฮชเปลี่ยนไปอย่างสิ้นเชิง
การใช้ตัวสร้างเฉพาะอัลกอริทึม
ในตัวอย่างก่อนหน้านี้ เราใช้ตัวสร้าง new() ทั่วไปและส่งผ่านใน “SHA256” เป็นชื่อของอัลกอริทึมในการสร้างวัตถุแฮช
แทนที่จะทำเช่นนั้น เราสามารถใช้ตัวสร้าง sha256() ดังที่แสดง:
sha256_hash = hashlib.sha256() message= "admintrick.com is awesome!" sha256_hash.update(message.encode()) sha256_hash.hexdigest() # Output: 'b360c77de704ad8f02af963d7da9b3bb4e0da6b81fceb4c1b36723e9d6d9de3d'
แฮชเอาต์พุตจะเหมือนกับแฮชที่เราได้รับก่อนหน้านี้สำหรับสตริงข้อความ “admintrick.com is Awesome!”
การสำรวจแอตทริบิวต์ของวัตถุแฮช
วัตถุแฮชมีแอตทริบิวต์ที่มีประโยชน์บางประการ:
- แอตทริบิวต์digest_sizeระบุขนาดของไดเจสต์เป็นไบต์ ตัวอย่างเช่น อัลกอริทึม SHA256 ส่งคืนแฮช 256 บิต ซึ่งเทียบเท่ากับ 32 ไบต์
- แอตทริบิวต์ block_size หมายถึงขนาดบล็อกที่ใช้ในอัลกอริทึมการแฮช
- ชื่อแอตทริบิวต์คือชื่อของอัลกอริทึมที่เราสามารถใช้ในตัวสร้าง new() การค้นหาค่าของแอตทริบิวต์นี้จะเป็นประโยชน์เมื่อวัตถุแฮชไม่มีชื่อที่สื่อความหมาย
เราสามารถตรวจสอบแอตทริบิวต์เหล่านี้สำหรับวัตถุ sha256_hash ที่เราสร้างไว้ก่อนหน้านี้:
>>> sha256_hash.digest_size 32 >>> sha256_hash.block_size 64 >>> sha256_hash.name 'sha256'
ต่อไป มาดูการใช้งานที่น่าสนใจของการแฮชโดยใช้โมดูลแฮชลิบของ Python
ตัวอย่างการปฏิบัติของการแฮช
การตรวจสอบความสมบูรณ์ของซอฟต์แวร์และไฟล์
ในฐานะนักพัฒนา เราดาวน์โหลดและติดตั้งแพ็คเกจซอฟต์แวร์ตลอดเวลา สิ่งนี้เป็นจริงไม่ว่าคุณจะทำงานบน Linux distro หรือบน Windows หรือ Mac
อย่างไรก็ตาม มิเรอร์บางตัวสำหรับแพ็คเกจซอฟต์แวร์อาจไม่น่าเชื่อถือ คุณสามารถค้นหาแฮช (หรือเช็คซัม) ข้างลิงค์ดาวน์โหลด และคุณสามารถตรวจสอบความสมบูรณ์ของซอฟต์แวร์ที่ดาวน์โหลดได้โดยการคำนวณแฮชและเปรียบเทียบกับแฮชที่เป็นทางการ
สามารถใช้กับไฟล์ในเครื่องของคุณได้เช่นกัน แม้แต่การเปลี่ยนแปลงเนื้อหาไฟล์ที่เล็กที่สุดก็จะเปลี่ยนแฮชอย่างมาก คุณสามารถตรวจสอบว่าไฟล์ได้รับการแก้ไขหรือไม่โดยการตรวจสอบแฮช
นี่เป็นตัวอย่างง่ายๆ สร้างไฟล์ข้อความ ‘my_file.txt’ ในไดเร็กทอรีการทำงาน และเพิ่มเนื้อหาลงไป
$ cat my_file.txt This is a sample text file. We are going to compute the SHA256 hash of this text file and also check if the file has been modified by recomputing the hash.
จากนั้นคุณสามารถเปิดไฟล์ในโหมดไบนารีอ่าน (‘rb’) อ่านในเนื้อหาของไฟล์และคำนวณแฮช SHA256 ดังที่แสดง:
>>> import hashlib >>> with open("my_file.txt","rb") as file: ... file_contents = file.read() ... sha256_hash = hashlib.sha256() ... sha256_hash.update(file_contents) ... original_hash = sha256_hash.hexdigest()
ในที่นี้ ตัวแปร original_hash คือแฮชของ ‘my_file.txt’ ในสถานะปัจจุบัน
>>> original_hash # Output: '53bfd0551dc06c4515069d1f0dc715d002d451c8799add29f3e5b7328fda9f8f'
ตอนนี้แก้ไขไฟล์ ‘my_file.txt’ คุณสามารถลบช่องว่างนำหน้าส่วนเกินออกก่อนคำว่า ‘going’ 🙂
คำนวณแฮชอีกครั้งและเก็บไว้ในตัวแปร computed_hash
>>> import hashlib >>> with open("my_file.txt","rb") as file: ... file_contents = file.read() ... sha256_hash = hashlib.sha256() ... sha256_hash.update(file_contents) ... computed_hash = sha256_hash.hexdigest()
จากนั้น คุณสามารถเพิ่มคำสั่ง assert อย่างง่ายที่ยืนยันว่า computed_hash เท่ากับ original_hash
>>> assert computed_hash == original_hash
หากไฟล์ถูกแก้ไข (ซึ่งเป็นจริงในกรณีนี้) คุณควรได้รับ AssertionError:
Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError
คุณสามารถใช้การแฮชเมื่อจัดเก็บข้อมูลที่ละเอียดอ่อน เช่น รหัสผ่านในฐานข้อมูล คุณยังสามารถใช้การแฮชในการตรวจสอบรหัสผ่านเมื่อเชื่อมต่อกับฐานข้อมูล ตรวจสอบแฮชของรหัสผ่านที่ป้อนกับแฮชของรหัสผ่านที่ถูกต้อง
บทสรุป
ฉันหวังว่าบทช่วยสอนนี้จะช่วยให้คุณเรียนรู้เกี่ยวกับการสร้างแฮชที่ปลอดภัยด้วย Python นี่คือประเด็นสำคัญ:
- โมดูล hashlib ของ Python นำเสนอการใช้งานอัลกอริธึมการแฮชหลายตัวที่พร้อมใช้งาน คุณสามารถรับรายการอัลกอริทึมที่รับประกันบนแพลตฟอร์มของคุณโดยใช้ hashlib.algorithms_guaranteed
- ในการสร้างวัตถุแฮช คุณสามารถใช้ตัวสร้าง new() ทั่วไปที่มีไวยากรณ์: hashlib.new(“algo-name”) อีกทางหนึ่ง คุณสามารถใช้ตัวสร้างที่สอดคล้องกับอัลกอริทึมการแฮชเฉพาะ เช่น hashlib.sha256() สำหรับแฮช SHA 256
- หลังจากเริ่มต้นสตริงข้อความที่จะแฮชและวัตถุแฮชแล้ว คุณสามารถเรียกใช้เมธอด update() บนวัตถุแฮช ตามด้วยเมธอด hexdigest() เพื่อรับแฮช
- การแฮชมีประโยชน์เมื่อตรวจสอบความสมบูรณ์ของสิ่งประดิษฐ์ซอฟต์แวร์และไฟล์ การจัดเก็บข้อมูลที่ละเอียดอ่อนในฐานข้อมูล และอื่นๆ
ต่อไป เรียนรู้วิธีเขียนโค้ดตัวสร้างรหัสผ่านแบบสุ่มใน Python