การ Hash รหัสผ่านด้วย Argon2 ใน Python

แชร์ความรู้ภาษา Python ไพทอน การเขียนโปรแกรมภาษาไพทอน

Moderator: mindphp, ผู้ดูแลกระดาน

Sakana
PHP Super Member
PHP Super Member
โพสต์: 307
ลงทะเบียนเมื่อ: 16/06/2025 9:38 am

การ Hash รหัสผ่านด้วย Argon2 ใน Python

โพสต์ที่ยังไม่ได้อ่าน โดย Sakana »

ในโลกของการรักษาความปลอดภัยไซเบอร์ยุคใหม่ การเลือกอัลกอริทึมสำหรับ Hash รหัสผ่าน (Password Hashing) ที่เหมาะสมเป็นสิ่งสำคัญยิ่งยวด แม้ว่า Bcrypt จะเป็นตัวเลือกที่ดีและยังคงใช้กันอย่างแพร่หลาย แต่เมื่อพูดถึงความปลอดภัยระดับสูงสุด โดยเฉพาะอย่างยิ่งในการต้านทานการโจมตีแบบ Brute-force และ Rainbow Table ที่ใช้ GPU และ ASIC อัลกอริทึมอย่าง Argon2 ได้รับการยอมรับว่าเป็น มาตรฐานทองคำใหม่
Argon2 ได้รับการคัดเลือกให้เป็นผู้ชนะในงาน Password Hashing Competition (PHC) ในปี 2015 ด้วยการออกแบบที่เน้นการใช้ทรัพยากรทั้ง CPU, หน่วยความจำ (RAM) และสามารถปรับแต่งให้ใช้หลายเธรดได้ ทำให้การโจมตีแบบ Mass-parallelization (โจมตีพร้อมกันจำนวนมาก) ทำได้ยากและมีค่าใช้จ่ายสูง
บทความนี้จะแนะนำวิธีการใช้งาน Argon2 ใน Python เพื่อ Hash และตรวจสอบรหัสผ่านของคุณอย่างปลอดภัย

ทำไมต้อง Argon2
Argon2 ถูกออกแบบมาเพื่อแก้ไขจุดอ่อนที่อาจเกิดขึ้นในอัลกอริทึม Hash รหัสผ่านรุ่นก่อนๆ โดยเฉพาะอย่างยิ่งความสามารถในการต้านทานการโจมตีด้วยฮาร์ดแวร์เฉพาะทาง (ASIC) และ GPU:
- Memory-hard: Argon2 ต้องการหน่วยความจำจำนวนมากในการคำนวณ Hash ทำให้การสร้างฮาร์ดแวร์เฉพาะทาง (ASIC) เพื่อโจมตีนั้นมีต้นทุนสูงมาก
- Time-hard: ต้องใช้เวลาในการคำนวณนาน (คล้ายกับ Bcrypt และ Scrypt) ซึ่งทำให้การโจมตีแบบ Brute-force ช้าลงอย่างมาก
- Parallelism-hard: สามารถปรับแต่งให้ใช้หลาย CPU core/thread ได้อย่างมีประสิทธิภาพ ทำให้การเร่งความเร็วในการโจมตีแบบขนาน (Parallelization) เป็นไปได้ยากและแพง
- Flexible Parameters: Argon2 มีพารามิเตอร์ที่สามารถปรับแต่งได้ละเอียดกว่า ทำให้สามารถปรับให้เข้ากับความต้องการด้านความปลอดภัยและทรัพยากรของระบบได้อย่างเหมาะสม

Argon2 มีหลาย "flavors" (รุ่นย่อย) ที่ใช้บ่อยคือ Argon2id ซึ่งรวมเอาข้อดีของ Argon2i (เน้นการเข้าถึงหน่วยความจำแบบอิสระเพื่อป้องกันการโจมตีจาก GPU) และ Argon2d (เน้นการเข้าถึงหน่วยความจำแบบขึ้นกับข้อมูลเพื่อป้องกันการโจมตีจาก Side-channel) เข้าไว้ด้วยกัน ทำให้เป็นตัวเลือกที่แนะนำสำหรับแอปพลิเคชันส่วนใหญ่

