Băm mật khẩu đúng cách

1/ Sử dụng scrypt, bcrypt, PBKDF2 hoặc argon2. Thuật toán nào trong số này cũng được, cứ chọn một cái mà dùng, thay thế cho MD5, SHA2, v.v.

2/ Băm _mỗi_ mật khẩu với một "muối" (salt) ngẫu nhiên dài 64 bit. Muối này không cần phải giữ bí mật, lưu chung với chỗ lưu mật khẩu cũng được.

3/ (Nâng cao) Băm _tất cả_ mật khẩu với một "tiêu" (pepper) ngẫu nhiên dài 128 bit. Tiêu này cần được giữ bí mật, lưu ở một máy chủ khác với chỗ lưu mật khẩu.

Tại sao phải làm những bước này? Tại sao thêm muối thôi không đủ? Tại sao cần phải có cả tiêu?

Các câu hỏi này tôi để dành cho các bạn sinh viên như là bài tập về nhà. Các bạn có thể trả lời vào phần comment bên dưới hoặc là email cho tôi ở thaidn@gmail.com.

Khoe cho các bạn sinh viên có cảm hứng trả lời câu hỏi: tôi thiết kế thuật toán băm mật khẩu đang được Google sử dụng để bảo vệ mật khẩu của tất cả người dùng.

Comments

Vo Tinh Thuong said…
This comment has been removed by the author.
Quân said…
Ngoài điều (1) và (2) thì làm sao chứng minh được cách thứ (3) là cách băm đúng. Chưa hẳn nó được sử dụng tại Google thì mặc định nó sẽ đúng.
Thai Duong said…
Thì bạn có thể chỉ ra nó sai ở đâu mà?

Tôi cũng không có nói là nó được sử dụng tại Google và cũng không có nói là nếu sử dụng tại Google thì nó đúng.
Quân said…
Nhưng tiêu đề bài viết là 'Băm mật khẩu đúng cách' nên em nghĩ (chắc/có thể đã có chứng minh ở đâu đó). Em chỉ hỏi về thực tế đã có chứng minh chứa, không hề có ý đả kích hay gì khác.
Thai Duong said…
Àh tôi nghĩ là đúng nhưng mà tôi cũng rất muốn biết những ý kiến khác. Không sao đâu, tôi không có thấy phiền câu hỏi của bạn.
n0c3rt said…
Mình nghĩ vầy ko biết phải ko:
1. Băm - để ngăn lộ plaintext password, tuy nhiên có thể dò tìm hash dựa theo từ điển online hoặc tự xây dựng offline sẵn có
2. Muối - Ngăn dò tìm theo các từ điển online (đa số là băm thuần). Tuy nhiên nếu attacker cố gắng để tìm ra password của 1 account cụ thể thì có thể xây dựng từ điển dựa trên muối sẵn có - hơi mất thời gian hơn
3. Tiêu - thêm tiêu và giữ tiêu bí mật, thì ngay cả khi có muối, attacker cũng ko thể xây dựng từ điển chính xác để dò tìm
Hoàng Em said…
Băm _mỗi_ mật khẩu với một "muối" (salt) ngẫu nhiên dài 64 bit:
- Muối phải độc nhất cho mỗi csdl, nhằm ngăn chặn nỗ lực tin tặc thịt được vào toàn bộ các chuỗi băm mật khẩu chỉ trong một lượt dò.
- Muối để ngăn chặn phương thức tấn công dùng bảng tổng hợp các chuỗi băm để tìm mật khẩu, có tên là rain gì đó em quên rồi...khi tấn công vét cạn, tin tặc không thể tạo ra tất cả các khả năng trong một lần, mà sẽ phải vét cạn từng mật khẩu kèm muối, kéo dài thời gian hơn.
Băm _tất cả_ mật khẩu với một "tiêu" (pepper) ngẫu nhiên dài 128 bit. Tiêu này cần được giữ bí mật, lưu ở một máy chủ khác với chỗ lưu mật khẩu.:
- Cần giữ bí mật thằng Tiêu này vì nếu Tiêu này vào tay tin tặc thì CSDL mình đúng nghĩa là tiêu thật :D
X said…
Em chào anh. Em không phải là SV, cũng ko phải là dân bảo mật, em là DEV 3 năm kinh nghiệm nhưng tự thấy vẫn là fresher :D Tuy nhiên, em xin phép trả lời 1 cách nghiêm túc theo ý hiểu của em.

1. Với MD5: cùng input thì output luôn giống nhau
Bcrypt thì trong nó đã có sẵn salt => mỗi lần mã hóa 1 input sẽ có output khác nhau.
=> bcrypt > md5

2. Việc thêm muối sẽ giúp hacker khó tìm ra thuật toán mã khóa, tránh brute force theo kiểu tạo 1 CSDL mapping password với hash chẳng hạn. Vì việc nhét muối theo thứ tự nào cũng gây khó dễ nhất định rồi.
Em xin bỏ qua về phần độ dài 64 bit vì em ko biết.

3. Sẽ là lý tưởng nếu muối là private, nhưng như thế sẽ phải lưu trữ list muối đó trong 1 CSDL mới. Mà theo lý thuyết CSDL đó vẫn có thể bị hack :D
=> nên focus lưu tiêu duy nhất và cố gắng bảo vệ 1 mình nó thôi :D

// Gõ đến đây em thấy không tự tin đúng và em hi vọng 1 ngày nào đó a sẽ viết một post cụ thể hơn về chủ đề này ạ.

// Hiện nay đa phần Dev xung quanh em và em đều chỉ dùng sẵn cơ chế Auth mà các framework support nên ko đi sâu vào việc tổ chức hay thiết kế thuật toán mã hóa :(
quangntenemy said…
Theo tôi băm mật khẩu cũng giống băm thịt khi làm món thịt năm viên, nó tuỳ khẩu vị mỗi người.
Bản thân tôi thì thường cho thêm gia vị + hành. Muối hay tiêu cho thêm 1 ít cũng được nhưng chỉ là phụ thôi.
Nếu chỉ muối thì mặn , thêm tiêu nữa cay lại ngon . ^^
Nghia Nguyen said…
Muối là để khiến việc giải mã tất cả mật khẩu của khách hàng trở nên khó kh n.
Tiêu là để khiến việc giải mã mật khẩu của một khách hàng nhất định trở nên khó kh ăn (ví dụ khách hàng đó có thể là một nhân vật đặc biệt nào đó).
Dee Lan said…
Vậy trong trường hợp xấu nhất cryto algo bị decrypted ngược lại theo cách 51-51 trong block chain thì sao ?
Thu Nguyen Dang said…
Ý kiến cá nhân về việc băm mật khẩu:

1. Sử dụng các thuật toán như md5, sha1, sha2 đơn thuần không đủ để đảm bảo mật khẩu không bị giải mã với tấn công brute force bởi với sức mạnh của GPU và công cụ như hashcat, người ta có thể thử lên tới hàng tỷ mật khẩu mỗi giây. Các thuật toán như bcrypt,... làm cho việc brute force trở nên khó khăn vì cùng với 1 sức mạnh GPU để thử hàng tỷ mật khẩu cho md5, aes, người ta chỉ có thể thử được vài chục ngàn mật khẩu mỗi giây với brypt.

2. Giả sử sử dụng md5, hay sha1. Việc băm mật khẩu với 1 salt sẽ tránh cho việc kẻ tấn công sử dụng những cơ sở dữ liệu về mã hash như hashkiller để tìm ra mật khẩu một cách nhanh chóng với việc search.

3. Việc băm thêm mật khẩu với 1 tiêu thì có lẽ là chiến lược: "không để tất cả trứng trong cùng một giỏ". Ví dụ như 1 ứng dụng web có lỗ hổng sql injection, kẻ tấn công lấy được salt, password hash cũng không thể thực hiện tấn công brute force giải mã mật khẩu được vì thiếu mất pepper.
Unknown said…
Hi anh

Em có thắc mắc về phần tích hợp của ngân lượng (https://www.nganluong.vn//data/developer_home/NL_checkout_v2.7_vn.doc)
Ở đây mỗi request gửi lên server của ngân lượng phải thêm một checksum, họ tính checksum bằng cách:
MD5(parameters + mật khẩu giao dịch). Theo em hiểu là để kiểm tra data integrity và authentication.

Như vậy rõ ràng họ phải lưu mật khẩu giao dịch dạng plaintext thì mới kiểm tra checksum được. Nếu coi mật khẩu giao dịch là secret key thì đúng là có thể lưu plaintext (hoặc mã hoá bởi một key dùng chung).

Theo anh cách làm trên có vấn đề gì và best practices là gì ạ?

Thanks anh.