iT邦幫忙

2021 iThome 鐵人賽

DAY 4
2
Modern Web

ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#系列 第 4

Day 4 - Using Argon2 for Salted Password Hashing with ASP.NET Web Forms C# 使用 Argon2 替密碼加鹽後雜湊加密

=x= 🌵 User Manager - Content Page 替後台管理者密碼加鹽加密。


密碼加鹽加密介紹 :

📌 後台的所有頁面建議可先上網找套版用的免費資源,由於要講到密碼加密,所以先從存資料開始,後面會再回頭講登入頁如何驗證密碼,本篇重點在於使用 Argon2 替密碼加鹽後加密再存到資料庫,流程為新增使用者的帳號密碼後,會先判斷帳號是否重複,如果帳號重複則拒絕,帳號不重複則進行密碼加密流程,密碼加密前先用鹽(Salt)產生隨機一段字串,並將鹽存入資料庫,然後將密碼與鹽組成一段字串再進行雜湊(Hash),結合處理完的密碼才存到資料庫,鹽要分開存的原因是因為之後登入時要用來驗證密碼,更詳細的觀念可以參考下面提供的連結。

本來一開始沒做加密,後來隨便找了內建的 SHA256 做加密,再後來看到後端版再聊加密的事就認真看完討論串,開始爬專有名詞,也了解加鹽可以增加原本密碼的複雜度增加安全性,密碼是先加鹽再雜湊加密,不要順序搞混很重要,而由於雜湊是不可從結果逆推回原始輸入的演算法,所以輸入的內容複雜度就很重要,可以降低被暴力破解的可能,這也是為什麼要密碼要加鹽的原因,了解後就試著跟著做做看吧!

👀 雜湊跟加密的不同參考文章 : Password Storage Cheat Sheet

👀 入門強烈推薦好文1 : 聽說不能用明文存密碼,那到底該怎麼存?

👀 入門強烈推薦好文2 : 密碼存明碼,怎麼不直接去裸奔算了?淺談 Hash , 用雜湊保護密碼

🧠 上面有提到加鹽,一開始聽到加鹽其實搞不太懂到底在做啥,看完文章才有概念。

👹 題外話: 想查加密原理時,很常在討論看到類似"你是真的想知道,還是你想做什麼 ?"



User Manager - Argon2 加密實作 :

🧠 前面提到因為看到後端版在討論加密,建議使用 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 stretchingCryptographic hash functionSalt (cryptography)BLAKE (hash function)

🦠 嗯~ 很多看不懂的東西呢~ 開始實作~

1. MSSQL 建立 Tayana 資料庫並新增管理者資料表

https://ithelp.ithome.com.tw/upload/images/20210918/20139487vCKNqQkyVd.jpg

  • 資料表大概長這樣,account 可以右鍵修改 "索引鍵" 將型別設成 "唯一索引鍵",避免自己手殘亂加,C# 後置程式碼也會先做檢查有無重複的帳號才加入帳號。

2. 建立套版的 Master Page 並增加使用者管理的排版 Content Page

https://ithelp.ithome.com.tw/upload/images/20210918/20139487M4F8gQuUYx.jpg


3. 在後置程式碼中拿掉象徵老闆 ID 1 的刪除鍵避免老闆刪除自己 ? !

  • 在 .aspx 的 GridView 新增 OnDataBound 事件,事件後置程式碼參考如下 :
protected void OnDataBind(object sender, EventArgs e)
{
    GridView1.Rows[0].Cells[6].Controls.Clear();
}
  • 🙈 ( 這樣老闆就能改內容,可以刪掉別人,但是不能刪掉自己摟~ )

  • 👀 GridView 資料繫結選擇不把密碼秀出來,因為不想處理加密過的密碼,減少製作時的難度。

4. 去 Nuget 安裝 Konscious.Security.Cryptography.Blake2

https://ithelp.ithome.com.tw/upload/images/20210918/201394871V941SiZG2.jpg


5. 後置程式碼加入 Argon2 加密功能如下

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);
}

6. 在新增按鈕點擊事件中,進行檢查帳號有無重複、取欄位填入密碼並與新增的鹽一起加密、資料庫新增"帳號"+"密碼加鹽加密後的結果"+"鹽"

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;
    }

}


7. 檢查資料表是不是有成功存進資料,完成~



本日總結 :

📢 密碼學的東西由於非本科,老實說看不太懂,所以只能盡量跟著參考文章進行,不過看完找到的入門強烈推薦好文,覺得懂了好多東西,有原來加鹽要這樣加的體悟,雖然維基百科的內容有超級多看不懂的地方,不過還是很有趣,實作的 SQL 寫法也都用最簡單就能做到的方式,希望大家看得懂。

  • 明日將介紹如何製作後台登入頁及 Argon2 如何驗證密碼。

上一篇
Day 3 - Using the Gmail SMTP Server to Send Emails with ASP.NET Web Forms C# 使用 Gmail 做為郵件伺服器來寄信
下一篇
Day 5 - Using Argon2 for Password Verifying with ASP.NET Web Forms C# 使用 Argon2 驗證密碼
系列文
ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

2
龜人
iT邦新手 3 級 ‧ 2021-12-16 23:13:58

Nuget 安裝 Konscious.Security.Cryptography.Blake2 後
請檢查方案的參考內是否有以下內容 :
Konscious.Security.Cryptography.Blake2
Konscious.Security.Cryptography.Argon2
如果發現缺少 .Argon2 請至 Nuget 加裝以下套件
https://ithelp.ithome.com.tw/upload/images/20211216/20139487ZaPyNqIt4B.jpg

我要留言

立即登入留言