MD5 vs SHA-256 — Tại Sao Bạn Nên Ngừng Dùng MD5
MD5 ở khắp nơi. Nó có trong mọi ngôn ngữ lập trình, mọi cơ sở dữ liệu, mọi SDK của nhà cung cấp đám mây. Các nhà phát triển tiếp cận nó theo thói quen — nó nhanh, tạo ra một chuỗi hex 32 ký tự gọn gàng, và API là hai dòng code. Vấn đề: MD5 đã bị phá vỡ về mặt mật mã kể từ năm 2004, và các cuộc tấn công chỉ ngày càng nhanh hơn và rẻ hơn kể từ đó.
Đây không phải lý thuyết. Một cuộc tấn công mạng năm 2012 vào hạ tầng Iran — malware Flame — đã giả mạo một chứng chỉ ký mã Microsoft bằng cách khai thác một va chạm MD5. Cùng kỹ thuật mà các nhà mật mã học học thuật đã chứng minh trong một bài báo trở thành một vũ khí được dùng trong gián điệp địa chính trị. MD5 không bị suy yếu nhẹ; nó cơ bản bị xâm phạm cho bất kỳ ứng dụng nào nơi đối thủ có thể chọn đầu vào.
SHA-256, một phần của họ SHA-2 được chuẩn hóa bởi NIST, không có các cuộc tấn công va chạm được biết và vẫn là tiêu chuẩn cho tính toàn vẹn mật mã năm 2026. Bài viết này giải thích chính xác sự khác biệt có ý nghĩa gì, khi nào (hiếm khi) MD5 vẫn chấp nhận được, và cách di chuyển an toàn. Bạn có thể tính cả hai băm ngay lập tức với các công cụ Toova MD5 hash và Toova SHA-256 hash.
Cách Hàm Băm Hoạt Động
Một hàm băm mật mã nhận một đầu vào có độ dài bất kỳ và tạo ra một đầu ra độ dài cố định (digest) với các thuộc tính này:
- Xác định: cùng đầu vào luôn tạo ra cùng đầu ra.
- Hiệu ứng tuyết lở: một thay đổi một bit trong đầu vào hoàn toàn thay đổi đầu ra.
- Kháng preimage: cho một băm, không khả thi về mặt tính toán để tìm đầu vào.
- Kháng va chạm: không khả thi về mặt tính toán để tìm hai đầu vào khác nhau tạo ra cùng băm.
Hiệu ứng tuyết lở là lý do tại sao cả MD5 và SHA-256 trông tương tự nhau thoạt nhìn:
MD5("The quick brown fox jumps over the lazy dog")
= 9e107d9d372bb6826bd81d3542a419d6
MD5("The quick brown fox jumps over the lazy cog")
= 1055d3e698d289f2af8663725127bd4b SHA-256("The quick brown fox jumps over the lazy dog")
= d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
SHA-256("The quick brown fox jumps over the lazy cog")
= e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be Một ký tự thay đổi trong đầu vào ("dog" → "cog"), tuy nhiên đầu ra hoàn toàn khác. Thuộc tính này áp dụng cho cả hai thuật toán. Sự khác biệt là điều gì xảy ra khi một kẻ tấn công cố ý tìm một va chạm.
MD5 — Lịch Sử Thất Bại (1996–2025)
MD5 được thiết kế bởi Ron Rivest năm 1991 như sự thay thế cho MD4. Đến năm 1996, Hans Dobbertin đã tìm thấy các va chạm trong hàm nén của MD5 — không phải toàn bộ thuật toán, nhưng một dấu hiệu cảnh báo rằng thiết kế dễ vỡ. Cộng đồng bảo mật bắt đầu khuyến nghị di chuyển sang SHA-1. Hầu hết các hệ thống bỏ qua điều này.
2004 — Các va chạm đầy đủ được chứng minh
Vào tháng 8 năm 2004, Xiaoyun Wang và Hongbo Yu đã trình bày một cuộc tấn công va chạm thực tế trên MD5 tại hội nghị CRYPTO. Họ có thể tạo hai thông điệp 1.024-bit khác nhau với cùng băm MD5 trong dưới một giờ trên một cluster. Đảm bảo cơ bản của MD5 — kháng va chạm — đã bị phá vỡ.
NIST ngay lập tức bắt đầu loại bỏ MD5 cho sử dụng liên bang. Hầu hết hướng dẫn ngành đã theo sau. Việc triển khai MD5 thực tế trong các hệ thống production hầu như không thay đổi.
2008 — Các chứng chỉ CA giả mạo
Một nhóm các nhà nghiên cứu (Sotirov, Stevens, và cộng sự) đã chứng minh rằng họ có thể tạo một chứng chỉ Certificate Authority giả mạo sẽ được tin tưởng bởi tất cả các trình duyệt chính. Cuộc tấn công đã khai thác việc nhiều tổ chức cấp chứng chỉ vẫn đang ký các chứng chỉ với MD5. Các nhà nghiên cứu đã tạo một va chạm giữa một yêu cầu chứng chỉ trông hợp lệ và một chứng chỉ CA tự tạo — sau đó nhận được một CA thực để ký cái hợp lệ, tạo ra một chữ ký cũng hợp lệ cho chứng chỉ CA giả.
Mọi trình duyệt chính ngay lập tức chặn các chứng chỉ được ký MD5. Hầu hết các tổ chức cấp chứng chỉ ngừng cấp chúng. Một bài học chính: các điểm yếu mật mã trở nên có thể khai thác vào thời điểm một kẻ tấn công kiểm soát đầu vào cho hàm băm.
2012 — Malware Flame
Malware gián điệp mạng Flame, được phát hiện năm 2012 và được quy cho các tác nhân nhà nước, đã giả mạo một chứng chỉ Windows Update của Microsoft bằng một va chạm MD5 tiền tố được chọn. Cuộc tấn công phức tạp hơn so với chứng minh năm 2008: những kẻ tấn công có thể tạo một payload độc hại va chạm với một chứng chỉ Microsoft hợp lệ dưới các điều kiện nơi hạ tầng ký của Microsoft sẽ hợp tác mà không hay biết.
Kết quả: Flame có thể tự phân phối qua Windows Update như thể nó là một bản cập nhật Microsoft hợp lệ, với một chữ ký Microsoft hợp lệ. Hàng trăm nghìn máy Windows ở Iran, Lebanon, Syria và Sudan đã bị nhiễm. Đây là một khai thác thực tế các cuộc tấn công va chạm MD5 ở quy mô quốc gia. Xem bài viết Wikipedia về malware Flame để có lịch sử đầy đủ.
2019–2025 — HashClash và các va chạm tức thì
Dự án HashClash (Marc Stevens, CWI Amsterdam) tiếp tục đẩy việc tạo va chạm MD5 đến các giới hạn thực tế. Đến năm 2019, các va chạm MD5 tiền tố được chọn — nơi một kẻ tấn công có thể chọn các tiền tố tùy ý cho cả hai thông điệp va chạm — có thể được tạo trong vài ngày trên phần cứng phổ thông. Đến năm 2022, các triển khai tối ưu hóa đã giảm điều này xuống còn vài giờ. Năm 2024, một bài báo HashClash đã chứng minh các va chạm trong dưới một phút trên một GPU hiện đại duy nhất.
Quỹ đạo rõ ràng: các cuộc tấn công va chạm MD5 không trở nên khó hơn khi phần cứng cải thiện — chúng trở nên dễ hơn. Điều cần một cluster năm 2004 cần một laptop năm 2026.
SHA-256 — Tại Sao Nó Vẫn Vững
SHA-256 là một phần của họ SHA-2, được thiết kế bởi NSA và chuẩn hóa bởi NIST năm 2001. Nó tạo ra một digest 256-bit (32 byte). Không có cuộc tấn công va chạm thực tế nào chống lại SHA-256 được biết kể từ năm 2026. Các cuộc tấn công được công bố tốt nhất giảm hệ số làm việc lý thuyết để tìm va chạm xuống khoảng 2^187 phép toán — vẫn vượt xa bất kỳ tài nguyên tính toán nào tồn tại hoặc dự kiến.
Biên độ bảo mật của SHA-256 cố ý bảo thủ. Ngay cả khi phần cứng cải thiện theo hệ số một tỷ (khoảng 30 nhân đôi theo thuật ngữ định luật Moore), phá vỡ SHA-256 vẫn không khả thi về mặt tính toán. Hệ số làm việc hiệu quả 2^18 đến 2^23 của MD5 cho các va chạm nằm trong tầm với của phần cứng khiêm tốn năm 2004.
SHA-256 cũng nhanh hơn bạn có thể mong đợi: các CPU hiện đại bao gồm các lệnh SHA chuyên dụng (Intel SHA Extensions, ARM Cryptography Extensions) cho phép phần mềm tính hàng triệu băm SHA-256 mỗi giây trên mỗi core. Nó không chậm hơn đáng kể so với MD5 cho các trường hợp sử dụng điển hình.
Khi MD5 Vẫn Chấp Nhận Được (Hiếm Khi)
"Bị phá vỡ" không có nghĩa là "vô dụng cho mọi mục đích." MD5 vẫn chấp nhận được trong các ngữ cảnh nơi:
- Không có đối thủ: phát hiện hỏng tệp ngẫu nhiên trong một hệ thống nội bộ đáng tin cậy — không xác minh các bản tải xuống từ internet, mà kiểm tra xem một bản sao tệp đã hoàn thành thành công hay không.
- Tốc độ quan trọng hơn bảo mật: tính các khóa cache hoặc các định danh shard nơi một va chạm đơn giản có nghĩa là một cache miss, không phải là một lỗ hổng bảo mật. Mô hình kẻ tấn công vắng mặt.
- Bạn đang khớp với một hệ thống bên ngoài hiện có: một số API cũ vẫn gửi các ETag hoặc tổng kiểm tra MD5. Bạn có thể chấp nhận và tính MD5 để tương tác, miễn là bạn không dùng nó cho các quyết định bảo mật.
- Phân vùng bảng băm: phân phối dữ liệu qua các bucket bởi MD5 của một khóa. Va chạm ở đây gây mất cân bằng, không phải các thất bại bảo mật.
Sợi chỉ chung: MD5 chấp nhận được khi ứng dụng không phụ thuộc vào kháng va chạm và không có kẻ tấn công nào có thể tạo các đầu vào. Ngay khi một trong các điều kiện đứt — kẻ tấn công có mặt, hoặc va chạm = thất bại bảo mật — chuyển sang SHA-256.
Các Truyền Thuyết Phổ Biến Về MD5
"MD5 ổn nếu chúng tôi thêm một salt"
Salting thay đổi đầu vào để hai người dùng với cùng mật khẩu nhận các băm khác nhau — nó ngăn ngừa các cuộc tấn công bảng cầu vồng. Nhưng nó không khắc phục vấn đề va chạm. Một kẻ tấn công với băm MD5 đã salt vẫn có thể brute-force nó hiệu quả vì MD5 nhanh: các GPU hiện đại tính khoảng 10–30 tỷ băm MD5 mỗi giây. Một salt thêm công việc tỷ lệ với không gian tìm kiếm, không phải với độ khó của thuật toán.
Đối với băm mật khẩu, cả MD5 và SHA-256 đều không phù hợp bất kể salting. Dùng bcrypt, scrypt hoặc Argon2.
"MD5 ổn vì chúng tôi chỉ dùng nội bộ"
Các hệ thống nội bộ bị xâm phạm. Mô hình mối đe dọa "kẻ tấn công không thể truy cập các đầu vào của chúng tôi" có xu hướng giữ vững cho đến khi một cuộc tấn công chuỗi cung ứng, một mối đe dọa nội bộ, hoặc một cấu hình sai làm lộ hệ thống. Cuộc tấn công Flame đã xảy ra chống lại các hệ thống có lẽ có niềm tin tương tự vào các kiểm soát nội bộ của họ.
"SHA-256 là quá mức — MD5 nhanh hơn"
Trên phần cứng hiện đại với các lệnh gia tốc SHA, SHA-256 chậm hơn khoảng 2–5 lần so với MD5. Đối với hầu hết các ứng dụng — kiểm tra tính toàn vẹn tệp, chữ ký API, các khóa cache — sự khác biệt là micro giây mỗi phép toán, không thể nhận thấy trong thực tế. Lập luận hiệu năng cho MD5 hơn SHA-256 chỉ giữ trong các kịch bản thông lượng cực cao nơi ngay cả micro giây quan trọng, và ngay cả khi đó thường có các giải pháp tốt hơn so với việc dùng một thuật toán bị phá vỡ.
Hướng Dẫn Di Chuyển — MD5 Sang SHA-256
Băm mật khẩu
// SAI: MD5 cho băm mật khẩu
const crypto = require('crypto');
const hash = crypto.createHash('md5').update(password).digest('hex');
// Thời gian crack với GPU hiện đại: vài giây đến vài phút // SAI: SHA-256 cho băm mật khẩu (vẫn quá nhanh)
const crypto = require('crypto');
const hash = crypto.createHash('sha256').update(password).digest('hex');
// ĐÚNG: dùng bcrypt, scrypt hoặc Argon2 cho mật khẩu
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12); Di chuyển các băm mật khẩu được lưu trữ yêu cầu một cách tiếp cận dần dần. Trên mỗi lần đăng nhập thành công: xác minh mật khẩu đối với băm MD5 hiện có, sau đó ngay lập tức băm lại với bcrypt và thay giá trị được lưu trữ. Đánh dấu mỗi tài khoản là đã di chuyển. Sau một khoảng thời gian hợp lý (90 ngày là điển hình), buộc đặt lại mật khẩu cho bất kỳ tài khoản còn lại nào vẫn dùng băm MD5.
Tính toàn vẹn tệp / tổng kiểm tra
# Linux: xác minh tệp đã tải xuống
sha256sum -c ubuntu-24.04-desktop-amd64.iso.sha256
# macOS
shasum -a 256 ubuntu-24.04-desktop-amd64.iso
# Windows PowerShell
Get-FileHash ubuntu-24.04-desktop-amd64.iso -Algorithm SHA256 Chuyển các kiểm tra tính toàn vẹn tệp từ MD5 sang SHA-256 thường là một thao tác tìm-và-thay trong code đơn giản. Hai bẫy: (1) các tổng kiểm tra hiện có được lưu trữ trong cơ sở dữ liệu hoặc tệp cần được tính lại và cập nhật — không có lối tắt; (2) các API hoặc hệ thống lưu trữ bên ngoài cung cấp ETag MD5 (như một số cấu hình S3) yêu cầu phối hợp để chuyển.
HMAC cho xác thực API
// HMAC-SHA-256 cho xác thực thông điệp
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', process.env.SECRET_KEY)
.update(message)
.digest('hex'); Nếu bạn dùng HMAC-MD5 cho ký yêu cầu API, chuyển sang HMAC-SHA-256. Cấu trúc HMAC thêm một khóa bí mật, hạn chế một số cuộc tấn công MD5, nhưng HMAC-MD5 có các lỗ hổng mở rộng độ dài và primitive cơ bản vẫn bị xâm phạm. Các tiêu chuẩn hiện đại (JWT, AWS SigV4, OAuth 2.0) đều chỉ định HMAC-SHA-256. Trình tạo HMAC của Toova hỗ trợ cả HMAC-SHA-256 và HMAC-SHA-512 để kiểm tra.
Chữ ký số và chứng chỉ
Bất kỳ chứng chỉ nào được ký với MD5 nên được phát hành lại ngay lập tức — hầu hết các tổ chức cấp chứng chỉ ngừng cấp các chứng chỉ được ký MD5 sau năm 2008, và tất cả các trình duyệt và hệ điều hành chính từ chối chúng. Đối với PKI nội bộ, kiểm toán cấu hình CA của bạn và đảm bảo SHA-256 là thuật toán chữ ký tối thiểu được phép. RSA-SHA256 hoặc ECDSA-SHA256 là các tiêu chuẩn hiện tại.
MD5 vs SHA-256 — Tham Khảo Nhanh
| Thuộc tính | MD5 | SHA-256 |
|---|---|---|
| Độ dài đầu ra | 128 bit (32 ký tự hex) | 256 bit (64 ký tự hex) |
| Kháng va chạm | Bị phá vỡ (các cuộc tấn công thực tế) | An toàn (không có cuộc tấn công nào được biết) |
| Băm mật khẩu | Không bao giờ | Không (dùng bcrypt/Argon2) |
| Chữ ký số | Không bao giờ | Có |
| Tính toàn vẹn tệp (bảo mật) | Không bao giờ | Có |
| Tổng kiểm tra không bảo mật | Chấp nhận được (không có kẻ tấn công) | Luôn ổn |
| Khóa cache | Chấp nhận được | Luôn ổn |
| Ký chứng chỉ TLS | Bị trình duyệt từ chối | Tiêu chuẩn |
| Tuân thủ FIPS 140-3 | Không (đã lỗi thời) | Có |
Kết Luận
MD5 đã bị phá vỡ về mặt mật mã kể từ năm 2004. Các va chạm tiền tố được chọn — kỹ thuật cung cấp năng lượng cho malware Flame — giờ đã rẻ về mặt tính toán. Bất kỳ ứng dụng nào dựa vào MD5 cho bảo mật (chữ ký, xác minh tính toàn vẹn, xác thực) đều dễ bị tổn thương trước các cuộc tấn công tốn vài phút thời gian tính toán để thực thi.
SHA-256 không có cuộc tấn công thực tế nào được biết, được gia tốc phần cứng trên các CPU hiện đại, và là tiêu chuẩn cho tính toàn vẹn mật mã qua TLS, ký mã và xác thực API. Chi phí hiệu năng so với MD5 là không đáng kể cho gần như mọi trường hợp sử dụng.
Đường dẫn di chuyển đơn giản: các kiểm tra tính toàn vẹn tệp là một thao tác tìm-và-thay. Các chữ ký API yêu cầu phối hợp một bump phiên bản. Các băm mật khẩu cần một chiến lược băm lại dần dần khi đăng nhập. Đối với bất kỳ code mới nào, SHA-256 nên là lựa chọn mặc định. Tính và so sánh các băm trực tiếp với Toova MD5 và Toova SHA-256 — hoặc tạo các mã xác thực HMAC-SHA-256 với trình tạo HMAC.