首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 實作 AES (高級加密標準) 加密演算法完整教學:原理、程式碼與最佳實踐

     編輯:關於C#

AES 核心特性

  • 對稱加密:加密解密使用相同金鑰
  • 分組長度:128 bits (16 bytes)
  • 金鑰長度:128 / 192 / 256 bits
  • 輪數:10 / 12 / 14 輪 (依金鑰長度)
  • 核心運算:有限域 GF(2⁸) 上的替代 (SubBytes)、置換 (ShiftRows, MixColumns)、輪金鑰加 (AddRoundKey)

.NET 內建實作 (生產環境首選)


using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public static class AesHelper
{
    /// 
    /// AES 加密 (CBC 模式,PKCS7 填充)
    /// 
    public static string Encrypt(string plainText, byte[] key, byte[] iv)
    {
        using (var aes = Aes.Create())
        {
            aes.Key = key;           // 16/24/32 bytes
            aes.IV = iv;             // 16 bytes
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            using (var encryptor = aes.CreateEncryptor())
            using (var ms = new MemoryStream())
            using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            using (var sw = new StreamWriter(cs, Encoding.UTF8))
            {
                sw.Write(plainText);
            }
            return Convert.ToBase64String(ms.ToArray());
        }
    }

    /// 
    /// AES 解密
    /// 
    public static string Decrypt(string cipherTextBase64, byte[] key, byte[] iv)
    {
        byte[] cipherBytes = Convert.FromBase64String(cipherTextBase64);
        
        using (var aes = Aes.Create())
        {
            aes.Key = key;
            aes.IV = iv;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            using (var decryptor = aes.CreateDecryptor())
            using (var ms = new MemoryStream(cipherBytes))
            using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            using (var sr = new StreamReader(cs, Encoding.UTF8))
            {
                return sr.ReadToEnd();
            }
        }
    }

    /// 
    /// 從密碼衍生金鑰與 IV (PBKDF2)
    /// 
    public static (byte[] Key, byte[] IV) DeriveKeyAndIV(string password, byte[] salt, int keySize = 256)
    {
        using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100_000, HashAlgorithmName.SHA256))
        {
            byte[] key = pbkdf2.GetBytes(keySize / 8);
            byte[] iv = pbkdf2.GetBytes(16); // IV 固定 16 bytes
            return (key, iv);
        }
    }
}

// 使用範例
class Program
{
    static void Main()
    {
        string password = "MyStrongPassword123!";
        byte[] salt = new byte[16];
        using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(salt);

        var (key, iv) = AesHelper.DeriveKeyAndIV(password, salt, 256);
        
        string original = "機密資料:信用卡號 1234-5678-9012-3456";
        string encrypted = AesHelper.Encrypt(original, key, iv);
        string decrypted = AesHelper.Decrypt(encrypted, key, iv);

        Console.WriteLine($"原文:{original}");
        Console.WriteLine($"密文:{encrypted}");
        Console.WriteLine($"解密:{decrypted}");
        Console.WriteLine($"Salt (需儲存):{Convert.ToBase64String(salt)}");
    }
}

AES 核心數學原理速覽 (理解實作細節)

有限域 GF(2⁸) 運算

  • 元素:0x00 ~ 0xFF (256 個位元組值)
  • 加法:XOR (^) 運算
  • 乘法:模不可約多項式 x⁸ + x⁴ + x³ + x + 1 (0x11B) 的多項式乘法
  • 關鍵乘法常數:0x01, 0x02, 0x03, 0x09, 0x0B, 0x0D, 0x0E

四大輪函數

  1. SubBytes:透過 S-Box (替代盒) 進行非線性位元組替代,提供混淆性
  2. ShiftRows:狀態矩陣列向左循環位移 (第 0 列 0 位、第 1 列 1 位...),提供擴散性
  3. MixColumns:列向量在 GF(2⁸) 上與固定矩陣相乘,跨列混合
  4. AddRoundKey:狀態與輪金鑰 XOR

金鑰擴展

  • 將原始金鑰擴展為 (Nr+1) × 16 bytes 輪金鑰陣列
  • 使用 RotWord (字循環)、SubWord (S-Box 替代)、Rcon (輪常數)
  • 確保每輪金鑰差異大,抵抗關聯攻擊

手工實作 AES (教學用,非生產建議)