เริ่มต้นใช้งาน Argon2 ใน Python
ในการใช้ Argon2 ใน Python เราจะใช้ไลบรารีที่ชื่อว่า argon2-cffi ซึ่งเป็น Python binding สำหรับไลบรารี Argon2 ที่เขียนด้วยภาษา C (cffi ย่อมาจาก C Foreign Function Interface)

คุณสามารถติดตั้งได้ง่ายๆ ด้วย pip:

โค้ด: เลือกทั้งหมด

pip install argon2-cffi
การ Hash รหัสผ่านด้วย Argon2
ในการ Hash รหัสผ่านด้วย Argon2 คุณจะต้องกำหนดพารามิเตอร์หลักสามตัว ได้แก่:
- memory_cost (m): จำนวนหน่วยความจำที่จะใช้ในการคำนวณ (ในหน่วย KiB) ยิ่งมากยิ่งปลอดภัยและต้านทาน GPU ได้ดีขึ้น
- time_cost (t): จำนวนครั้งที่อัลกอริทึมจะวนซ้ำ ยิ่งมากยิ่งปลอดภัยแต่ใช้เวลานานขึ้น
- parallelism (p): จำนวนเธรด/คอร์ที่จะใช้ในการคำนวณ (แนะนำให้ใช้ 1 หรือเท่ากับจำนวนคอร์ของ CPU หากต้องการประสิทธิภาพสูงสุดในการ Hash)

argon2-cffi จะจัดการเรื่องการสร้าง Salt และการเข้ารหัสพารามิเตอร์เหล่านี้ลงใน Hash Output ให้โดยอัตโนมัติ

โค้ด: เลือกทั้งหมด

from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError

# สร้าง instance ของ PasswordHasher
# สามารถกำหนดค่า memory_cost, time_cost, parallelism ได้
# ค่าเริ่มต้นที่แนะนำมักจะเพียงพอสำหรับแอปพลิเคชันส่วนใหญ่
# ตัวอย่าง: ph = PasswordHasher(memory_cost=65536, time_cost=4, parallelism=2)
# ค่าเริ่มต้นของ argon2-cffi อาจจะประมาณ memory_cost=1024*128 (128 MiB), time_cost=2, parallelism=8
# สำหรับการใช้งานจริง ควรทดสอบหาค่าที่เหมาะสมกับ server resource ของคุณ
ph = PasswordHasher() 

def hash_password_argon2(password):
    return ph.hash(password)

# --- ตัวอย่างการใช้งาน ---
plain_password = "MyUltraSecurePassword!"
hashed_pwd_argon2 = hash_password_argon2(plain_password)

print(f"Plain Password: {plain_password}")
print(f"Hashed Password (Argon2): {hashed_pwd_argon2}")
คำอธิบายโค้ด:
- PasswordHasher(): สร้างอ็อบเจกต์ PasswordHasher คุณสามารถส่งพารามิเตอร์ memory_cost, time_cost, และ parallelism เข้าไปใน constructor เพื่อปรับแต่งความแรงของ Hash ได้
- ph.hash(password): ฟังก์ชันนี้จะรับรหัสผ่านที่เป็น String (ไลบรารีนี้จัดการการ encode เป็น bytes ให้เอง) และคืนค่า Hash ที่สมบูรณ์แบบที่เป็น String ซึ่งประกอบด้วยข้อมูลเกี่ยวกับเวอร์ชันของ Argon2, พารามิเตอร์ที่ใช้, Salt และ Hash Value จริงๆ

ผลลัพธ์

โค้ด: เลือกทั้งหมด

Plain Password: MyUltraSecurePassword!
Hashed Password (Argon2): $argon2id$v=19$m=65536,t=3,p=4$2dxEnSLjyh4vCtfjKqwAwg$SUlN/hPPmL+8UJSIBXjpB/BSGzOaIxl4zgH1flC/YzM
การตรวจสอบรหัสผ่านด้วย Argon2
เมื่อผู้ใช้พยายามเข้าสู่ระบบ คุณจะต้องนำรหัสผ่านที่ผู้ใช้ป้อนเข้ามาไปเปรียบเทียบกับ Hash ที่เก็บอยู่ในฐานข้อมูล ซึ่ง argon2-cffi ก็มีฟังก์ชันสำหรับทำสิ่งนี้โดยเฉพาะ

