非對稱加密 (公開金鑰加密) 是現代資安基石:公鑰加密、私鑰解密 (機密性);私鑰簽名、公鑰驗證 (完整性/不可否認性)。.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));
}
}
兩個分頁:
// 生成金鑰
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、私鑰落地必加密。掌握此套流程,即可構建安全通訊、數位簽章、授權驗證、加密儲存等核心功能。