Visual Studio中C# RSA解密报错:Key not valid for use in specified state
RSA解密报错:System.Security.Cryptography.CryptographicException: 'Key not valid for use in specified state'
问题场景
在Visual Studio开发大学C#项目时,自定义RsaEncryptionService类实现RSA加密解密逻辑,测试解密随机字符串正常,但读取Key.txt文件内容解密时触发上述错误。
自定义RsaEncryptionService类代码
public class RsaEncryptionService { private static RSACryptoServiceProvider csp = new RSACryptoServiceProvider(2048); private RSAParameters _privateKey; private RSAParameters _publicKey; public RsaEncryptionService() { _privateKey = csp.ExportParameters(true); _publicKey = csp.ExportParameters(false); } public string GetPublicKey() { var sw = new StringWriter(); var xmlSerializer = new XmlSerializer(typeof(RSAParameters)); xmlSerializer.Serialize(sw, _publicKey); return sw.ToString(); } public string GetPrivateKey() { var sw = new StringWriter(); var xmlSerializer = new XmlSerializer(typeof(RSAParameters)); xmlSerializer.Serialize(sw, _privateKey); return sw.ToString(); } public string Encript(string plainText) { csp = new RSACryptoServiceProvider(); csp.ImportParameters(_publicKey); var dataBytes = Encoding.Unicode.GetBytes(plainText); var cypherData = csp.Encrypt(dataBytes, false); return Convert.ToBase64String(cypherData); } public string Decript(string cypherText) { var dataBytes = Convert.FromBase64String(cypherText); csp.ImportParameters(_privateKey); var plaintextBytes = csp.Decrypt(dataBytes, false); return Encoding.Unicode.GetString(plaintextBytes); } }
触发错误的测试代码
var rsa = new RsaEncryptionService(); byte[] text = File.ReadAllBytes(Application.StartupPath + "\\Export\\Export.txt"); string key = File.ReadAllText(Application.StartupPath + "\\Export\\Key.txt"); string iv = File.ReadAllText(Application.StartupPath + "\\Export\\IV.txt"); var DecryptedKey = rsa.Decript(key);
问题分析
- 静态CSP实例的状态污染:类中使用静态
RSACryptoServiceProvider字段,在Encript方法中重新实例化覆盖了静态对象,后续Decript方法使用这个被修改后的实例导入私钥,导致密钥状态不匹配。 - 多实例共享冲突:静态字段会被所有
RsaEncryptionService实例共享,若多次实例化类,会引发密钥状态混乱。 - 潜在的密钥不匹配:若
Key.txt中的内容不是当前实例公钥加密生成的Base64字符串,也会触发解密失败。
修复方案
修改后的RsaEncryptionService类
public class RsaEncryptionService { private readonly RSAParameters _privateKey; private readonly RSAParameters _publicKey; public RsaEncryptionService() { using var csp = new RSACryptoServiceProvider(2048); _privateKey = csp.ExportParameters(true); _publicKey = csp.ExportParameters(false); } public string GetPublicKey() { var sw = new StringWriter(); var xmlSerializer = new XmlSerializer(typeof(RSAParameters)); xmlSerializer.Serialize(sw, _publicKey); return sw.ToString(); } public string GetPrivateKey() { var sw = new StringWriter(); var xmlSerializer = new XmlSerializer(typeof(RSAParameters)); xmlSerializer.Serialize(sw, _privateKey); return sw.ToString(); } public string Encrypt(string plainText) { using var csp = new RSACryptoServiceProvider(); csp.ImportParameters(_publicKey); var dataBytes = Encoding.Unicode.GetBytes(plainText); var cypherData = csp.Encrypt(dataBytes, false); return Convert.ToBase64String(cypherData); } public string Decrypt(string cypherText) { var dataBytes = Convert.FromBase64String(cypherText); using var csp = new RSACryptoServiceProvider(); csp.ImportParameters(_privateKey); var plaintextBytes = csp.Decrypt(dataBytes, false); return Encoding.Unicode.GetString(plaintextBytes); } }
关键修改说明
- 移除静态
RSACryptoServiceProvider字段,改为在构造函数、加密/解密方法中使用局部实例,通过using确保资源自动释放。 - 修正方法名拼写错误:
Encript→Encrypt、Decript→Decrypt,符合C#命名规范。 - 每个加密/解密操作使用独立的
RSACryptoServiceProvider实例,彻底避免状态污染问题。
额外检查项
- 确认
Key.txt中的内容是当前RsaEncryptionService实例公钥加密生成的Base64字符串,若为外部密钥加密的内容,需对应导入正确的私钥。 - 读取文件时确保无多余空格、换行符,可通过
key = key.Trim()清理内容后再解密。
内容的提问来源于stack exchange,提问作者Borna
相关产品推荐
相关产品推荐