โค้ด: เลือกทั้งหมด

from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError

# สามารถกำหนดค่า memory_cost, time_cost, parallelism ได้
# ค่าเริ่มต้นที่แนะนำมักจะเพียงพอสำหรับแอปพลิเคชันส่วนใหญ่
# ตัวอย่าง: ph = PasswordHasher(memory_cost=65536, time_cost=4, parallelism=2)
# ค่าเริ่มต้นของ argon2-cffi อาจจะประมาณ memory_cost=1024*128 (128 MiB), time_cost=2, parallelism=8
# สำหรับการใช้งานจริง ควรทดสอบหาค่าที่เหมาะสมกับ server resource ของคุณ

# สร้าง instance ของ PasswordHasher
ph = PasswordHasher() 

def verify_password_argon2(plain_password, hashed_password_from_db):
    try:
        ph.verify(hashed_password_from_db, plain_password)
        return True
    except VerifyMismatchError:
        # เกิดเมื่อรหัสผ่านไม่ตรงกัน
        return False
    except Exception as e:
        # กรณีอื่นๆ เช่น hash string เสียหาย
        print(f"An error occurred during verification: {e}")
        return False


def hash_password_argon2(password):
    return ph.hash(password)

# --- ตัวอย่างการใช้งาน ---
plain_password = "MyUltraSecurePassword!"
hashed_pwd_argon2 = hash_password_argon2(plain_password)

print(f"Plain Password: {plain_password}")
if verify_password_argon2(plain_password, hashed_pwd_argon2):
    print(f"'{plain_password}' - Login successful!")
else:
    print(f"'{plain_password}' - Login failed!")
คำอธิบายโค้ด:
- ph.verify(hashed_password_from_db, plain_password): ฟังก์ชันนี้จะรับ Hash ที่เก็บไว้ในฐานข้อมูล (ซึ่งมี Salt และพารามิเตอร์ทั้งหมดฝังอยู่) และรหัสผ่าน Plain Text ที่ผู้ใช้ป้อนเข้ามา หากรหัสผ่านตรงกัน ฟังก์ชันจะทำงานได้สำเร็จ (ไม่เกิด Exception) หากไม่ตรงกัน จะเกิด VerifyMismatchError
- Error Handling: การใช้ try-except VerifyMismatchError เป็นสิ่งสำคัญมากในการจัดการผลลัพธ์ของการตรวจสอบรหัสผ่านอย่างถูกต้อง

ผลลัพธ์
Python Knowledge-1.png
Python Knowledge-1.png (2.4 KiB) Viewed 68 times
สรุป
Argon2 เป็นอัลกอริทึมการ Hash รหัสผ่านที่ทันสมัยและแข็งแกร่งที่สุดในปัจจุบัน ด้วยคุณสมบัติ Memory-hard และ Parallelism-hard ทำให้มันเป็นตัวเลือกที่ยอดเยี่ยมในการปกป้องข้อมูลรหัสผ่านของผู้ใช้จากภัยคุกคามที่พัฒนาไปอย่างรวดเร็ว
การนำ argon2-cffi ไปใช้งานในแอปพลิเคชัน Python ของคุณเป็นขั้นตอนที่สำคัญในการยกระดับความปลอดภัย ซึ่งเป็นการลงทุนที่คุ้มค่าเพื่อรักษาความน่าเชื่อถือและความไว้วางใจของผู้ใช้ของคุณครับ

อ้างอิง
- https://www.mindphp.com/developer/80-ph ... ction.html
- viewtopic.php?p=441753
- viewtopic.php?t=116518
- https://www.mindphp.com/บทเรียนออนไลน์/ ... iable.html
- https://github.com/hynek/argon2-cffi
  • Similar Topics
    ตอบกลับ
    แสดง
    โพสต์ล่าสุด

ผู้ใช้งานขณะนี้

สมาชิกกำลังดูบอร์ดนี้: ไม่มีสมาชิกใหม่ และบุคลทั่วไป 6