วิธีใช้ Bcrypt ในการ Hash รหัสผ่านใน Python: ปกป้องข้อมูลผู้ใช้ให้ปลอดภัย

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

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

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

วิธีใช้ Bcrypt ในการ Hash รหัสผ่านใน Python: ปกป้องข้อมูลผู้ใช้ให้ปลอดภัย

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

ในยุคดิจิทัลที่ภัยคุกคามทางไซเบอร์มีอยู่รอบตัว การปกป้องข้อมูลผู้ใช้ โดยเฉพาะอย่างยิ่ง รหัสผ่าน ถือเป็นความรับผิดชอบอันดับแรกของผู้พัฒนาทุกคน การจัดเก็บรหัสผ่านในรูปแบบ Plain Text (ข้อความที่อ่านได้) ในฐานข้อมูลเป็นเรื่องที่อันตรายอย่างยิ่งและไม่ควรทำโดยเด็ดขาด
บทความนี้จะแนะนำคุณให้รู้จักกับ Bcrypt หนึ่งในอัลกอริทึมการทำ Password Hashing ที่แข็งแกร่งและเป็นที่ยอมรับ เพื่อใช้ในการ Hash รหัสผ่านในภาษา Python ซึ่งจะช่วยให้ข้อมูลรหัสผ่านของผู้ใช้ของคุณปลอดภัยแม้ในกรณีที่ฐานข้อมูลถูกเจาะ

ทำไมต้อง Hash รหัสผ่าน และทำไมต้องเป็น Bcrypt?
การเก็บรหัสผ่านแบบ Plain Text นั้นอันตรายอย่างยิ่ง หากฐานข้อมูลถูกบุกรุก รหัสผ่านของผู้ใช้จะตกอยู่ในมือของแฮกเกอร์ทันที
Hashing คือกระบวนการแปลงข้อมูล (ในที่นี้คือรหัสผ่าน) ให้เป็นชุดอักขระที่ไม่สามารถย้อนกลับไปหารหัสผ่านต้นฉบับได้ (One-way Function) ซึ่งต่างจากการเข้ารหัส (Encryption) ที่สามารถถอดรหัสกลับได้
แล้วทำไมต้องเลือก Bcrypt ล่ะ?
  • ออกแบบมาเพื่อ Hash รหัสผ่านโดยเฉพาะ: Bcrypt ถูกออกแบบมาเพื่อต้านทานการโจมตีแบบ Brute-force และ Dictionary Attack โดยเฉพาะ
  • Computationally Intensive: Bcrypt ถูกทำให้ทำงานช้าลงโดยใช้ "Work Factor" หรือ "Cost Factor" ยิ่งค่า Work Factor สูงเท่าไหร่ การคำนวณ Hash ก็ยิ่งใช้เวลามากขึ้นเท่านั้น การทำเช่นนี้ทำให้การโจมตีแบบเดาสุ่มทำได้ยากและใช้เวลานานมาก แม้ว่าเครื่องคอมพิวเตอร์จะทรงพลังขึ้นในอนาคต เราก็สามารถเพิ่ม Work Factor เพื่อรักษาความปลอดภัยได้
  • ใช้ Salt อัตโนมัติ: Bcrypt จะสร้าง Salt (ค่าสุ่มที่ไม่ซ้ำกัน) และผนวกเข้าไปใน Hash Output โดยอัตโนมัติ ทำให้รหัสผ่านเดียวกันถูก Hash ออกมาได้ค่าที่ไม่ซ้ำกันในแต่ละครั้ง ซึ่งช่วยป้องกัน Rainbow Table Attack ได้อย่างมีประสิทธิภาพ
เริ่มต้นใช้งาน Bcrypt ใน Python
ในการใช้ Bcrypt ใน Python เราจะใช้ไลบรารีที่ชื่อว่า bcrypt ซึ่งคุณสามารถติดตั้งได้ผ่าน pip:

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

pip install bcrypt
การ Hash รหัสผ่านด้วย Bcrypt
ขั้นตอนแรกคือการนำรหัสผ่าน Plain Text ที่ผู้ใช้ป้อนเข้ามา (เช่น ตอนสมัครสมาชิก) มา Hash ก่อนจะเก็บลงในฐานข้อมูล

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

import bcrypt

def hash_password(password):
    # เปลี่ยน password string เป็น bytes (bcrypt ทำงานได้เฉพาะ bytes)
    password_bytes = password.encode('utf-8')

    # สร้าง salt และ hash password
    # สร้าง generates a random salt
    # สามารถเพิ่มเติมได้เอง เช่น bcrypt.gensalt(rounds=14)
    hashed_password = bcrypt.hashpw(password_bytes, bcrypt.gensalt())
    
    return hashed_password

# --- ตัวอย่างการใช้งาน ---
plain_password = "MySuperSecurePassword123!"
hashed_pwd = hash_password(plain_password)

print(f"Plain Password: {plain_password}")
print(f"Hashed Password: {hashed_pwd.decode('utf-8')}") # แปลงกับเป็น string 
ผลลัพธ์
Python Knowledge-1.png
Python Knowledge-1.png (5.08 KiB) Viewed 143 times
คำอธิบายโค้ด:
  • password.encode('utf-8'): Bcrypt ทำงานกับข้อมูลแบบ bytes ดังนั้นเราจึงต้องแปลง String ของรหัสผ่านให้เป็น bytes ก่อน
  • bcrypt.gensalt(): ฟังก์ชันนี้จะสร้าง Salt แบบสุ่มที่ไม่ซ้ำกันในแต่ละครั้งที่เรียกใช้ ค่า rounds (Work Factor) เริ่มต้นคือ 12 ซึ่งเป็นค่าที่เหมาะสมสำหรับ Bcrypt ในปัจจุบัน
  • bcrypt.hashpw(password_bytes, bcrypt.gensalt()): นี่คือฟังก์ชันหลักที่ใช้ในการ Hash รหัสผ่าน มันจะนำรหัสผ่านและ Salt ที่สร้างขึ้นมาใช้ในการคำนวณ Hash
การตรวจสอบรหัสผ่านด้วย Bcrypt
เมื่อผู้ใช้พยายามเข้าสู่ระบบ คุณจะต้องนำรหัสผ่านที่ผู้ใช้ป้อนเข้ามาไปเปรียบเทียบกับ Hash ที่เก็บอยู่ในฐานข้อมูล ซึ่ง bcrypt ก็มีฟังก์ชันสำหรับทำสิ่งนี้โดยเฉพาะ

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

import bcrypt
def verify_password(plain_password, hashed_password):
    # แปลง  string to bytes
    plain_password_bytes = plain_password.encode('utf-8')

    # Verify the password
    return bcrypt.checkpw(plain_password_bytes, hashed_password)
ตัวอย่างการใช้งาน

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

import bcrypt

def hash_password(password):
    # เปลี่ยน password string เป็น bytes (bcrypt ทำงานได้เฉพาะ bytes)
    password_bytes = password.encode('utf-8')

    # สร้าง salt และ hash password
    # สร้าง generates a random salt
    # สามารถเพิ่มเติมได้เอง เช่น bcrypt.gensalt(rounds=14)
    hashed_password = bcrypt.hashpw(password_bytes, bcrypt.gensalt())
    
    return hashed_password

def verify_password(plain_password, hashed_password):
    # แปลง  string to bytes
    plain_password_bytes = plain_password.encode('utf-8')

    # Verify the password
    return bcrypt.checkpw(plain_password_bytes, hashed_password)

# --- ตัวอย่างการใช้งาน ---
plain_password = "MySuperSecurePassword123!"
hashed_pwd = hash_password(plain_password)

if verify_password(plain_password, hashed_pwd):
    print(f"Plain Password: '{plain_password}' - Login successful!")
else:
    print(f"'{plain_password}' - Login failed!")

print(f"Hashed Password: {hashed_pwd.decode('utf-8')}") # แปลงกับเป็น string 
ผลลัพธ์
Python Knowledge-1.png
Python Knowledge-1.png (5.11 KiB) Viewed 143 times
คำอธิบายโค้ด:
- bcrypt.checkpw(plain_password_bytes, hashed_password): ฟังก์ชันนี้จะทำการ Hash รหัสผ่านที่ผู้ใช้ป้อนเข้ามาโดยใช้ Salt และ Work Factor ที่ดึงมาจาก hashed_password ที่เก็บไว้ จากนั้นจึงนำผลลัพธ์มาเปรียบเทียบกัน หากตรงกันจะคืนค่า True หากไม่ตรงจะคืนค่า False
- สำคัญ: คุณไม่จำเป็นต้องดึง Salt หรือ Work Factor ออกมาจาก Hash เอง bcrypt.checkpw จัดการให้ทั้งหมดแล้ว

การจัดการ Work Factor (Cost Factor)
Work Factor (หรือ rounds ใน bcrypt.gensalt()) เป็นตัวกำหนดความยากในการคำนวณ Hash ยิ่งค่าสูง ก็ยิ่งปลอดภัย แต่ก็ยิ่งใช้เวลาในการประมวลผลนานขึ้น
- ค่าเริ่มต้นคือ 12 ซึ่งเป็นค่าที่เหมาะสมในปัจจุบัน
- คุณสามารถปรับค่านี้ได้ หากฮาร์ดแวร์ของคุณมีประสิทธิภาพสูงขึ้น หรือหากคุณต้องการเพิ่มความปลอดภัยในอนาคต

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

import bcrypt

# Hash with a higher work factor (e.g., 14)
higher_cost_hashed_pwd = bcrypt.hashpw(b"anotherPassword", bcrypt.gensalt(rounds=14))
print(f"Hashed with cost 14: {higher_cost_hashed_pwd.decode('utf-8')}")
คำอธิบายโค้ด:
- b"anotherPassword" คือการทำให้เป็น bytes
- bcrypt.gensalt(rounds=14) คือ จำนวน rounds ที่ใช้ในการคำนวณ Hash

ข้อควรพิจารณา: การเพิ่ม Work Factor จะส่งผลต่อเวลาในการ Login หรือ Register เนื่องจากต้องใช้เวลาในการคำนวณ Hash นานขึ้น คุณควรทดสอบให้แน่ใจว่าค่าที่เลือกไม่ส่งผลกระทบต่อประสบการณ์ผู้ใช้มากเกินไป

สรุป
การใช้ Bcrypt ในการ Hash รหัสผ่านใน Python เป็นแนวทางปฏิบัติที่สำคัญและเป็นมาตรฐานสำหรับความปลอดภัยของข้อมูลผู้ใช้ ด้วยไลบรารี bcrypt คุณสามารถ Hash รหัสผ่านและตรวจสอบความถูกต้องได้อย่างง่ายดายและมีประสิทธิภาพ โดยไม่ต้องกังวลเรื่องการจัดการ Salt หรือ Work Factor ที่ซับซ้อน ซึ่งถูกจัดการให้อัตโนมัติโดยไลบรารีนี้
นอกจากนี้ Bcrypt ยังออกแบบมาให้ต้านทานการโจมตีแบบ Brute-force และ Rainbow Table ได้ดี โดยสามารถปรับระดับความยาก (work factor) ได้ตามความต้องการ เพื่อให้เหมาะสมกับสภาพแวดล้อมและทรัพยากรของระบบของคุณอย่างปลอดภัยและยืดหยุ่น

อ้างอิง
- https://www.mindphp.com/บทความ/31-ความร ... h-e-w.html
- viewtopic.php?f=79&t=116426
- https://www.mindphp.com/คู่มือ/73-คืออะ ... ออะไร.html
- viewtopic.php?t=105393
- https://github.com/pyca/bcrypt/
Sakana
PHP Super Member
PHP Super Member
โพสต์: 307
ลงทะเบียนเมื่อ: 16/06/2025 9:38 am

Re: วิธีใช้ Bcrypt ในการ Hash รหัสผ่านใน Python: ปกป้องข้อมูลผู้ใช้ให้ปลอดภัย

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

ในยุคดิจิทัลที่ภัยคุกคามทางไซเบอร์มีอยู่รอบตัว การปกป้องข้อมูลผู้ใช้ โดยเฉพาะอย่างยิ่ง รหัสผ่าน ถือเป็นความรับผิดชอบอันดับแรกของผู้พัฒนาทุกคน การจัดเก็บรหัสผ่านในรูปแบบ Plain Text (ข้อความที่อ่านได้) ในฐานข้อมูลเป็นเรื่องที่อันตรายอย่างยิ่งและไม่ควรทำโดยเด็ดขาด
บทความนี้จะแนะนำคุณให้รู้จักกับ Bcrypt หนึ่งในอัลกอริทึมการทำ Password Hashing ที่แข็งแกร่งและเป็นที่ยอมรับ เพื่อใช้ในการ Hash รหัสผ่านในภาษา Python ซึ่งจะช่วยให้ข้อมูลรหัสผ่านของผู้ใช้ของคุณปลอดภัยแม้ในกรณีที่ฐานข้อมูลถูกเจาะ

ทำไมต้อง Hash รหัสผ่าน และทำไมต้องเป็น Bcrypt?
การเก็บรหัสผ่านแบบ Plain Text นั้นอันตรายอย่างยิ่ง หากฐานข้อมูลถูกบุกรุก รหัสผ่านของผู้ใช้จะตกอยู่ในมือของแฮกเกอร์ทันที
Hashing คือกระบวนการแปลงข้อมูล (ในที่นี้คือรหัสผ่าน) ให้เป็นชุดอักขระที่ไม่สามารถย้อนกลับไปหารหัสผ่านต้นฉบับได้ (One-way Function) ซึ่งต่างจากการเข้ารหัส (Encryption) ที่สามารถถอดรหัสกลับได้
แล้วทำไมต้องเลือก Bcrypt ล่ะ?
  • ออกแบบมาเพื่อ Hash รหัสผ่านโดยเฉพาะ: Bcrypt ถูกออกแบบมาเพื่อต้านทานการโจมตีแบบ Brute-force และ Dictionary Attack โดยเฉพาะ
  • Computationally Intensive: Bcrypt ถูกทำให้ทำงานช้าลงโดยใช้ "Work Factor" หรือ "Cost Factor" ยิ่งค่า Work Factor สูงเท่าไหร่ การคำนวณ Hash ก็ยิ่งใช้เวลามากขึ้นเท่านั้น การทำเช่นนี้ทำให้การโจมตีแบบเดาสุ่มทำได้ยากและใช้เวลานานมาก แม้ว่าเครื่องคอมพิวเตอร์จะทรงพลังขึ้นในอนาคต เราก็สามารถเพิ่ม Work Factor เพื่อรักษาความปลอดภัยได้
  • ใช้ Salt อัตโนมัติ: Bcrypt จะสร้าง Salt (ค่าสุ่มที่ไม่ซ้ำกัน) และผนวกเข้าไปใน Hash Output โดยอัตโนมัติ ทำให้รหัสผ่านเดียวกันถูก Hash ออกมาได้ค่าที่ไม่ซ้ำกันในแต่ละครั้ง ซึ่งช่วยป้องกัน Rainbow Table Attack ได้อย่างมีประสิทธิภาพ
เริ่มต้นใช้งาน Bcrypt ใน Python
ในการใช้ Bcrypt ใน Python เราจะใช้ไลบรารีที่ชื่อว่า bcrypt ซึ่งคุณสามารถติดตั้งได้ผ่าน pip:

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

pip install bcrypt
การ Hash รหัสผ่านด้วย Bcrypt
ขั้นตอนแรกคือการนำรหัสผ่าน Plain Text ที่ผู้ใช้ป้อนเข้ามา (เช่น ตอนสมัครสมาชิก) มา Hash ก่อนจะเก็บลงในฐานข้อมูล

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

import bcrypt

def hash_password(password):
    # เปลี่ยน password string เป็น bytes (bcrypt ทำงานได้เฉพาะ bytes)
    password_bytes = password.encode('utf-8')

    # สร้าง salt และ hash password
    # สร้าง generates a random salt
    # สามารถเพิ่มเติมได้เอง เช่น bcrypt.gensalt(rounds=14)
    hashed_password = bcrypt.hashpw(password_bytes, bcrypt.gensalt())
    
    return hashed_password

# --- ตัวอย่างการใช้งาน ---
plain_password = "MySuperSecurePassword123!"
hashed_pwd = hash_password(plain_password)

print(f"Plain Password: {plain_password}")
print(f"Hashed Password: {hashed_pwd.decode('utf-8')}") # แปลงกับเป็น string 
ผลลัพธ์
Python Knowledge-1.png
Python Knowledge-1.png (4.34 KiB) Viewed 113 times
คำอธิบายโค้ด:
  • password.encode('utf-8'): Bcrypt ทำงานกับข้อมูลแบบ bytes ดังนั้นเราจึงต้องแปลง String ของรหัสผ่านให้เป็น bytes ก่อน
  • bcrypt.gensalt(): ฟังก์ชันนี้จะสร้าง Salt แบบสุ่มที่ไม่ซ้ำกันในแต่ละครั้งที่เรียกใช้ ค่า rounds (Work Factor) เริ่มต้นคือ 12 ซึ่งเป็นค่าที่เหมาะสมสำหรับ Bcrypt ในปัจจุบัน
  • bcrypt.hashpw(password_bytes, bcrypt.gensalt()): นี่คือฟังก์ชันหลักที่ใช้ในการ Hash รหัสผ่าน มันจะนำรหัสผ่านและ Salt ที่สร้างขึ้นมาใช้ในการคำนวณ Hash
การตรวจสอบรหัสผ่านด้วย Bcrypt
เมื่อผู้ใช้พยายามเข้าสู่ระบบ คุณจะต้องนำรหัสผ่านที่ผู้ใช้ป้อนเข้ามาไปเปรียบเทียบกับ Hash ที่เก็บอยู่ในฐานข้อมูล ซึ่ง bcrypt ก็มีฟังก์ชันสำหรับทำสิ่งนี้โดยเฉพาะ

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

import bcrypt
def verify_password(plain_password, hashed_password):
    # แปลง  string to bytes
    plain_password_bytes = plain_password.encode('utf-8')

    # Verify the password
    return bcrypt.checkpw(plain_password_bytes, hashed_password)
ตัวอย่างการใช้งาน

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

import bcrypt

def hash_password(password):
    # เปลี่ยน password string เป็น bytes (bcrypt ทำงานได้เฉพาะ bytes)
    password_bytes = password.encode('utf-8')

    # สร้าง salt และ hash password
    # สร้าง generates a random salt
    # สามารถเพิ่มเติมได้เอง เช่น bcrypt.gensalt(rounds=14)
    hashed_password = bcrypt.hashpw(password_bytes, bcrypt.gensalt())
    
    return hashed_password

def verify_password(plain_password, hashed_password):
    # แปลง  string to bytes
    plain_password_bytes = plain_password.encode('utf-8')

    # Verify the password
    return bcrypt.checkpw(plain_password_bytes, hashed_password)

# --- ตัวอย่างการใช้งาน ---
plain_password = "MySuperSecurePassword123!"
hashed_pwd = hash_password(plain_password)

if verify_password(plain_password, hashed_pwd):
    print(f"Plain Password: '{plain_password}' - Login successful!")
else:
    print(f"'{plain_password}' - Login failed!")

print(f"Hashed Password: {hashed_pwd.decode('utf-8')}") # แปลงกับเป็น string 
ผลลัพธ์
Python Knowledge-2.png
Python Knowledge-2.png (4.67 KiB) Viewed 113 times
คำอธิบายโค้ด:
- bcrypt.checkpw(plain_password_bytes, hashed_password): ฟังก์ชันนี้จะทำการ Hash รหัสผ่านที่ผู้ใช้ป้อนเข้ามาโดยใช้ Salt และ Work Factor ที่ดึงมาจาก hashed_password ที่เก็บไว้ จากนั้นจึงนำผลลัพธ์มาเปรียบเทียบกัน หากตรงกันจะคืนค่า True หากไม่ตรงจะคืนค่า False
- สำคัญ: คุณไม่จำเป็นต้องดึง Salt หรือ Work Factor ออกมาจาก Hash เอง bcrypt.checkpw จัดการให้ทั้งหมดแล้ว

การจัดการ Work Factor (Cost Factor)
Work Factor (หรือ rounds ใน bcrypt.gensalt()) เป็นตัวกำหนดความยากในการคำนวณ Hash ยิ่งค่าสูง ก็ยิ่งปลอดภัย แต่ก็ยิ่งใช้เวลาในการประมวลผลนานขึ้น
- ค่าเริ่มต้นคือ 12 ซึ่งเป็นค่าที่เหมาะสมในปัจจุบัน
- คุณสามารถปรับค่านี้ได้ หากฮาร์ดแวร์ของคุณมีประสิทธิภาพสูงขึ้น หรือหากคุณต้องการเพิ่มความปลอดภัยในอนาคต

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

import bcrypt

# Hash with a higher work factor (e.g., 14)
higher_cost_hashed_pwd = bcrypt.hashpw(b"anotherPassword", bcrypt.gensalt(rounds=14))
print(f"Hashed with cost 14: {higher_cost_hashed_pwd.decode('utf-8')}")
คำอธิบายโค้ด:
- b"anotherPassword" คือการทำให้เป็น bytes
- bcrypt.gensalt(rounds=14) คือ จำนวน rounds ที่ใช้ในการคำนวณ Hash

ข้อควรพิจารณา: การเพิ่ม Work Factor จะส่งผลต่อเวลาในการ Login หรือ Register เนื่องจากต้องใช้เวลาในการคำนวณ Hash นานขึ้น คุณควรทดสอบให้แน่ใจว่าค่าที่เลือกไม่ส่งผลกระทบต่อประสบการณ์ผู้ใช้มากเกินไป

สรุป
การใช้ Bcrypt ในการ Hash รหัสผ่านใน Python เป็นแนวทางปฏิบัติที่สำคัญและเป็นมาตรฐานสำหรับความปลอดภัยของข้อมูลผู้ใช้ ด้วยไลบรารี bcrypt คุณสามารถ Hash รหัสผ่านและตรวจสอบความถูกต้องได้อย่างง่ายดายและมีประสิทธิภาพ โดยไม่ต้องกังวลเรื่องการจัดการ Salt หรือ Work Factor ที่ซับซ้อน ซึ่งถูกจัดการให้อัตโนมัติโดยไลบรารีนี้
นอกจากนี้ Bcrypt ยังออกแบบมาให้ต้านทานการโจมตีแบบ Brute-force และ Rainbow Table ได้ดี โดยสามารถปรับระดับความยาก (work factor) ได้ตามความต้องการ เพื่อให้เหมาะสมกับสภาพแวดล้อมและทรัพยากรของระบบของคุณอย่างปลอดภัยและยืดหยุ่น

อ้างอิง
- https://www.mindphp.com/บทความ/31-ความร ... h-e-w.html
- viewtopic.php?f=79&t=116426
- https://www.mindphp.com/คู่มือ/73-คืออะ ... ออะไร.html
- viewtopic.php?t=105393
- https://github.com/pyca/bcrypt/
- https://www.mindphp.com/บทความ/244-secu ... ation.html
ตอบกลับโพส
  • Similar Topics
    ตอบกลับ
    แสดง
    โพสต์ล่าสุด

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

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