開發 Windows 客戶端程式,若連線第三方網站或服務需要登入,沒多少使用者能忍受每用一次敲一次密碼,故記憶密碼是必備功能。

用明碼儲存密碼是天地不容的低級行為! 帳號系統存密碼應使用雜湊值,如此可做到不知密碼內容但能比對是否相符,有效降低密碼外洩風險;記憶密碼需還原使用,故不能用雜湊,但至少也要加密並妥善保存。這些是開發者的基本常識,請務必確立正確觀念,以免成為資安破口。

.NET 已內建完整的加解密 API,要實作 DES、AES 甚至公私鑰加密都不是問題,如何妥善保存才是重點。無腦做法是將加密金鑰寫死在程式裡,設定檔跟執行檔存在同一目錄,但這樣拿到兩個檔案就等同偷到儲存的密碼。若要更安全,將程式、設定檔、加密金鑰分開存放(甚至有些存在 Registry)可提高被破解的難度。

自己設計夠安全的密碼保管機制要費點心思,若客戶端是 Windows 桌面程式或 Console Application,則有個現成密碼保險箱 -- Windows 認證管理員:

認證管理員是 Windows 內建功能,由 Windows 確保只有特定登入帳號能存取,又有現成操作介面可查詢、管理,狂喝牛奶又不用養牛就是爽! 不過,Credential Management 只有 Win32 API,.NET Framework 沒提供對映程式庫,所幸 NuGet 上已有前人種好樹,讓我們在樹下乘涼喝牛奶:

CredentialManagement 程式庫的用法超級簡單,new Credential() 物件,以 target 參數識別儲存項目,.Save() 儲存、.Load() 載入,.Delete() 刪除。唯一要說明的是 CredentialType 參數,分成兩大類:Domain Credentials 跟 Generic Credentials,前者是 Windows 核心 Local Security Authority (LSA) 程序專用,一般應用程式請選 Generic。程式範例如下:

class Program
{
    static void Main(string[] args)
    {
        var targetId = "CredMan-Test";

        // 保存帳號密碼
        var cred = new Credential(
            "jeffrey", 
            // 亦可用加密過的密碼取代明碼密碼,再多一道鎖
            "this_i5_the_passw0rd", 
            targetId, 
            CredentialType.Generic);
        cred.Save();

        //讀取帳號密碼
        var storedCred = new Credential { Target = targetId };
        if (storedCred.Load())
        {
            Console.WriteLine($"Username = {storedCred.Username}");
            Console.WriteLine($"Password = {storedCred.Password}");
        }
        Console.Write("是否移除所儲存的密碼?(Y/N)");
        if (((char)Console.Read()).ToString().ToUpper() == "Y")
        {
            storedCred.Delete();
        }
    }
}

不過,由上述程式碼可知,若惡意人士知道 Windows 登入帳號密碼或取得執行身分,指定 Target 名稱即能提取密碼內容,要再提升安全性密碼內容可先用 DES 或 AES 加密再存入認證管理員,當作第二道保險。不過,當對方都能假冒你的身分執行程式,這些額外防禦的意義不大。真要做到方便又安全,加入 IC 卡、指紋... 等第二因素認證恐怕是唯一解。

Example of using Windows Credentials Management to store password.


Comments

# by Woodycheung

不好意思 暗黑大 我有一個問題一直想不通 例如我用asp.net core 3.1做開發 一開始沒打算寫xamarin 結果用了asp.net core MVC去開發網站 後來網站快做好了時想說把xamarin也一起做出來好了 那我應該把MVC中的dbcontext都掉到去新開的一個webapi好呢 還是直接在原本的MVC中再開發下去好呢?請求解答QAQ

# by Jeffrey

to Woodycheung,Xamarin 用的 WebAPI 與一般使用者訪問的網站拆開會比較好管理,安全管控與更新頻率可分開,彈性較大。DbContext 部分我會拆成獨立 Library,讓 WebAPI 與 MVC 專案共用,也就是這篇所提的情境:https://blog.darkthread.net/blog/ef-migration-in-cls-lib/

# by woodycheung

謝謝感黑大

Post a comment