// 完整手工實作極長,此處展示核心結構
public class AesManual
{
    private readonly byte[,] _sBox = new byte[16,16]; // 標準 S-Box
    private readonly byte[,] _invSBox = new byte[16,16];
    private readonly byte[,] _rCon = new byte[11,4];  // Rcon[1..10]
    private byte[,] _w; // 輪金鑰陣列 [4, 4*(Nr+1)]
    private int _nr;    // 輪數

    public AesManual(byte[] key)
    {
        // 1. 依金鑰長度設定 Nr, Nk
        // 2. 建構 S-Box, InvSBox (仿射變換 + 乘法逆元)
        // 3. 建構 Rcon
        // 4. KeyExpansion() 填充 _w
    }

    private byte GF_Mul(byte a, byte b) 
    {
        // 俄羅斯農夫乘法 (位元級實作)
        byte result = 0;
        while (b > 0)
        {
            if ((b & 1) != 0) result ^= a;
            bool hiBit = (a & 0x80) != 0;
            a <<= 1;
            if (hiBit) a ^= 0x1B; // 模 x^8+x^4+x^3+x+1
            b >>= 1;
        }
        return result;
    }

    public void Encrypt(byte[] input, byte[] output) 
    {
        // 1. 載入 State[4,4]
        // 2. AddRoundKey (第 0 輪)
        // 3. for round = 1 to Nr-1: SubBytes, ShiftRows, MixColumns, AddRoundKey
        // 4. 最後一輪: SubBytes, ShiftRows, AddRoundKey (無 MixColumns)
        // 5. 輸出
    }

    public void Decrypt(byte[] input, byte[] output) 
    {
        // 逆序操作:InvShiftRows, InvSubBytes, AddRoundKey, InvMixColumns
        // InvMixColumns 使用係數 0x0E, 0x0B, 0x0D, 0x09
    }
}

模式選擇指南

模式IV 需求平行化適用場景警示
CBC必要 (隨機)解密可平行通用資料加密需 PKCS7 填充,防填充神谕攻擊
GCM必要 (Nonce)加解密可平行需認證加密 (AEAD).NET Core 3.1+ 支援 AesGcm,**強烈推薦**
CTR必要 (Counter)完全平行串流加密、隨機存取不可重複 Nonce,無完整性保護
ECB無完全平行**嚴禁用於機密資料**相同明文產生相同密文,洩漏模式

現代最佳實踐:AES-GCM (認證加密)


// .NET Core 3.1 / .NET 5+ 專用
public static class AesGcmHelper
{
    public static (byte[] CipherText, byte[] Tag) Encrypt(byte[] plainText, byte[] key, byte[] nonce)
    {
        var cipherText = new byte[plainText.Length];
        var tag = new byte[16]; // 128-bit 標籤
        using (var aes = new AesGcm(key))
        {
            aes.Encrypt(nonce, plainText, cipherText, tag);
        }
        return (cipherText, tag);
    }

    public static byte[] Decrypt(byte[] cipherText, byte[] tag, byte[] key, byte[] nonce)
    {
        var plainText = new byte[cipherText.Length];
        using (var aes = new AesGcm(key))
        {
            aes.Decrypt(nonce, cipherText, tag, plainText);
        }
        return plainText;
    }
}

關鍵安全檢查清單

  1. ✅ 永不硬編碼金鑰:使用 PBKDF2/Argon2 從密碼衍生,或 KMS/HSM 管理。
  2. ✅ 每次加密產生新隨機 IV/Nonce:使用 RandomNumberGenerator.Create()。
  3. ✅ 金鑰輪換機制:定期更換主金鑰,保留舊金鑰解密歷史資料。
  4. ✅ 使用認證加密 (GCM/CCM):同時保證機密性與完整性,防篡改。
  5. ✅ 防計時攻擊:比較標籤/金鑰用 CryptographicOperations.FixedTimeEquals。
  6. ✅ 安全銷毀敏感資料:Array.Clear(key, 0, key.Length) 或 Span.Clear()。
  7. ❌ 不要自己寫 AES 給生產用:側通道攻擊、實作錯誤風險極高,務必用經過驗證的庫 (BouncyCastle、.NET 內建)。

效能參考 (AES-256-CBC, 1MB 資料)

實作加密時間解密時間備註
.NET 內建 Aes (硬體加速 AES-NI)~8 ms~7 ms現代 CPU 內建指令集加速
.NET 內建 AesGcm~10 ms~9 ms含認證標籤計算
純 C# 手工實作~1200 ms~1100 ms無硬體加速、教學用
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved