EncryptedXml DecryptDocument方法抛出“Bad Data”exception

我为Encrypt / Decrypt Streams写了一个代码块。 代码在我的本地计算机上运行。 但是当我在网上发布我的代码时,解密函数抛出“坏数据”exception这是我的加密和解密函数

private static MemoryStream EncryptStream(XmlDocument xmlDoc, XmlElement elementToEncrypt, string password) { CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = password; RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); RijndaelManaged sessionKey = null; try { if (xmlDoc == null) throw new ArgumentNullException("xmlDoc"); if (rsaKey == null) throw new ArgumentNullException("rsaKey"); if (elementToEncrypt == null) throw new ArgumentNullException("elementToEncrypt"); sessionKey = new RijndaelManaged(); sessionKey.KeySize = 256; EncryptedXml eXml = new EncryptedXml(); byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false); EncryptedData edElement = new EncryptedData(); edElement.Type = EncryptedXml.XmlEncElementUrl; edElement.Id = EncryptionElementID; edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); EncryptedKey ek = new EncryptedKey(); byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, rsaKey, false); ek.CipherData = new CipherData(encryptedKey); ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); edElement.KeyInfo = new KeyInfo(); KeyInfoName kin = new KeyInfoName(); kin.Value = KeyName; ek.KeyInfo.AddClause(kin); edElement.CipherData.CipherValue = encryptedElement; edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek)); EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false); if (sessionKey != null) { sessionKey.Clear(); } rsaKey.Clear(); MemoryStream stream = new MemoryStream(); xmlDoc.Save(stream); stream.Position = 0; Encoding encodeing = System.Text.UnicodeEncoding.Default; return stream; } catch (Exception e) { if (sessionKey != null) { sessionKey.Clear(); } rsaKey.Clear(); throw (e); } } private static MemoryStream DecryptStream(XmlDocument xmlDoc, string password) { CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = password; RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); EncryptedXml exml = null; try { if (xmlDoc == null) throw new ArgumentNullException("xmlDoc"); if (rsaKey == null) throw new ArgumentNullException("rsaKey"); exml = new EncryptedXml(xmlDoc); exml.AddKeyNameMapping(KeyName, rsaKey); exml.DecryptDocument(); rsaKey.Clear(); MemoryStream outStream = new MemoryStream(); xmlDoc.Save(outStream); outStream.Position = 0; return outStream; } catch (Exception e) { rsaKey.Clear(); throw (e); } } 

“exml.DecryptDocument();”抛出exception 线。

你对问题和解决方案有什么看法吗?

编辑:

在MSDN页面,有如下的评语

要将XML加密与X.509证书一起使用,必须安装Microsoft增强加密提供程序,并且X.509证书必须使用增强型提供程序。 如果您没有安装Microsoft增强加密提供程序或X.509证书不使用增强的提供程序,则解密XML文档时将引发带有“未知错误”的CryptographicException。

您对“Microsoft Enhanced Cryptographic Provider”和“X.509 certificate”有什么想法吗? 我的问题可以与这些相关吗?

在尝试解密另一台PC时,解密function抛出“坏数据”exception的原因是CspParameters链接到运行加密的PC上的会话。

需要在XML中嵌入和加密cspParams对象,以便在另一台PC上启用Decryption。 幸运的是,我们可以使用EncryptionProperty。

 private static MemoryStream EncryptStream(XmlDocument xmlDoc, XmlElement elementToEncrypt, string password) { CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = password; RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); RijndaelManaged sessionKey = null; try { if (xmlDoc == null) throw new ArgumentNullException("xmlDoc"); if (rsaKey == null) throw new ArgumentNullException("rsaKey"); if (elementToEncrypt == null) throw new ArgumentNullException("elementToEncrypt"); sessionKey = new RijndaelManaged(); sessionKey.KeySize = 256; EncryptedXml eXml = new EncryptedXml(); byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false); EncryptedData edElement = new EncryptedData(); edElement.Type = EncryptedXml.XmlEncElementUrl; edElement.Id = EncryptionElementID; edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url); EncryptedKey ek = new EncryptedKey(); byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, rsaKey, false); ek.CipherData = new CipherData(encryptedKey); ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); // Save some more information about the key using the EncryptionProperty element. // Create a new "EncryptionProperty" XmlElement object. var property = new XmlDocument().CreateElement("EncryptionProperty", EncryptedXml.XmlEncNamespaceUrl); // Set the value of the EncryptionProperty" XmlElement object. property.InnerText = RijndaelManagedEncryption.EncryptRijndael(Convert.ToBase64String(rsaKey.ExportCspBlob(true)), "Your Salt string here"); // Create the EncryptionProperty object using the XmlElement object. var encProperty = new EncryptionProperty(property); // Add the EncryptionProperty object to the EncryptedKey object. ek.AddProperty(encProperty); edElement.KeyInfo = new KeyInfo(); KeyInfoName kin = new KeyInfoName(); kin.Value = KeyName; ek.KeyInfo.AddClause(kin); edElement.CipherData.CipherValue = encryptedElement; edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek)); EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false); if (sessionKey != null) { sessionKey.Clear(); } rsaKey.Clear(); MemoryStream stream = new MemoryStream(); xmlDoc.Save(stream); stream.Position = 0; Encoding encodeing = System.Text.UnicodeEncoding.Default; return stream; } catch (Exception) { if (sessionKey != null) { sessionKey.Clear(); } rsaKey.Clear(); throw; } } private static MemoryStream DecryptStream(XmlDocument xmlDoc, string password) { CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = password; RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); var keyInfo = xmlDoc.GetElementsByTagName("EncryptionProperty")[0].InnerText; rsaKey.ImportCspBlob( Convert.FromBase64String(RijndaelManagedEncryption.DecryptRijndael(keyInfo, "Your Salt string here"))); EncryptedXml exml = null; try { if (xmlDoc == null) throw new ArgumentNullException("xmlDoc"); if (rsaKey == null) throw new ArgumentNullException("rsaKey"); exml = new EncryptedXml(xmlDoc); exml.AddKeyNameMapping(KeyName, rsaKey); exml.DecryptDocument(); rsaKey.Clear(); MemoryStream outStream = new MemoryStream(); xmlDoc.Save(outStream); outStream.Position = 0; return outStream; } catch (Exception) { rsaKey.Clear(); throw; } } 

看看RijndaelManagedEncryption类。

不要重新发明加密协议。 你会弄错的 。 例如,error handling存储在CSP中的RSA密钥并期望它们神奇地出现在任何机器上。

要加密传输中的数据,请使用SSL / TLS。 .Net提供与SslStream开箱即用的function。 对于WCF,请参见如何:使用SSL配置IIS托管的WCF服务 。