MD5 是單向哈希,不可逆。驗證邏輯:
存儲值 = MD5(明文密碼)輸入值 = MD5(用戶輸入明文),比較 輸入值 == 存儲值<%@ Import Namespace="System.Security.Cryptography" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
string ComputeMd5(string input) {
using (MD5 md5 = MD5.Create()) {
byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
foreach (byte b in hash) sb.Append(b.ToString("x2"));
return sb.ToString();
}
}
void Login_Click(Object sender, EventArgs e) {
string pwdHash = ComputeMd5(txtPassword.Text);
string sql = "SELECT COUNT(*) FROM Users WHERE Username=@u AND PasswordHash=@p";
using (SqlConnection cn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(sql, cn)) {
cmd.Parameters.AddWithValue("@u", txtUsername.Text);
cmd.Parameters.AddWithValue("@p", pwdHash);
cn.Open();
int count = (int)cmd.ExecuteScalar();
lblResult.Text = count > 0 ? "登錄成功" : "用戶名或密碼錯誤";
}
}
</script>
<form runat="server">
用戶名: <asp:TextBox ID="txtUsername" Runat="server" /><br/>
密碼: <asp:TextBox ID="txtPassword" TextMode="Password" Runat="server" /><br/>
<asp:Button Text="登錄" OnClick="Login_Click" Runat="server" />
<asp:Label ID="lblResult" Runat="server" />
</form>
MD5(salt + password),每用戶唯一鹽值存儲在表中,防彩虹表攻擊MD5(MD5(...MD5(password)...)) 1000+ 次,增加暴力破解成本PasswordHasher)| 問題 | 影響 | 補救措施 |
|---|---|---|
| 不可逆 | 用戶忘記密碼無法找回,只能重置 | 提供「重置密碼」流程(郵箱/手機驗證 + 臨時鏈接) |
| 碰撞風險 | 理論上不同輸入產生相同哈希 | 遷移至 SHA-256+ 或 BCrypt |
| 速度過快 | GPU 可秒級嘗試億級字典 | 加鹽 + 高迭代 或 遷移慢哈希算法 |
| 舊數據遷移難 | 存量明文/弱哈希需用戶重新登錄才能升級 | 登錄時檢測舊哈希,驗證成功後重新計算強哈希覆蓋 |
-- 檢測並升級邏輯 (偽代碼)
IF stored_hash LIKE 'md5_%' THEN
IF MD5(input) == stored_hash THEN
new_hash = BCrypt.HashPassword(input)
UPDATE users SET password_hash = new_hash WHERE id = ...
RETURN SUCCESS
END IF
ELSE IF BCrypt.Verify(input, stored_hash) THEN
RETURN SUCCESS
END IF
MD5 密碼驗證僅適合學習/非核心業務。生產系統必須使用 BCrypt/Argon2/PBKDF2 等專為密碼設計的慢哈希算法,並配合加鹽、HTTPS、賬戶鎖定、審計日志等纵深防御體系。