RSA加解密系统OAEP填充解密错误修复求助
修复RSA OAEP填充解密错误
问题根源
你的代码中GenerateKeys方法创建了两个独立的RSA实例,分别导出公钥和私钥——这两组密钥完全不配对。用这个公钥加密的数据,自然无法用另一个无关的私钥解密,直接导致OAEP填充验证失败。
修复步骤
- 使用同一个RSA实例生成密钥对:密钥对必须由同一个RSA对象生成,才能保证公钥和私钥匹配。
- 完善密钥显示逻辑:私钥包含更多参数(如D、P、Q等),原
GetKeyString方法只显示公钥参数,需要补充私钥的信息展示。 - 推荐使用现代RSA API:
RSACryptoServiceProvider是旧版API,替换为RSA.Create()可获得更好的兼容性和安全性。
完整修正代码
using System; using System.Text; using System.IO; using System.Security.Cryptography; using System.Windows.Forms; namespace RSA { public partial class Form1 : Form { private RSAParameters publicKey; private RSAParameters privateKey; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { GenerateKeys(); publicKeyLabel.Text = GetKeyString(publicKey, isPrivateKey: false); privateKeyLabel.Text = GetKeyString(privateKey, isPrivateKey: true); } // 修复:用同一个RSA实例生成配对的密钥对 private void GenerateKeys() { using (RSA rsa = RSA.Create(2048)) // 推荐使用2048位及以上密钥长度 { publicKey = rsa.ExportParameters(false); privateKey = rsa.ExportParameters(true); } } // 完善:支持显示公钥/私钥的完整参数 static string GetKeyString(RSAParameters key, bool isPrivateKey) { StringBuilder sb = new StringBuilder(); sb.AppendLine($"模数(n): {BitConverter.ToString(key.Modulus).Replace("-", "")}"); sb.AppendLine($"指数(e): {BitConverter.ToString(key.Exponent).Replace("-", "")}"); if (isPrivateKey) { sb.AppendLine($"私钥指数(d): {BitConverter.ToString(key.D).Replace("-", "")}"); sb.AppendLine($"素数p: {BitConverter.ToString(key.P).Replace("-", "")}"); sb.AppendLine($"素数q: {BitConverter.ToString(key.Q).Replace("-", "")}"); sb.AppendLine($"d mod (p-1): {BitConverter.ToString(key.DP).Replace("-", "")}"); sb.AppendLine($"d mod (q-1): {BitConverter.ToString(key.DQ).Replace("-", "")}"); sb.AppendLine($"逆元q mod p: {BitConverter.ToString(key.InverseQ).Replace("-", "")}"); } return sb.ToString(); } private void buttonChooseFile_Click(object sender, EventArgs e) { string filePath = GetFilePath(); if (!string.IsNullOrEmpty(filePath)) { string textToEncrypt = File.ReadAllText(filePath); originalTextLabel.Text = $"原始文本: {textToEncrypt}"; } } private void buttonEncrypt_Click(object sender, EventArgs e) { string textToEncrypt = originalTextLabel.Text.Replace("原始文本: ", ""); if (!string.IsNullOrEmpty(textToEncrypt)) { string encryptedText = EncryptText(textToEncrypt, publicKey); encryptedTextLabel.Text = $"加密文本: {encryptedText}"; } } private string GetFilePath() { using (OpenFileDialog openFileDialog = new OpenFileDialog()) { openFileDialog.Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*"; if (openFileDialog.ShowDialog() == DialogResult.OK) { return openFileDialog.FileName; } else { return null; } } } // 替换为现代RSA API private string EncryptText(string text, RSAParameters publicKey) { using (RSA rsa = RSA.Create()) { rsa.ImportParameters(publicKey); byte[] encryptedBytes = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1); return Convert.ToBase64String(encryptedBytes); } } // 替换为现代RSA API private string DecryptText(string encryptedText, RSAParameters privateKey) { using (RSA rsa = RSA.Create()) { rsa.ImportParameters(privateKey); byte[] encryptedBytes = Convert.FromBase64String(encryptedText); byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, RSAEncryptionPadding.OaepSHA1); return Encoding.UTF8.GetString(decryptedBytes); } } private void buttonDecrypt_Click(object sender, EventArgs e) { string encryptedText = encryptedTextLabel.Text.Replace("加密文本: ", ""); if (!string.IsNullOrEmpty(encryptedText)) { string decryptedText = DecryptText(encryptedText, privateKey); decryptedTextLabel.Text = $"解密文本: {decryptedText}"; } } } }
额外注意事项
- 密钥长度:1024位RSA密钥已被认为不安全,建议使用2048位或4096位。
- 填充一致性:加密和解密必须使用相同的填充模式(此处为
OaepSHA1),如果更换哈希算法(如SHA256),需两边同步修改。 - 文本处理:RSA仅适合加密小数据(如对称密钥),若需加密大文本,建议先用AES等对称算法加密数据,再用RSA加密对称密钥。
内容的提问来源于stack exchange,提问作者Boooeee
相关产品推荐
相关产品推荐

