💡 Key Takeaways
- What Hash Functions Actually Do (And Why You Should Care)
- MD5: The Broken Algorithm That Won't Die
- SHA-256: The Cryptographic Workhorse
- bcrypt: Purpose-Built for Password Security
Tôi vẫn nhớ ngày tôi phải giải thích với Giám đốc điều hành của chúng tôi tại sao toàn bộ cơ sở dữ liệu người dùng của chúng tôi bị xâm phạm. Đó là năm 2016, tôi đã là một kỹ sư bảo mật trong tám năm, và tôi nghĩ rằng mình biết mình đang làm gì. Chúng tôi đã sử dụng MD5 để băm mật khẩu—một quyết định được đưa ra nhiều năm trước khi tôi gia nhập—và một kẻ tấn công đã phá vỡ 87% trong số 340,000 mật khẩu người dùng của chúng tôi chỉ trong chưa đầy 48 giờ. Lỗi bảo mật đó đã tốn của chúng tôi 2,3 triệu đô la cho việc khắc phục, vô vàn giờ làm việc của kỹ sư, và gần như đã phá hủy danh tiếng của chúng tôi. Bài học đau đớn đó đã dạy tôi một điều quan trọng: hiểu các hàm băm không còn là tùy chọn cho các nhà phát triển nữa. Nó là điều cơ bản.
💡 Những Ý Chính
- Hàm Băm Thực Sự Làm Gì (Và Tại Sao Bạn Nên Quan Tâm)
- MD5: Thuật Toán Hỏng Không Chịu Chết
- SHA-256: Mã Hóa Đáng Tin Cậy
- bcrypt: Được Thiết Kế Riêng Cho An Ninh Mật Khẩu
Ngày nay, với tư cách là một kiến trúc sư bảo mật chính với 15 năm kinh nghiệm, tôi đã xem xét hàng trăm mã nguồn và tư vấn cho nhiều công ty khởi nghiệp. Các sai lầm giống nhau cứ lặp đi lặp lại. Các nhà phát triển coi các hàm băm như những "hộp đen" có thể thay thế được, chọn MD5 vì nó "nhanh" hoặc SHA-256 vì nghe có vẻ an toàn. Nhưng đây là sự thật: chọn sai hàm băm giống như lắp đặt một cánh cửa lưới trên một chiếc tàu ngầm. Nó có thể trông giống như an ninh, nhưng nó sẽ không cứu bạn khi áp lực gia tăng.
Hàm Băm Thực Sự Làm Gì (Và Tại Sao Bạn Nên Quan Tâm)
Chúng ta hãy bắt đầu với những điều cơ bản. Một hàm băm nhận đầu vào có kích thước bất kỳ và tạo ra một đầu ra cố định có kích thước được gọi là băm hoặc tổng kết. Hãy nghĩ về nó như một dấu vân tay toán học. Bạn đưa vào "password123" và nhận lại một cái gì đó như "482c811da5d5b4bc6d497ffa98491e38". Đầu vào giống nhau luôn tạo ra đầu ra giống nhau, nhưng chỉ cần một thay đổi nhỏ—như "password124"—sẽ tạo ra một hàm băm hoàn toàn khác.
Hành vi xác định này làm cho các hàm băm trở nên cực kỳ hữu ích. Tôi sử dụng chúng hàng ngày để kiểm tra độ toàn vẹn dữ liệu, chữ ký số, lưu trữ mật khẩu và khóa cache. Nhưng đây là điều mà hầu hết các nhà phát triển bỏ qua: không phải tất cả các hàm băm đều được tạo ra như nhau, và việc sử dụng sai hàm băm có thể gây thảm họa.
Các hàm băm có ba đặc tính quan trọng. Thứ nhất, chúng là các hàm một chiều—bạn không thể đảo ngược quá trình để lấy lại đầu vào ban đầu. Thứ hai, chúng có tính kháng va chạm, có nghĩa là sẽ không thể thực hiện được hành vi tính toán để tìm hai đầu vào khác nhau mà tạo ra cùng một hàm băm. Thứ ba, chúng thể hiện hiệu ứng bão tuyết, trong đó một thay đổi nhỏ trong đầu vào tạo ra một đầu ra khác biệt hoàn toàn.
Trong công việc tư vấn của tôi, tôi đã thấy các nhà phát triển nhầm lẫn các hàm băm với mã hóa. Điều này là rất nguy hiểm. Mã hóa có thể đảo ngược với khóa đúng; băm thì không. Khi bạn mã hóa dữ liệu, bạn lên kế hoạch để giải mã nó sau. Khi bạn băm dữ liệu, bạn đang tạo ra một chuyển đổi một chiều. Tôi từng kiểm tra một công ty khởi nghiệp trong lĩnh vực chăm sóc sức khỏe mà họ đã "mã hóa" mật khẩu bằng AES và lưu trữ các khóa trong cùng một cơ sở dữ liệu. Họ nghĩ rằng họ đang an toàn. Họ thì không.
Các tác động thực tế rất lớn. Theo Báo cáo Điều Tra Vi phạm Dữ liệu Verizon 2023, 86% các vụ vi phạm liên quan đến thông tin xác thực bị đánh cắp. Nếu bạn đang lưu trữ mật khẩu không đúng cách, bạn không chỉ đang đặt nguy cơ cho người dùng của mình—mà còn cho toàn bộ doanh nghiệp của bạn. Tôi đã chứng kiến các công ty phải đóng cửa sau các sự cố bảo mật mà nếu có băm đúng cách thì có thể đã tránh được.
MD5: Thuật Toán Hỏng Không Chịu Chết
MD5 (Thuật toán Tổng Kết Tin Nhắn 5) được thiết kế bởi Ronald Rivest vào năm 1991. Nó tạo ra giá trị băm 128-bit, thường được biểu diễn dưới dạng một số thập lục phân 32 ký tự. Trong hơn một thập kỷ, nó là hàm băm được sử dụng cho mọi thứ từ lưu trữ mật khẩu đến kiểm tra tính toàn vẹn của tệp. Rồi chúng tôi phát hiện ra rằng nó về cơ bản đã bị hỏng.
"Sự khác biệt giữa MD5 và bcrypt không chỉ là kỹ thuật—đó là sự khác biệt giữa một vụ vi phạm tốn hàng triệu và một vụ vi phạm chỉ gây bất tiện. Hãy chọn hàm băm của bạn như thể sự sống còn của công ty bạn phụ thuộc vào đó, vì thực sự là như vậy."
Cú tấn công va chạm đầu tiên chống lại MD5 đã được công bố vào năm 2004 bởi Xiaoyun Wang và nhóm của cô ấy. Họ đã chứng minh rằng hai đầu vào khác nhau có thể tạo ra cùng một hàm băm MD5 chỉ trong vài giờ tính toán. Đến năm 2012, các nhà nghiên cứu có thể tạo ra các va chạm MD5 chỉ trong vài giây trên phần cứng tiêu dùng. Ngày nay, với điện toán đám mây, bạn có thể tạo ra các va chạm với khoảng 0,65 đô la thời gian tính toán AWS.
Tôi vẫn thường xuyên gặp MD5 trong các hệ thống sản xuất. Tháng trước, tôi đã xem xét một ứng dụng fintech xử lý 50 triệu đô la giao dịch hàng tháng. Họ đã sử dụng MD5 để băm các mã thông báo API. Khi tôi chỉ ra lỗ hổng, nhà phát triển chính đã nói: "Nhưng chúng tôi chỉ sử dụng nó cho các bản kiểm tra, không phải mật khẩu." Điều này hoàn toàn bỏ lỡ điểm mấu chốt. Lỗ hổng va chạm của MD5 làm cho nó không phù hợp cho bất kỳ ứng dụng nào quan trọng về an ninh.
Dưới đây là một ví dụ cụ thể về nguy cơ. Một kẻ tấn công có thể tạo ra hai tệp thực thi khác nhau với cùng một hàm băm MD5. Họ gửi phiên bản vô hại để kiểm tra mã, được phê duyệt, sau đó thay thế bằng phiên bản độc hại. Kiểm tra tổng hợp MD5 của bạn vượt qua, nhưng bạn vừa triển khai phần mềm độc hại. Đây không phải là lý thuyết—điều này đã xảy ra trong các vụ tấn công thực tế, bao gồm phần mềm độc hại Flame đã khai thác các va chạm MD5 trong chữ ký mã của Microsoft.
Tốc độ lúc trước khiến MD5 trở nên hấp dẫn giờ đây lại là điểm yếu lớn nhất của nó. Trên phần cứng hiện đại, bạn có thể tính toán khoảng 8 tỷ hàm băm MD5 mỗi giây chỉ với một GPU. Điều này làm cho các cuộc tấn công brute-force trở nên dễ dàng đến mức tầm thường. Tôi đã thực hiện một bài kiểm tra trên trạm làm việc của mình với NVIDIA RTX 4090: tôi đã phá vỡ một cơ sở dữ liệu của 100,000 mật khẩu đã băm MD5 trong 47 phút. Các mật khẩu không yếu—chúng có trung bình 10 ký tự với chữ hoa và chữ số. MD5 không thể bảo vệ chống lại sức mạnh máy tính hiện đại.
Dù vậy, MD5 vẫn tồn tại. Tôi thấy nó trong các hệ thống lỗi thời, trong các kịch bản vội vàng, trong các bài hướng dẫn không được cập nhật từ năm 2010. Các nhà phát triển chọn nó vì nó nhanh, vì nó quen thuộc, vì "chúng tôi không lưu trữ bất cứ điều gì quan trọng." Nhưng bảo mật không hoạt động theo cách đó. Bạn không thể chỉ an toàn một phần. Hoặc hàm băm của bạn là an toàn về mặt mật mã, hoặc nó là một trách nhiệm chờ bùng nổ.
SHA-256: Mã Hóa Đáng Tin Cậy
SHA-256 là một phần của gia đình SHA-2, được thiết kế bởi NSA và được công bố vào năm 2001. Nó tạo ra giá trị băm 256-bit, thường được thể hiện dưới dạng một chuỗi thập lục phân 64 ký tự. Khác với MD5, SHA-256 vẫn an toàn về mặt mật mã. Không có cuộc tấn công va chạm thực tiễn nào tồn tại, và nó là nền tảng của cơ sở hạ tầng bảo mật hiện đại, bao gồm thuật toán proof-of-work của Bitcoin.
| Hàm Băm | Tốc Độ | Trường Hợp Sử Dụng | Tình Trạng An Ninh |
|---|---|---|---|
| MD5 | Cực Nhanh (~300 MB/s) | Các bản kiểm tra, ứng dụng không bảo mật | Bị Hỏng Về Mặt Mật Mã - Không bao giờ sử dụng cho mật khẩu |
| SHA-256 | Rất Nhanh (~150 MB/s) | Chữ ký số, chứng chỉ, tính toàn vẹn của tệp | An toàn cho tính toàn vẹn, công cụ sai cho mật khẩu |
| bcrypt | Cố Tình Chậm (có thể điều chỉnh) | Băm mật khẩu | Chuẩn ngành - thiết kế cho mật khẩu |
| Argon2 | Cố Tình Chậm (có thể điều chỉnh) | Băm mật khẩu, phát sinh khóa | Chuẩn hiện đại - người chiến thắng trong Cuộc Thi Băm Mật Khẩu |
| PBKDF2 | Chậm Có Thể Cấu Hình | Băm mật khẩu, hệ thống cũ | Chấp nhận được nhưng ưu tiên bcrypt/Argon2 |
Tôi sử dụng SHA-256 rất rộng rãi, nhưng có những điểm cần lưu ý quan trọng. Nó rất tốt cho tính toàn vẹn dữ liệu, chữ ký số và ứng dụng blockchain. Nó nhanh—máy tính xách tay của tôi có thể tính toán khoảng 500 triệu hàm băm SHA-256 mỗi giây—điều này làm cho nó hoàn hảo để xác minh tải xuống tệp hoặc tạo các hệ thống lưu trữ dựa trên nội dung. Git sử dụng SHA-1 (người tiền nhiệm của SHA-256) cho đúng mục đích này.
Nhưng đây là nơi các nhà phát triển gặp sai lầm: họ sử dụng SHA-256 để băm mật khẩu. Điều này có vẻ hợp lý—nó an toàn, nó nhanh, nó được khuyến nghị bởi các tiêu chuẩn bảo mật. Vấn đề là "nhanh" chính xác là điều bạn không muốn cho băm mật khẩu. Nhớ rằng 500 triệu hàm băm mỗi giây không? Điều đó có nghĩa là một kẻ tấn công với một GPU khá có thể cố gắng 500 triệu lần đoán mật khẩu mỗi giây.
Hãy để tôi minh họa với những con số thực tế. Gần đây tôi đã thử nghiệm tấn công băm mật khẩu chống lại các hàm băm SHA-256 bằng cách sử dụng hashcat trên một hệ thống với bốn GPU RTX 4090. Thiết lập đó tiêu tốn khoảng 8,000 đô la và có thể tính toán 200 tỷ hàm băm SHA-256 mỗi giây. Với tốc độ đó, tôi có thể ép hết toàn bộ không gian của các mật khẩu 8 ký tự (sử dụng chữ hoa, chữ thường và số) trong khoảng 3.5 giờ. Ngay cả khi có một salt—mà bạn nên luôn sử dụng—tốc độ của SHA-256 khiến các cuộc tấn công brute-force trở nên hiệu quả tới mức đáng sợ.
Các trường hợp sử dụng thích hợp cho SHA-256 là khi bạn cần bảo mật mật mã nhưng không cần lưu trữ mật khẩu. Tôi sử dụng nó cho các triển khai HMAC (Mã Xác Thực Tin Nhắn Dựa Trên Băm), nơi tôi xác minh rằng một thông điệp không bị giả mạo. Tôi sử dụng nó để tạo ra các ID xác định từ nội dung. Tôi sử dụng nó trong chuỗi chứng chỉ và chữ ký số. Những ứng dụng này hưởng lợi từ tốc độ và bảo mật của SHA-256.
Một mô hình tôi khuyến nghị là sử dụng SHA-256 như một phần của hàm phát sinh khóa, nhưng không bao giờ riêng lẻ. Ví dụ, trong một dự án gần đây, chúng tôi cần tạo ra các khóa mã hóa từ mật khẩu người dùng. Chúng tôi đã sử dụng PBKDF2 với SHA-256 là hàm băm nền tảng, ru