.NET 8中RSA解密触发CryptographicException(0xC100000D)求助
.NET 8 RSA解密抛出0xC100000D错误问题
问题概述
在.NET 8环境下使用C#实现RSA加密功能,加密测试运行正常,但解密时抛出System.Security.Cryptography.CryptographicException,错误码为0xC100000D,提示"Unknown error (0xc100000d)"。
错误详情
System.Security.Cryptography.CryptographicException HResult=0xC100000D Message=Unknown error (0xc100000d) Source=System.Security.Cryptography StackTrace: at Interop.BCrypt.BCryptEncryptRsa(SafeBCryptKeyHandle key, ReadOnlySpan`1 source, Span`1 destination, Void* pPaddingInfo, BCryptEncryptFlags dwFlags) at System.Security.Cryptography.RSABCrypt.TryEncrypt(ReadOnlySpan`1 data, Span`1 destination, RSAEncryptionPadding padding, Int32& bytesWritten) at System.Security.Cryptography.RSA.Encrypt(ReadOnlySpan`1 data, Span`1 destination, RSAEncryptionPadding padding) at System.Security.Cryptography.RSABCrypt.Encrypt(Byte[] data, RSAEncryptionPadding padding) at FileCryptography.FileEncryptionUtility.Encrypt(Byte[] data, String pemKey) in Class1.cs:line 51 at FileCryptography.FileEncryptionUtility.EncryptFile(String filePath, String pemKey) in Class1.cs:line 25 at FileCryptography.FileEncryptionUtility.File_encryption(Boolean Is_encrypt, String File_path, String PEMkey) in Class1.cs:line 14 at Cry.Form.File_crypt(Boolean Is_encrypt, String File_path) in Form1.cs:line 114 at Cry.Form.Form_Load(Object sender, EventArgs e) in Form1.cs:line 203 at System.Windows.Forms.Form.OnLoad(EventArgs e) at System.Windows.Forms.Control.CreateControl(Boolean ignoreVisible) at System.Windows.Forms.Control.CreateControl() at System.Windows.Forms.Control.WmShowWindow(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)
实现代码
Class1.cs
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace FileCryptography { public class FileEncryptionUtility { public static void File_encryption(bool Is_encrypt, string File_path, string PEMkey) { if (Is_encrypt) { EncryptFile(File_path, PEMkey); } else { DecryptFile(File_path, PEMkey); } } private static void EncryptFile(string filePath, string pemKey) { byte[] data = File.ReadAllBytes(filePath); byte[] encryptedData = Encrypt(data, pemKey); File.Delete(filePath); string p1 = Path.GetDirectoryName(filePath); string p2 = Path.GetFileNameWithoutExtension(filePath); string p3 = Path.GetExtension(filePath); string p4 = ".rwnenc"; string p = $"{p1}{p2}{p3}{p4}"; File.WriteAllBytes(p, encryptedData); File.Delete(filePath); } private static void DecryptFile(string filePath, string pemKey) { byte[] encryptedData = File.ReadAllBytes(filePath); byte[] decryptedData = Decrypt(encryptedData, pemKey); string directory = Path.GetDirectoryName(filePath); string filenameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); filenameWithoutExtension = filenameWithoutExtension.Replace(".rwnenc", ""); string newFilePath = Path.Combine(directory, filenameWithoutExtension); File.WriteAllBytes(newFilePath, decryptedData); } private static byte[] Encrypt(byte[] data, string pemKey) { using (RSA rsa = RSA.Create()) { rsa.ImportFromPem(pemKey.ToCharArray()); return rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA512); } } private static byte[] Decrypt(byte[] data, string pemKey) { using (RSA rsa = RSA.Create()) { rsa.ImportFromPem(pemKey.ToCharArray()); return rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA512); } } } }
问题排查与解决方法
1. 密钥不匹配(最可能原因)
RSA加密必须使用公钥,解密必须使用对应的私钥。如果解密时传入的是公钥PEM,会直接触发该错误:
- 检查解密时传入的
pemKey是否为私钥PEM(私钥PEM开头为-----BEGIN RSA PRIVATE KEY-----或-----BEGIN PRIVATE KEY-----); - 确保加密用的公钥和解密用的私钥是同一密钥对生成的。
2. 加密数据长度超出RSA限制
RSA OAEP SHA512的最大明文长度计算公式为:密钥长度(位)/8 - 2*哈希长度(字节) - 2。例如2048位密钥的最大明文长度为256 - 2*64 -2 = 126字节:
- 如果加密的文件大小超过该限制,加密时虽未抛出异常,但生成的密文无效,导致解密失败;
- 正确做法是用RSA加密对称加密密钥(如AES),再用对称密钥加密大文件,避免直接用RSA加密大数据。
3. 文件路径拼接错误
EncryptFile中拼接加密文件路径时缺少目录分隔符,可能导致加密文件写入错误位置,解密时读取的不是正确密文:
// 错误写法:目录与文件名直接拼接,缺少路径分隔符 string p = $"{p1}{p2}{p3}{p4}"; // 正确写法:使用Path.Combine拼接路径 string p = Path.Combine(p1, $"{p2}{p3}{p4}");
同时代码中重复执行File.Delete(filePath);,第一次删除后第二次会抛出异常,建议移除重复的删除操作。
4. 解密时文件名处理错误
DecryptFile中对文件名的处理存在冗余,Path.GetFileNameWithoutExtension(filePath)已经会去掉最后一个扩展名(.rwnenc),无需额外替换:
// 冗余操作,可移除 filenameWithoutExtension = filenameWithoutExtension.Replace(".rwnenc", "");
内容的提问来源于stack exchange,提问作者Kam Max
相关产品推荐
相关产品推荐

