=x= 🌵 User Manager - Content Page 替後台管理者密碼加鹽加密。
📌 後台的所有頁面建議可先上網找套版用的免費資源,由於要講到密碼加密,所以先從存資料開始,後面會再回頭講登入頁如何驗證密碼,本篇重點在於使用 Argon2 替密碼加鹽後加密再存到資料庫,流程為新增使用者的帳號密碼後,會先判斷帳號是否重複,如果帳號重複則拒絕,帳號不重複則進行密碼加密流程,密碼加密前先用鹽(Salt)產生隨機一段字串,並將鹽存入資料庫,然後將密碼與鹽組成一段字串再進行雜湊(Hash),結合處理完的密碼才存到資料庫,鹽要分開存的原因是因為之後登入時要用來驗證密碼,更詳細的觀念可以參考下面提供的連結。
本來一開始沒做加密,後來隨便找了內建的 SHA256 做加密,再後來看到後端版再聊加密的事就認真看完討論串,開始爬專有名詞,也了解加鹽可以增加原本密碼的複雜度增加安全性,密碼是先加鹽再雜湊加密,不要順序搞混很重要,而由於雜湊是不可從結果逆推回原始輸入的演算法,所以輸入的內容複雜度就很重要,可以降低被暴力破解的可能,這也是為什麼要密碼要加鹽的原因,了解後就試著跟著做做看吧!
👀 雜湊跟加密的不同參考文章 : Password Storage Cheat Sheet
👀 入門強烈推薦好文1 : 聽說不能用明文存密碼,那到底該怎麼存?
👀 入門強烈推薦好文2 : 密碼存明碼,怎麼不直接去裸奔算了?淺談 Hash , 用雜湊保護密碼
🧠 上面有提到加鹽,一開始聽到加鹽其實搞不太懂到底在做啥,看完文章才有概念。
👹 題外話: 想查加密原理時,很常在討論看到類似"你是真的想知道,還是你想做什麼 ?"
🧠 前面提到因為看到後端版在討論加密,建議使用 bcrypt 或 Argon2 但後者好像更優,所以最後選擇 Argon2 的來實作。
👀 實作參考資源 : How to Use Argon2 for Password Hashing in C#
👀 同上作者內文提到的必讀好文 : How to Securely Store a Password
👀 Argon2 維基百科介紹 : https://en.wikipedia.org/wiki/Argon2
👀 Wikipedia 相關參考知識 : key derivation function (KDF)、Key stretching、Cryptographic hash function 、Salt (cryptography) 、BLAKE (hash function)
🦠 嗯~ 很多看不懂的東西呢~ 開始實作~
protected void OnDataBind(object sender, EventArgs e)
{
GridView1.Rows[0].Cells[6].Controls.Clear();
}
🙈 ( 這樣老闆就能改內容,可以刪掉別人,但是不能刪掉自己摟~ )
👀 GridView 資料繫結選擇不把密碼秀出來,因為不想處理加密過的密碼,減少製作時的難度。
using System.Security.Cryptography;
using System.Text;
using Konscious.Security.Cryptography;
// Argon2 加密
//產生 Salt 功能
private byte[] CreateSalt()
{
var buffer = new byte[16];
var rng = new RNGCryptoServiceProvider();
rng.GetBytes(buffer);
return buffer;
}
// Hash 處理加鹽的密碼功能
private byte[] HashPassword(string password, byte[] salt)
{
var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password));
//底下這些數字會影響運算時間,而且驗證時要用一樣的值
argon2.Salt = salt;
argon2.DegreeOfParallelism = 8; // 4 核心就設成 8
argon2.Iterations = 4; // 迭代運算次數
argon2.MemorySize = 1024 * 1024; // 1 GB
return argon2.GetBytes(16);
}
"帳號"
+"密碼加鹽加密後的結果"
+"鹽"
protected void BtnAddAccount_Click(object sender, EventArgs e)
{
bool haveSameAccount = false;
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
string sqlCheck = "SELECT * FROM managerData WHERE account = @account";
string sqlAdd = "INSERT INTO managerData (account, password, salt) VALUES(@account, @password, @salt)";
SqlCommand commandCheck = new SqlCommand(sqlCheck, connection);
SqlCommand commandAdd = new SqlCommand(sqlAdd, connection);
//檢查有無重複帳號
commandCheck.Parameters.AddWithValue("@account", TBoxAddAccount.Text);
connection.Open();
SqlDataReader readerCountry = commandCheck.ExecuteReader();
if (readerCountry.Read()) {
haveSameAccount = true;
LabelAdd.Visible = true; //帳號重複通知
}
connection.Close();
//無重複帳號才執行加入
if (!haveSameAccount) {
//Hash 加鹽加密
string password = TBoxAddPassword.Text;
var salt = CreateSalt();
string saltStr = Convert.ToBase64String(salt); //將 byte 改回字串存回資料表
var hash = HashPassword(password, salt);
string hashPassword = Convert.ToBase64String(hash);
commandAdd.Parameters.AddWithValue("@account", TBoxAddAccount.Text);
commandAdd.Parameters.AddWithValue("@password", hashPassword);
commandAdd.Parameters.AddWithValue("@salt", saltStr);
connection.Open();
commandAdd.ExecuteNonQuery();
connection.Close();
//畫面渲染
GridView1.DataBind();
//清空輸入欄位
TBoxAddAccount.Text = "";
TBoxAddPassword.Text = "";
LabelAdd.Visible = false;
}
}
📢 密碼學的東西由於非本科,老實說看不太懂,所以只能盡量跟著參考文章進行,不過看完找到的入門強烈推薦好文,覺得懂了好多東西,有原來加鹽要這樣加的體悟,雖然維基百科的內容有超級多看不懂的地方,不過還是很有趣,實作的 SQL 寫法也都用最簡單就能做到的方式,希望大家看得懂。
Nuget 安裝 Konscious.Security.Cryptography.Blake2 後
請檢查方案的參考內是否有以下內容 :
Konscious.Security.Cryptography.Blake2
Konscious.Security.Cryptography.Argon2
如果發現缺少 .Argon2 請至 Nuget 加裝以下套件