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

ASP.NET C# 3DES 加密解密完整實作:CryptoHelper 最佳實踐指南

     編輯:ASP.NET 基礎

設計目標

  • 採用 **TripleDES (3DES)** 對稱加密,兼容舊系統。
  • 金鑰 (Key) 與初始向量 (IV) 從 **設定檔** 讀取,不硬編碼。
  • 提供 **靜態輔助類**,封裝 `ICryptoTransform`、`CryptoStream` 細節。
  • 正確處理 **資源釋放**、**異常捕獲**、**Base64 編碼** 輸出。

設定檔區段


<configuration>
  <appSettings>
    <add key="DES_Key" value="KIPSToILGp6fl+3gXJvMsN4IajizYBBT" /> <!-- 24 bytes Base64 = 192 bits -->
    <add key="DES_IV"  value="SuFjcEmp/TE=" />                           <!-- 8 bytes Base64 = 64 bits -->
  </appSettings>
</configuration>

生成金鑰腳本 (一次性執行存入設定檔):


using (var tdes = new TripleDESCryptoServiceProvider())
{
    tdes.GenerateKey(); tdes.GenerateIV();
    Console.WriteLine("Key: " + Convert.ToBase64String(tdes.Key));
    Console.WriteLine("IV:  " + Convert.ToBase64String(tdes.IV));
}

CryptoHelper 完整實作


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

public static class CryptoHelper
{
    private static readonly byte[] _key = Convert.FromBase64String(ConfigurationManager.AppSettings["DES_Key"]);
    private static readonly byte[] _iv  = Convert.FromBase64String(ConfigurationManager.AppSettings["DES_IV"]);

    /// 加密字串 → Base64 密文
    public static string Encrypt(string plainText)
    {
        if (string.IsNullOrEmpty(plainText)) return string.Empty;

        using (var tdes = new TripleDESCryptoServiceProvider { Key = _key, IV = _iv, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
        using (var ms = new MemoryStream())
        using (var cs = new CryptoStream(ms, tdes.CreateEncryptor(), CryptoStreamMode.Write))
        using (var sw = new StreamWriter(cs, Encoding.UTF8))
        {
            sw.Write(plainText);
            sw.Flush(); // 關鍵:確保資料寫入 CryptoStream
            cs.FlushFinalBlock();
            return Convert.ToBase64String(ms.ToArray());
        }
    }

    /// Base64 密文 → 解密明文
    public static string Decrypt(string cipherBase64)
    {
        if (string.IsNullOrEmpty(cipherBase64)) return string.Empty;

        try
        {
            byte[] cipherBytes = Convert.FromBase64String(cipherBase64);
            using (var tdes = new TripleDESCryptoServiceProvider { Key = _key, IV = _iv, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
            using (var ms = new MemoryStream(cipherBytes))
            using (var cs = new CryptoStream(ms, tdes.CreateDecryptor(), CryptoStreamMode.Read))
            using (var sr = new StreamReader(cs, Encoding.UTF8))
            {
                return sr.ReadToEnd();
            }
        }
        catch (CryptographicException)
        {
            // 金鑰錯誤、資料竄改、Padding 無效
            return null; // 或拋出自訂異常
        }
        catch (FormatException)
        {
            // 非合法 Base64
            return null;
        }
    }
}

關鍵實作細節解析

細節說明
CipherMode.CBC密碼分組鏈接模式,需 IV,比 ECB 安全。
PaddingMode.PKCS7標準填充,跨平台相容 (Java/Python 同規格)。
StreamWriter/StreamReader自動處理 UTF-8 編碼轉換,避免手動 GetBytes 錯誤。
sw.Flush() + cs.FlushFinalBlock()確保所有緩衝區資料經過加密寫入 MemoryStream。
using 區塊巢狀保證 CryptoStream、MemoryStream、TripleDES 正確 Dispose,釋放非託管資源。
靜態唯讀金鑰應用程式啟動讀取一次,效能最佳;若需熱更新可改用 Lazy/設定監聽。

使用範例


string original = "機敏資料:身分證 A123456789";
string encrypted = CryptoHelper.Encrypt(original); // "N8lAaHMFtSAQgaf3+RUFng=="
string decrypted = CryptoHelper.Decrypt(encrypted); // 還原原文

Console.WriteLine($"加密: {encrypted}");
Console.WriteLine($"解密: {decrypted}");

安全性與現代化建議

議題建議
3DES 已棄用NIST 建議遷移至 **AES-256-GCM** (認證加密),提供機密性+完整性。
金鑰管理生產環境應使用 **Azure Key Vault / HashiCorp Vault / AWS KMS**,勿存於 web.config。
IV 重複使用CBC 模式下同一 Key 必須搭配**隨機 IV**,建議每次加密產生新 IV 並前綴於密文。
完整性驗證3DES-CBC 无認證標籤,易受 Padding Oracle 攻擊。改用 AES-GCM 或額外加 HMAC-SHA256。

AES-GCM 現代化實作片段 (.NET Core 3.1+)


public static class AesGcmHelper
{
    public static (byte[] cipher, byte[] nonce, byte[] tag) Encrypt(byte[] key, byte[] plain)
    {
        var nonce = new byte[12]; // GCM 建議 96-bit nonce
        RandomNumberGenerator.Fill(nonce);
        var tag = new byte[16];
        var cipher = new byte[plain.Length];
        using (var aes = new AesGcm(key))
            aes.Encrypt(nonce, plain, cipher, tag);
        return (cipher, nonce, tag);
    }

    public static byte[] Decrypt(byte[] key, byte[] nonce, byte[] cipher, byte[] tag)
    {
        var plain = new byte[cipher.Length];
        using (var aes = new AesGcm(key))
            aes.Decrypt(nonce, cipher, tag, plain);
        return plain;
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved