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

C# 非對稱加密實戰:RSA 算法完整實現與金鑰管理

     編輯:關於C語言

前言

非對稱加密 (公開金鑰加密) 是現代資安基石:公鑰加密、私鑰解密 (機密性);私鑰簽名、公鑰驗證 (完整性/不可否認性)。.NET System.Security.Cryptography.RSACryptoServiceProvider 提供 FIPS 相容的 RSA 實現。本文構建完整 WinForms 示範程式:金鑰對生成、XML 格式匯入匯出、檔案持久化、字串加密解密、編碼處理、UI 交互,並解析關鍵安全細節。

核心類別設計


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

public class RsaCrypto
{
    private RSACryptoServiceProvider _rsa;

    public RsaCrypto() {
        _rsa = new RSACryptoServiceProvider(2048); // 2048-bit 金鑰
    }

    // 生成新金鑰對
    public void GenerateKeys() {
        _rsa = new RSACryptoServiceProvider(2048);
    }

    // 匯出公鑰 (XML, 不含私鑰)
    public string ExportPublicKey() {
        return _rsa.ToXmlString(false);
    }

    // 匯出私鑰 (XML, 含公私鑰)
    public string ExportPrivateKey() {
        return _rsa.ToXmlString(true);
    }

    // 從 XML 匯入公鑰
    public void ImportPublicKey(string xml) {
        _rsa.FromXmlString(xml);
    }

    // 從 XML 匯入私鑰
    public void ImportPrivateKey(string xml) {
        _rsa.FromXmlString(xml);
    }

    // 公鑰加密 (資料長度限制:KeySize/8 - 11 bytes for PKCS#1 v1.5)
    public byte[] Encrypt(string plainText, Encoding encoding = null) {
        encoding = encoding ?? Encoding.UTF8;
        byte[] data = encoding.GetBytes(plainText);
        return _rsa.Encrypt(data, false); // false = PKCS#1 v1.5, true = OAEP
    }

    // 私鑰解密
    public string Decrypt(byte[] cipherText, Encoding encoding = null) {
        encoding = encoding ?? Encoding.UTF8;
        byte[] plain = _rsa.Decrypt(cipherText, false);
        return encoding.GetString(plain);
    }

    // 簽名 (私鑰)
    public byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm = null) {
        hashAlgorithm = hashAlgorithm ?? HashAlgorithmName.SHA256;
        return _rsa.SignData(data, hashAlgorithm, RSASignaturePadding.Pkcs1);
    }

    // 驗證簽名 (公鑰)
    public bool VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm = null) {
        hashAlgorithm = hashAlgorithm ?? HashAlgorithmName.SHA256;
        return _rsa.VerifyData(data, signature, hashAlgorithm, RSASignaturePadding.Pkcs1);
    }

    // 持久化到檔案
    public void SaveKeys(string publicKeyPath, string privateKeyPath) {
        File.WriteAllText(publicKeyPath, ExportPublicKey(), Encoding.UTF8);
        File.WriteAllText(privateKeyPath, ExportPrivateKey(), Encoding.UTF8);
    }

    // 從檔案載入
    public void LoadKeys(string publicKeyPath, string privateKeyPath) {
        ImportPublicKey(File.ReadAllText(publicKeyPath, Encoding.UTF8));
        ImportPrivateKey(File.ReadAllText(privateKeyPath, Encoding.UTF8));
    }
}

WinForms 示範介面

兩個分頁:

  1. 金鑰管理:生成金鑰 → 顯示 XML → 儲存公鑰/私鑰檔案
  2. 加密解密:讀取公鑰檔 → 輸入明文 → 公鑰加密 → 顯示 Base64 密文 → 讀取私鑰檔 → 私鑰解密 → 顯示明文

關鍵代碼片段 (事件處理)


// 生成金鑰
private void btnGenerate_Click(object sender, EventArgs e) {
    _crypto.GenerateKeys();
    txtPublicKey.Text = _crypto.ExportPublicKey();
    txtPrivateKey.Text = _crypto.ExportPrivateKey();
}

// 儲存公鑰
private void btnSavePublic_Click(object sender, EventArgs e) {
    if (saveFileDialog.ShowDialog() == DialogResult.OK) {
        File.WriteAllText(saveFileDialog.FileName, txtPublicKey.Text, Encoding.UTF8);
    }
}

// 讀取公鑰
private void btnLoadPublic_Click(object sender, EventArgs e) {
    if (openFileDialog.ShowDialog() == DialogResult.OK) {
        txtPublicKey.Text = File.ReadAllText(openFileDialog.FileName, Encoding.UTF8);
    }
}

// 公鑰加密
private void btnEncrypt_Click(object sender, EventArgs e) {
    _crypto.ImportPublicKey(txtPublicKey.Text);
    byte[] cipher = _crypto.Encrypt(txtPlainText.Text);
    txtCipherText.Text = Convert.ToBase64String(cipher); // 顯示用 Base64
}

// 私鑰解密
private void btnDecrypt_Click(object sender, EventArgs e) {
    _crypto.ImportPrivateKey(txtPrivateKey.Text);
    byte[] cipher = Convert.FromBase64String(txtCipherText.Text);
    string plain = _crypto.Decrypt(cipher);
    txtDecryptedText.Text = plain;
}

關鍵安全細節與最佳實踐

主題說明建議
金鑰長度1024-bit 已不安全,2048-bit 為基準,長期機密 4096-bit建構子指定 2048 或更高
填充模式PKCS#1 v1.5 相容舊系統;OAEP (Optimal Asymmetric Encryption Padding) 更安全新系統用 Encrypt(data, true) (OAEP)
資料長度限制RSA 只能加密 KeySize/8 - padding 位元組 (2048-bit 約 245 bytes)長資料用混合加密:AES 隨機金鑰加密資料 + RSA 加密 AES 金鑰
編碼加密輸入為位元組陣列,字串需指定編碼 (UTF-8)統一用 UTF-8,跨平台安全
密文傳輸位元組陣列不可直接顯示/傳輸Base64 編碼 (如示範),或十六進位
私鑰保護XML 私鑰含極敏感參數 (D, P, Q, DP, DQ, InverseQ)生產環境:加密儲存、硬體安全模組 (HSM)、Windows DPAPI、Azure Key Vault
隨機數RSA 加密/簽名需高品質隨機數RSACryptoServiceProvider 內建 CSP RNG,可信
時序攻擊解密/簽名耗時可能洩露私鑰資訊高安全環境用恆時實現或硬體加速

混合加密實現範例 (長資料)


public sealed class HybridEncryption
{
    // 加密:AES-256-CBC + RSA-OAEP
    public static (byte[] EncryptedData, byte[] EncryptedKey, byte[] Iv) Encrypt(string plainText, string rsaPublicKeyXml) {
        using (Aes aes = Aes.Create()) {
            aes.KeySize = 256;
            aes.GenerateKey();
            aes.GenerateIV();
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;

            byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
            byte[] cipherBytes;
            using (var encryptor = aes.CreateEncryptor()) {
                cipherBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
            }

            using (var rsa = new RSACryptoServiceProvider(2048)) {
                rsa.FromXmlString(rsaPublicKeyXml);
                byte[] encryptedKey = rsa.Encrypt(aes.Key, true); // OAEP
                return (cipherBytes, encryptedKey, aes.IV);
            }
        }
    }

    // 解密
    public static string Decrypt(byte[] cipherData, byte[] encryptedKey, byte[] iv, string rsaPrivateKeyXml) {
        using (var rsa = new RSACryptoServiceProvider(2048)) {
            rsa.FromXmlString(rsaPrivateKeyXml);
            byte[] aesKey = rsa.Decrypt(encryptedKey, true);

            using (Aes aes = Aes.Create()) {
                aes.Key = aesKey;
                aes.IV = iv;
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                using (var decryptor = aes.CreateDecryptor()) {
                    byte[] plainBytes = decryptor.TransformFinalBlock(cipherData, 0, cipherData.Length);
                    return Encoding.UTF8.GetString(plainBytes);
                }
            }
        }
    }
}

總結

RSA 非對稱加密是資安基礎設施核心。.NET RSACryptoServiceProvider 提供了完整、合規的實現。本文涵蓋:金鑰生成/匯入匯出/持久化、字串加密解密、簽名驗證、編碼處理、混合加密突破長度限制、私鑰保護最佳實踐。關鍵原則:公鑰可公開、私鑰極機密、長資料用混合加密、新系統用 OAEP、私鑰落地必加密。掌握此套流程,即可構建安全通訊、數位簽章、授權驗證、加密儲存等核心功能。

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