C# Argon2 雜湊示範

先使用 NuGet 安裝 Konscious.Security.Cryptography.Argon2 套件,或是使用 .NET CLI 執行以下指令安裝
	
dotnet add package Konscious.Security.Cryptography.Argon2
    

使用示範:
    
        static void Main()
        {

            // 範例密碼
            var password = "P@ssw0rd!";
            Console.WriteLine($"Password: {password}");

            // 雜湊參數
            // memoryKb: 使用的記憶體大小(KB) -> 65536 KB = 64 MB
            // iterations: 迭代次數
            // degreeOfParallelism: 平行度(通常設為 CPU 核心數)
            var memoryKb = 65536; // 64 MB
            var iterations = 4;
            var degreeOfParallelism = Environment.ProcessorCount; // 自動填入 CPU 核心數量

            // 產生隨機鹽值(salt)
            var salt = GenerateRandomSalt(16);

            // 產生雜湊(hash),長度 32 bytes
            var hash = HashPassword(password, salt, memoryKb, iterations, degreeOfParallelism, 32);

            // 自訂儲存格式:Base64(salt) + '.' + Base64(hash)
            var stored = Convert.ToBase64String(salt) + "." + Convert.ToBase64String(hash);
            Console.WriteLine($"Stored (salt.hash): {stored}");

            // 驗證(正確密碼)
            var ok = VerifyPassword(password, stored, memoryKb, iterations, degreeOfParallelism);
            Console.WriteLine($"Verification (correct password): {ok}");

            // 驗證(錯誤密碼)
            var wrong = VerifyPassword("wrong-password", stored, memoryKb, iterations, degreeOfParallelism);
            Console.WriteLine($"Verification (wrong password): {wrong}");
        }

        // 產生隨機鹽值
        // 輸入: size = 欲產生的位元組數
        // 輸出: 隨機的 byte[] 鹽值
        static byte[] GenerateRandomSalt(int size)
        {
            var salt = new byte[size];
            using var rng = RandomNumberGenerator.Create();
            rng.GetBytes(salt);
            return salt;
        }

        // 使用 Argon2id 雜湊密碼
        // 輸入:
        //   password: 要雜湊的密碼字串
        //   salt: 已生成的鹽值
        //   memoryKb: 記憶體大小(KB)
        //   iterations: 迭代次數
        //   degreeOfParallelism: 平行度
        //   hashLength: 要回傳的雜湊長度(bytes)
        // 輸出: 雜湊後的 byte[]
        static byte[] HashPassword(string password, byte[] salt, int memoryKb, int iterations, int degreeOfParallelism, int hashLength)
        {
            // 將密碼轉為 UTF-8 bytes
            var passwordBytes = Encoding.UTF8.GetBytes(password);

            // 建立 Argon2id 實例並設定參數
            var argon2 = new Argon2id(passwordBytes)
            {
                Salt = salt,
                DegreeOfParallelism = degreeOfParallelism,
                MemorySize = memoryKb,
                Iterations = iterations
            };

            // 取得指定長度的雜湊
            return argon2.GetBytes(hashLength);
        }

        // 驗證密碼是否符合已儲存的 hash
        // 輸入:
        //   password: 要驗證的密碼字串
        //   stored: 儲存的字串(上方指定格式為 Base64(salt) + '.' + Base64(hash))
        //   memoryKb, iterations, degreeOfParallelism: 與雜湊相同的參數
        // 輸出: bool,若相同則回傳 true
        static bool VerifyPassword(string password, string stored, int memoryKb, int iterations, int degreeOfParallelism)
        {
            // 將儲存字串以 '.' 分割為 salt 與 hash(皆為 Base64)
            var parts = stored.Split('.');
            if (parts.Length != 2)
                return false;

            var salt = Convert.FromBase64String(parts[0]);
            var expectedHash = Convert.FromBase64String(parts[1]);

            // 使用相同參數與 salt 再次雜湊輸入密碼
            var actualHash = HashPassword(password, salt, memoryKb, iterations, degreeOfParallelism, expectedHash.Length);

            // 使用固定時間比較以避免時序攻擊
            return CryptographicOperations.FixedTimeEquals(actualHash, expectedHash);
        }
    

範例輸出:
    
Argon2id hash demo (Konscious.Security.Cryptography.Argon2)
Password: P@ssw0rd!
Stored (salt.hash): DmlJhletpUOqQGvu2D0Beg==.YV7kqHidt7Nom1q5bo0hxZexrsIZdkuQqwXR2+yBAfk=

    



參考資料:
Github - kmaragon/Konscious.Security.Cryptography

留言