วิวัฒนาการของการแฮชรหัสผ่าน
คุณอาจเคยได้ยินคำแนะนำในการเลือกอัลกอริธึมแฮชรหัสผ่าน แต่คุณเคยคิดไหมว่าทำไมถึงแนะนำสิ่งเหล่านี้? ในบทความนี้ เราจะสำรวจวิวัฒนาการของอัลกอริธึมแฮชรหัสผ่านและเหตุผลเบื้องหลังพวกมัน
บทนำ
การแฮชรหัสผ่าน ตามชื่อเลย คือกระบวนการของการคำนวณค่าแฮชจากรหัสผ่าน ค่าของแฮชมักถูกเก็บในฐานข้อมูล และในกระบวนการเข้าสู่ระบบ (sign-in) ค่าแฮชของรหัสผ่านที่ผู้ใช้ป้อนเข้ามาจะถูกคำนวณและเปรียบเทียบกับค่าแฮชที่เก็บไว้ในฐานข้อมูล หากตรงกัน ผู้ใช้จะได้รับการยืนยันตัวตน
ก่อนที่เราจะลงลึกในวิวัฒนาการของอัลกอริธึมแฮชรหัสผ่าน สิ่งสำคัญคือการเข้าใจว่าทำไมมันถึงจำเป็น
รหัสผ่านแบบข้อความธรรมดา: ความเสี่ยงด้านความปลอดภัยขนาดใหญ่
ลองนึกภาพว่าคุณเป็นผู้ใช้ของเว็บไซต์ที่คุณลงทะเบียนบัญชีไว้ วันหนึ่งเว็บไซต์นั้นถูกแฮ็กและฐานข้อมูลถูกทำให้รั่วไหล หากเว็บไซต์นั้นเก็บรหัสผ่านในรูปแบบข้อความธรรมดา แฮกเกอร์สามารถเข้าถึงรหัสผ่านของคุณได้โดยตรง เนื่องจากหลายคนใช้รหัสผ่านซ้ำกันในหลายเว็บไซต์ แฮกเกอร์สามารถใช้รหัสผ่านนี้เพื่อเข้าถึงบัญชีอื่น ๆ ของคุณได้โดยไม่ได้รับอนุญาต สถานการณ์จะยิ่งรุนแรงขึ้นไปอีกหากคุณใช้รหัสผ่านเดียวกันหรือคล้ายกันกับบัญชีอีเมลของคุณ เพราะแฮกเกอร์สามารถรีเซ็ตรหัสผ่านของคุณและยึดครองบัญชีทั้งหมดที่เกี่ยวข้องได้
แม้ไม่มีข้อมูลรั่วไหล ในทีมขนาดใหญ่ก็มีใครบางคนที่มีการเข้าถึงฐานข้อมูลสามารถเห็นรหัสผ่านได้ เมื่อเทียบกับข้อมูลอื่น ๆ รหัสผ่านเป็นข้อมูลที่อ่อนไหวสูง และคุณคงไม่ต้องก ารให้ใครมีการเข้าถึงมันเลย
การเก็บรหัสผ่านโดยไม่แฮชถือเป็นข้อผิดพลาดของมือสมัครเล่น น่าเสียดาย หากคุณค้นหาคำว่า "รหัสผ่านรั่วไหลในรูปแบบข้อความธรรมดา" คุณจะพบว่าบริษัทใหญ่ ๆ เช่น Facebook, DailyQuiz และ GoDaddy ก็เคยประสบปัญหารหัสผ่านรั่วไหลในรูปแบบข้อความธรรมดา เป็นไปได้ว่าบริษัทอื่น ๆ อีกหลายแห่งก็ได้ทำข้อผิดพลาดเช่นนี้
การเข้ารหัส v.s. การขออนุญาต v.s. การแฮช
สามคำนี้มักถูกสับสน แต่แท้จริงแล้วพวกมันเป็นแนวคิดที่ต่างกัน
การเข้ารหัส
การเข้ารหัสคือสิ่งที่ต้องตัดออกไปก่อนสำหรับการเก็บรหัสผ่าน เช่น Base64 เป็นอัลกอริธึมการเข้ารหัสที่แปลงข้อมูลไบนารีให้เป็นสตริงของตัวอักษร:
การรู้จักอัลกอริธึมการเข้ารหัสทำให้ใครก็สามารถถอดรหัสสตริงที่เข้ารหัสและดึงข้อมูลต้นฉบับออกมาได้:
สำหรับแฮกเกอร์ ส่วนมากอัลกอริธึมเข้ารหัสเหมือนกับข้อความธรรมดา
การขออนุญาต
ก่อนการแฮชจะเป็นที่นิยม การขออนุญาตถูกใช้เพื่อเก็บรหัสผ่าน เช่น ด้วย AES การเข้ารหัสเกี่ยวข้องกับการใช้คีย์ (หรือคู่ของคีย์) เพื่อเข้ารหัสและถอดรหัสข้อมูล
ปัญหากับการขออนุญาตปรากฏชัดเจนในคำว่า "ถอดรหัส" การขออนุญาตสามารถดำเนินการย้อนกลับได้ หมายความว่าหากแฮกเกอร์ได้คีย์มา พวกเขาสามารถถอดรหัสรหัสผ่านและดึงรหัสผ่านในรูปแบบข้อความธรรมดาได้
การแฮช
ความแตกต่างหลัก ๆ ระหว่างการแฮช การเข้ารหัส และการขออนุญาตคือการแฮชเป็นสิ่งที่ไม่สามารถย้อนกลับได้ เมื่อรหัสผ่านถูกแฮชแล้ว มันไม่สามารถถูกถอดรหัสให้เป็นรูปแบบต้นฉบับได้อีก
ในฐานะเจ้าของเว็บไซต์ คุณไม่จำเป็นต้องรู้รหัสผ่านเอง ตราบเท่าที่ผู้ใช้สามารถเข้าสู่ระบบได้ด้วยรหัสผ่านที่ถูกต้อง กระบวนการลงทะเบียนสามารถสรุปได้ดังนี้:
- ผู้ใช้ป้อนรหัสผ่าน
- บริการใช้การแฮชอัลกอริธึมเพื่อคำนวณค่าของแฮชของรหัสผ่าน
- บริการเก็บค่าของแฮชในฐานข้อมูล
เมื่อผู้ใช้เข้าสู่ระบบ กระบวนการเป็นดังนี้:
- ผู้ใช้ป้อนรหัสผ่าน
- บริการใช้การแฮชอัลกอริธึมเดิมเพื่อคำนวณค่าของแฮชของรหัสผ่าน
- บ ริการเปรียบเทียบค่าของแฮชกับค่าของแฮชที่เก็บไว้ในฐานข้อมูล
- หากค่าของแฮชตรงกัน ผู้ใช้จะได้รับการยืนยันตัวตน
ทั้งสองกระบวนการนี้หลีกเลี่ยงการเก็บรหัสผ่านเป็นข้อความธรรมดา และเนื่องจากการแฮชไม่สามารถย้อนกลับได้ แม้ว่าฐานข้อมูลจะถูกแฮกเกอร์เจาะได้แค่ค่าของแฮชที่ดูเหมือนเป็นสตริงสุ่มเท่านั้น
ชุดเริ่มต้นของอัลกอริธึมแฮช
การแฮชอาจดูเหมือนเป็นวิธีแก้ปัญหาที่สมบูรณ์แบบสำหรับการเก็บรหัสผ่าน แต่มันไม่ง่ายแบบนั้น เพื่อเข้าใจว่าทำไม เรามาสำรวจวิวัฒนาการของอัลกอริธึมแฮชรหัสผ่านกันเถอะ
MD5
ในปี 1992 Ron Rivest ได้ออกแบบ อัลกอริธึม MD5 ซึ่งเป็นอัลกอริธึมสรุปข้อความที่สามารถคำนวณค่าแฮช 128 บิตจากข้อมูลใด ๆ MD5 ถูกใช้กันอย่างแพร่หลายในหลายสาขา รวมถึงการแฮชรหัสผ่านด้วย ตัวอย่างเช่น ค่าของแฮช MD5 ของ "123456" คือ:
อย่างที่กล่าวมาก่อนหน้านี้ ค่าของแฮชดูเหมือนเป็นสตริงสุ่มและไม่สามารถย้อนกลับได้ ยิ่งไปกว่านั้น MD5 มีความเร็วและง่ายต่อการทำให้มันกลายเป็นอัลกอริธึมแฮชรหัสผ่านที่นิยมมากที่สุด
อย่างไรก็ตาม ข้อได้เปรียบของ MD5 ก็คือข้อเสียเช่นกันในการแฮชรหัสผ่าน ความเร็วของมันทำให้มันเป็นเป้าหมายง่ายต่อการโจมตีด้วยวิธี brute-force หากแฮกเกอร์มีรายชื่อของรหัสผ่านที่พบบ่อยและข้อมูลส่วนตัวของคุณ พวกเขาสามารถคำนวณค่าของแฮช MD5 ของแต่ละส่วนประกอบและเปรียบเทียบกับค่าของแฮชในฐานข้อมูลได้ ตัวอย่างเช่นพวกเขาอาจรวมวันเกิดของค ุณกับชื่อของคุณหรือกับชื่อสัตว์เลี้ยงของคุณ
ในปัจจุบัน เครื่องคอมพิวเตอร์มีพลังมากกว่าก่อน ทำให้มันง่ายต่อการโจมตี brute force แฮชรหัสผ่านของ MD5
ตระกูล SHA
ทำไมไม่ใช้อัลกอริธึมอื่นที่สร้างค่าของแฮชที่ยาวขึ้น? ตระกูล SHA ดูเหมือนจะเป็นทางเลือกที่ดี SHA-1 เป็นอัลกอริธึมแฮชที่สร้างค่าของแฮช 160 บิต และ SHA-2 เป็นตระกูลอัลกอริธึมแฮชที่สร้างค่าของแฮชที่มีความยาว 224 บิต, 256 บิต, 384 บิต, และ 512 บิต ลองดูค่าของแฮช SHA-256 ของ "123456":
ค่าของแฮช SHA-256 ยาวกว่าของ MD5 และมันก็ไม่สามารถย้อนกลับได้ แต่ยังมีปัญหาอีก หากคุณรู้จักค่าของแฮชแล้ว อย่างที่เห็นในข้างบน และคุณเห็นค่าของแฮชที่แน่ชัดในฐานข้อมูล คุณจะรู้เลยว่ารหัสผ่านคือ "123456" แฮกเกอร์สามารถสร้างรายชื่อของรหัสผ่านที่พบบ่อยและค่าของแฮชที่ตรงกันและเปรียบเทียบกับค่าของแฮชในฐานข้อมูลได้ รายชื่อนี้เป็นที่รู้จักกันว่าเป็น rainbow table
Salt
เพื่อบรรเทาการโจมตีด้วย rainbow table แนวคิดของ salt ได้ถูกแนะนำ Salt เป็นสตริงสุ่มที่ถู กเพิ่มเข้าไปในรหัสผ่านก่อนการแฮช ตัวอย่างเช่น หาก salt คือ "salt" และคุณต้องการใช้ SHA-256 เพื่อแฮชรหัสผ่าน "123456" พร้อมกับ salt แทนที่จะทำง่าย ๆ แบบนี้:
คุณควรจะทำแบบนี้:
อย่างที่เห็น ผลลัพธ์จะแตกต่างไปจากการแฮชโดยไม่มี salt โดยทั่วไปแล้ว ผู้ใช้แต่ละคนจะได้รับ salt แบบสุ่มระหว่างการลงทะเบียนซึ่งถูกเก็บในฐานข้อมูลข้างค่าของแฮช ในกระบวนการเข้าสู่ระบบ salt ถูกใช้ในการคำนวณค่าของแฮชของรหัสผ่านที่ป้อนเข้ามาและเปรียบเทียบกับค่าของแฮชที่เก็บไว้
Iteration
ถึงแม้จะเพิ่ม salt ค่าของแฮชยังคงไวต่อการโจมตีด้วยวิธี brute-force เนื่องจากฮาร์ดแวร์มีประสิทธิภาพมากขึ้น เพื่อทำให้ยากขึ้น Iteration (เช่น การรันอัลกอริธึมแฮชหลายครั้ง) สามารถถูกนำม าใช้ได้ ตัวอย่างเช่นแทนที่จะใช้:
คุณสามารถใช้:
การเพิ่มจำนวน iteration ทำให้การโจมตีด้วยวิธี brute-force ยากขึ้น แต่สิ่งนี้ก็จะกระทบกระบวนการเข้าสู่ระบบเพราะมันจะทำให้ช้าลง ดังนั้น จำเป็นต้องหาสมดุลระหว่างความปลอดภัยและประสิทธิภาพ
ช่วงพักกลาง
มาพักกันหน่อยและสรุปลักษณะของอัลกอริธึมแฮชรหัสผ่านที่ดี:
- ไม่สามารถย้อนกลับได้ (preimage resistance)
- ยากต่อการโจมตีด้วยวิธี brute-force
- ทนทานต่อการโจมตีด้วย rainbow table
อย่างที่คุณอาจสังเกตเห็น salt และ iteration จำเป็นเพื่อทำตามข้อกำหนดทั้งหมดนี้ ปัญหาคือทั้ง MD5 และตระกูล SHA ไม่ได้ถูกออกแบบมาเฉพาะสำหรับการแฮชรหัสผ่าน; พวกมันถูกใช้กันทั่วไปในการตรวจสอบความสมบูรณ์ (หรื อ "สรุปข้อความ") ด้วยเหตุนี้ แต่ละเว็บไซต์อาจมีการใช้งาน salt และ iteration แตกต่างกัน ทำให้เกิดความท้าทายในการมาตรฐานและการย้ายข้อมูล
อัลกอริธึมแฮชรหัสผ่าน
เพื่อแก้ปัญหานี้ มีหลายอัลกอริธึมแฮชที่ถูกออกแบบมาเฉพาะสำหรับการแฮชรหัสผ่าน ลองมาดูกันบ้าง
bcrypt
bcrypt เป็นอัลกอริธึมแฮชรหัสผ่านที่ถูกออกแบบโดย Niels Provos และ David Mazières มันถูกใช้กันอย่างแพร่หลายในหลายภาษาโปรแกรม นี่คือตัวอย่างของค่าแฮช bcrypt:
แม้ว่ามันจะดูเหมือนเป็นสตริงสุ่มอีกอัน แต่มันมีข้อมูลเพิ่มเติม ลองแยกดู:
- ส่วนแรก
$2y
บ่งบอกถึงอัลกอริธึมซึ่งคือ2y
. - ส่วนที่สอง
$12
บ่งบอกจำนวน iteration ซึ่งคือ12
ซึ่งหมายความว่าอัลกอริธึมแฮชจะถูกรัน 212=4096 ครั้ง (iteration). - ส่วนที่สาม
wNt7lt/xf8wRJgPU7kK2ju
คือ salt. - ส่วนสุดท้าย
GrirhHK4gdb0NiCRdsSoAxqQoNbiluu
คือค่าของแฮช.
bcrypt มีบางข้อจำกัด:
- ความยาวสูงสุดของรหัสผ่านคือ 72 byte.
- salt ถูกจำกัดที่ 16 byte.
- ค่าของแฮชถูกจำกัดที่ 184 bit.
Argon2
เนื่องจากข้อถกเถียงและข้อจำกัดของอัลกอริธึมแฮชรหัสผ่านที่มีอยู่ การแข่งขันแฮชรหัสผ่าน password hashing competition ได้จัดขึ้นในปี 2015 โดยไม่ลงรายละเอียด ลองโฟกัสที่ผู้ชนะ: Argon2.
Argon2 เป็นอัลกอริธึมแฮชรหัสผ่านที่ออกแบบโดย Alex Biryukov, Daniel Dinu และ Dmitry Khovratovich มันนำเสนอแนวคิดใหม่บางข้อ:
- Memory-hard: อัลกอริธึมถูกออกแบบมาให้ยากต่อการประมวลผลแบบคู่ขนาน ทำให้การโจมตีด้วย GPU ยากขึ้น
- Time-hard: อัลกอริธึมถูกออกแบบมาให้ยากต่อการปรับแต่ง ทำให้การโจมตีด้วย ASIC (Application-specific integrated circuits) ยากขึ้น
- Side-channel resistant: อัลกอริธึมถูกออกแบบมาให้ทนทานต่อการโจมตีช่องทางข้าง เช่น การโจมตีเวลา
มีสองเวอร์ชันหลักของ Argon2, Argon2i และ Argon2d. Argon2i ปลอดภัยที่สุดต่อการโจมตีช่องช่องข้าง ในขณะที่ Argon2d ให้ความต้านทานสูงสุดต่อการโจมตี GPU.
-- Argon2
นี่คือตัวอย่างของค่าแฮช Argon2:
ลองแยกดู:
- ส่วนแรก
$argon2i
บ่งบอกถึงอัลกอริธึมซึ่งคือargon2i
. - ส่วนที่สอง
$v=19
บ่งบอกถึงเวอร์ชันซึ่งคือ19
. - ส่วนที่สาม
$m=16,t=2,p=1
บ่งบอกถึงค่าใช้จ่ายหน่วยความจำ ค่าใช้จ่ายเวลา และระดับการขนานซึ่งคือ16
,2
และ1
. - ส่วนที่สี่
$YTZ5ZnpXRWN5SlpjMHBDRQ
คือ salt. - ส่วนสุดท้าย
$12oUmJ6xV5bIadzZHkuLTg
คือค่าของแฮช.
ใน Argon2 ความยาวสูงสุดของรหัสผ่านคือ 232-1 byte, salt ถูกจำกัดที่ 232-1 byte และค่าของแฮชถูกจำกัดที่ 232-1 byte ซึ่งเพียงพอสำหรับสถานการณ์ส่วนใหญ่
Argon2 มีอยู่ในหลายภาษาโปรแกรมเช่น node-argon2 สำหรับ Node.js และ argon2-cffi สำหรับ Python
สรุป
ตลอดหลายปีที่ผ่านมา อัลกอริธึมแฮชรหัสผ่านได้ผ่านการวิวัฒนาการอย่างมีนัยสำคัญ เราต้องขอบคุณชุมชนความปลอดภัยสำหรับความพยายามหลายสิบปีในการทำให้อินเทอร์เน็ตเป็นที่ปลอดภัยขึ้น ขอบคุณการมีส่วนร่วมของพวกเขา นักพัฒนาสามารถให้ความสำคัญกับการสร้างบริการที่ดีขึ้นโดยไม่ต้องกังวลเกี่ยวกับความปลอดภัยของการแฮชรหัสผ่าน แม้ว่าการป้องกันความปลอดภัย 100% ในระบบอาจจะไม่สามารถทำได้ แต่เราสามารถใช้นโยบายหลากหลายเพื่อเสี่ยงต่อความเสี่ยงที่เกี่ยวข้อง
หากคุณต้องการหลีกเลี่ยงความยุ่งยากในการดำเนินการยืนยันและอำนาจอนุญาต ลองใช้ Logto ฟรี เรามีโซลูชันที่ปลอดภัย (เราใช้ Argon2!), เชื่อถือได้ และมีความสามารถขยายได้ ช่วยให้คุณสามารถมุ่งมั่นกับการสร้างผลิตภัณฑ์ของคุณได้