首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

C# DES 加密解密完整實現:ECB/CBC 模式、PKCS7 填充、Base64 編碼、鑰匙管理最佳實踐

     編輯:更多程式設計知識

DES (Data Encryption Standard) 是 56 位密鑰的對稱分組加密算法,雖已被 AES 取代,但在維護舊系統、對接老接口、嵌入式設備通信等場景仍廣泛使用。本文提供生產級 C# 實現,涵蓋 ECB/CBC 模式、PKCS7 填充、Base64 編碼、初始化向量 (IV) 處理、鑰匙派生、異常處理與安全最佳實踐。

核心實現類


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

public static class DesEncryption {
    // 默認密鑰與 IV (僅演示,生產環境嚴禁硬編碼!)
    private const string DefaultKey = "VavicApp"; // 8 字節 = 64 位 (含 8 位校驗位,實際 56 位有效)
    private const string DefaultIV  = "VavicApp"; // CBC 模式必須 8 字節 IV

    /// 
    /// DES 加密 (CBC 模式 + PKCS7 填充 + Base64 輸出)
    /// 
    public static string Encrypt(string plainText, string key = null, string iv = null, CipherMode mode = CipherMode.CBC) {
        if (string.IsNullOrEmpty(plainText)) return string.Empty;
        key ??= DefaultKey;
        iv ??= DefaultIV;

        ValidateKeyIV(key, iv);

        using var des = DES.Create();
        des.Key = Encoding.ASCII.GetBytes(key.PadRight(8).Substring(0, 8)); // 強制 8 字節
        des.IV  = Encoding.ASCII.GetBytes(iv.PadRight(8).Substring(0, 8));
        des.Mode = mode;
        des.Padding = PaddingMode.PKCS7;

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

    /// 
    /// DES 解密
    /// 
    public static string Decrypt(string cipherText, string key = null, string iv = null, CipherMode mode = CipherMode.CBC) {
        if (string.IsNullOrEmpty(cipherText)) return string.Empty;
        key ??= DefaultKey;
        iv ??= DefaultIV;

        ValidateKeyIV(key, iv);

        byte[] cipherBytes;
        try {
            cipherBytes = Convert.FromBase64String(cipherText);
        } catch (FormatException) {
            throw new CryptographicException("無效的 Base64 密文");
        }

        using var des = DES.Create();
        des.Key = Encoding.ASCII.GetBytes(key.PadRight(8).Substring(0, 8));
        des.IV  = Encoding.ASCII.GetBytes(iv.PadRight(8).Substring(0, 8));
        des.Mode = mode;
        des.Padding = PaddingMode.PKCS7;

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

    private static void ValidateKeyIV(string key, string iv) {
        if (string.IsNullOrEmpty(key) || key.Length < 8) throw new ArgumentException("密鑰必須至少 8 字符");
        if (string.IsNullOrEmpty(iv) || iv.Length < 8) throw new ArgumentException("IV 必須至少 8 字符");
    }
}

使用示例


string original = "敏感數據:身份證 11010119900307893X、銀行卡 6225880123456789";
string encrypted = DesEncryption.Encrypt(original);
string decrypted = DesEncryption.Decrypt(encrypted);

Console.WriteLine($"原文: {original}");
Console.WriteLine($"密文: {encrypted}");   // 輸出 Base64 字符串
Console.WriteLine($"解密: {decrypted}");
Console.WriteLine($"驗證: {original == decrypted}"); // True

關鍵參數深度解析

參數推薦值說明
AlgorithmDES固定 64 位塊大小,56 位有效密鑰
ModeCBC (Cipher Block Chaining)**首選**。引入 IV,相同明文加密出不同密文,抵抗模式分析。ECB 模式不安全,僅用於兼容極老系統
PaddingPKCS7填充至 8 字節倍數。.NET PaddingMode.PKCS7 等同 PKCS#5
Key8 字節 (64 位)第 8、16、24...56 位為奇偶校驗位,實際熵 56 位。**嚴禁硬編碼**,需從 KMS/環境變量/安全存儲讀取
IV8 字節,隨機生成**每次加密必須隨機生成新 IV**,與密文一起存儲/傳輸(通常前綴在密文前)。不可重複使用相同 Key+IV
EncodingUTF-8明文轉字節編碼,雙方約定一致
Output EncodingBase64二進制密文安全傳輸編碼

生產級增強:隨機 IV + 密文格式規範


public static class DesEncryptionV2 {
    // 密文格式: [IV(8 bytes)][CipherText...] -> Base64
    public static string EncryptWithRandomIV(string plainText, string key) {
        if (string.IsNullOrEmpty(plainText)) return string.Empty;
        ValidateKey(key);

        using var des = DES.Create();
        des.Key = Encoding.ASCII.GetBytes(key.PadRight(8).Substring(0, 8));
        des.Mode = CipherMode.CBC;
        des.Padding = PaddingMode.PKCS7;
        des.GenerateIV(); // 自動生成隨機 IV

        using var ms = new MemoryStream();
        ms.Write(des.IV, 0, des.IV.Length); // 寫入 IV 作為密文頭
        using var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
        using var sw = new StreamWriter(cs, Encoding.UTF8);
        sw.Write(plainText);
        sw.Flush();
        cs.FlushFinalBlock();
        return Convert.ToBase64String(ms.ToArray());
    }

    public static string DecryptWithRandomIV(string cipherText, string key) {
        if (string.IsNullOrEmpty(cipherText)) return string.Empty;
        ValidateKey(key);

        byte[] fullBytes = Convert.FromBase64String(cipherText);
        if (fullBytes.Length < 8) throw new CryptographicException("密文過短,不含 IV");

        using var des = DES.Create();
        des.Key = Encoding.ASCII.GetBytes(key.PadRight(8).Substring(0, 8));
        des.Mode = CipherMode.CBC;
        des.Padding = PaddingMode.PKCS7;

        byte[] iv = new byte[8];
        Array.Copy(fullBytes, 0, iv, 0, 8);
        des.IV = iv;

        byte[] cipherBytes = new byte[fullBytes.Length - 8];
        Array.Copy(fullBytes, 8, cipherBytes, 0, cipherBytes.Length);

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

    private static void ValidateKey(string key) {
        if (string.IsNullOrEmpty(key) || key.Length < 8) throw new ArgumentException("密鑰至少 8 字符");
    }
}

鑰匙管理最佳實踐(必讀)

  1. 絕不硬編碼密鑰:使用 Azure Key Vault、AWS KMS、HashiCorp Vault、Kubernetes Secrets、環境變量注入。
  2. 密鑰輪換:定期 (90-180 天) 生成新密鑰,舊密文重新加密或標記版本解密。
  3. 密鑰派生:若密鑰來自口令,使用 PBKDF2/Argon2/scrypt:
    var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 100000, HashAlgorithmName.SHA256); var key = pbkdf2.GetBytes(8);
  4. 最小權限:加密服務與業務服務分離,業務服務僅持有加密 API 權限,不知明文密鑰。
  5. 審計日誌:記錄每次加密/解密操作的請求者、時間、數據標識(不記明文/密文)。

遷移建議:DES → AES

新系統**強制使用 AES-256-GCM** (或 AES-256-CBC+HMAC-SHA256):


using var aes = Aes.Create();
aes.KeySize = 256;
aes.Mode = CipherMode.GCM; // .NET 6+ 支持 GCM,內置認證加密
aes.GenerateKey();
aes.GenerateIV();
// 加密
using var encryptor = aes.CreateEncryptor();
var cipher = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
var tag = aes.GetTag(); // GCM 認證標籤
// 存儲: IV + Cipher + Tag

AES 優勢:128/192/256 位密鑰、128 位塊大小、硬件加速 (AES-NI)、認證加密模式 (GCM/CCM) 防篡改、無已知實用攻擊。

常見陷阱排查

解密報錯 Bad Data / Padding is invalid
1. Key/IV 不匹配 2. 密文被截斷/修改 3. Base64 解碼錯誤 (含換行/空格) 4. Padding 模式不一致 5. 編碼不一致 (加密 UTF-8,解密用 ASCII)
中文解密亂碼
明文編碼與解密編碼不一致。統一使用 Encoding.UTF8。
跨平台 (Windows/Linux) 解密失敗
.NET Core/5/6+ 跨平台一致。舊 .NET Framework 可能依賴 CAPI/CNG 實現差異,統一遷移至 .NET 6+。
性能問題
DES 極慢 (轉為 AES 硬件加速)。大數據分塊流式加密 (CryptoStream),避免全量載入內存。

雖然 DES 已退出歷史舞台,但理解其模式、填充、IV、鑰匙管理原理,是掌握現代對稱加密 (AES、ChaCha20-Poly1305) 的基石。維護舊系統時請嚴格遵循「隨機 IV、密鑰外部化、認證加密」原則,將風險降至最低。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved