Lưu mật khẩu an toàn hơn với Bcrypt

Lưu mật khẩu an toàn hơn với Bcrypt

Hầu hết chúng ta khi tập làm web hoặc một ứng dụng liên quan tới đăng nhập/xác thực người dùng thì đều được hướng dẫn là dùng các hàm tính hash như MD5/SHA… để lưu trữ mật khẩu. Để tăng độ an toàn thì có thể tạo thêm các cột gọi là “salt” cho mỗi user. Đó là một chuỗi ngẫu nhiên được thêm vào trước khi tạo ra giá trị hash cuối cùng rồi lưu vào database nhằm hạn chế bị tìm ra mật khẩu bằng các phương thức như Rainbow table, Brute-force, Dictionary attack. Cách này không còn an toàn với các chip tính toán siêu nhanh và ngày càng nhanh ngày nay. Các chíp xử lí đồ hoặc chuyên dụng GPU còn nhanh hơn gấp bội.

Tại sao? Tại vì các thuật toán tính hash được thiết kế với mục tiêu càng nhanh càng tốt. Nó thường được dùng để tạo ra checksum dùng trong việc kiểm tra sự bảo toàn của lượng dữ liệu lớn. Nếu bạn hay down các phần mềm nguồn mở hoặc miễn phí sẽ hay thấy cái này.

Vậy giải pháp là gì?


Giải pháp là sử dụng Bcrypt.

Bcrypt được thiết kế riêng cho việc bảo vệ mật khẩu. Nó chậm hơn rất nhiều so với hash functions vì quy trình tính toán phức tạp hơn, tốn nhiều công sức hơn. Bởi vậy các phương pháp tấn công có thể nhanh với MD5/SHA… ở trên cũng phải chậm theo.

Theo benchmark trên laptop với chíp Intel Core i5 của tôi nếu chọn “work factor” là 14, thì cần tới khoảng 0.4s để bcrypt tính được hash, còn đối với MD5/SHA… là khoản 0.001s (khoảng 400 lần).

Ứng dụng Bcrypt như thế nào?

Bcrypt được triển khai trong hầu hết các ngôn ngữ lập trình. Trong PHP mặc dù không có sẵn hàm bcrypt() nhưng có khá nhiều thư viện hỗ trợ việc này (trong đó có ZF2). Việc xác thực cũng tương tự như các phương thức trước đây:
- Tạo hash khi user tạo tài khoản
- Tạo hash khi user đăng nhập
- So sánh hash

Thực ra bước 2 và 3 sẽ được thực hiện bên trong bcrypt, ta chỉ cần truyền vào hash được lưu trong database và chuỗi mật khẩu mà user vừa điền khi đăng nhập.

Bcrypt sẽ tự tạo ra salt và gắn luôn vào chuỗi kết quả nên ta không cần tạo thêm column để lưu salt trong database.

Thành phần vô cùng quan trọng trong bcrypt là “work factor” như đề cập ở trên. Bcrypt sẽ lặp 2^work (2 mũ work) lần để tính hash. Nên work càng tăng, thời gian tính hash càng chậm. Một work cân bằng độ an toàn và thời gian tính toán nằm trong khoảng từ 11 tới 14 (tùy thuộc vào độ busy và sức mạnh của server).

Một column để chứa giá trị bcrypt sẽ cần tối thiểu 59 characters nếu “work factor” có 1 chữ số. Và hiện nay work chưa cần phải lớn tới hàng 3 chữ số nên một column varchar(60) là đủ dùng.

Kết hợp Zend Authentication với Bcrypt?

Cần tạo riêng một custom adapter cho Zend Authentication vì ZF không hỗ trợ sẵn kiểu authenticate với bcrypt (có lẽ chủ yếu vì các loại db không hỗ trợ sẵn bcrypt trong khi cái adapter DbTable thì dựa trên hàm hash của db).

Tham khảo:
- How to Safely Store a Password: http://codahale.com/how-to-safely-store-a-password/
- Bcrypt: http://en.wikipedia.org/wiki/Bcrypt
- Rainbow Table: http://en.wikipedia.org/wiki/Rainbow_table
- Brute-force Attack: http://en.wikipedia.org/wiki/Brute_force_attack
- Dictionary Attack: http://en.wikipedia.org/wiki/Dictionary_attack
- Bcrypt trong ZF2: http://framework.zend.com/manual/2.0/en/modules/zend.crypt.password.html
- Bcrypt: Choosing a Work Factor: http://wildlyinaccurate.com/bcrypt-choosing-a-work-factor

Nguồn: http://nducthuan.blogspot.com/

Comments

Popular Posts