我为Encrypt / Decrypt Streams编写了一个代码块。 代码在我的本地机器上工作。 但是当我在网上发布我的代码时 解密函数抛出“错误数据”异常 这是我的加密和解密功能
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();”上抛出异常线。
您对问题和解决方案有什么了解吗?
修改
在MSDN页面中,有如下的评论
要将XML加密与X.509证书一起使用,您必须拥有 安装了Microsoft Enhanced Cryptographic Provider和X.509 证书必须使用增强型提供商。如果你没有 安装了Microsoft Enhanced Cryptographic Provider或X.509 证书不使用增强型提供程序,a 当您启动时,将抛出带有“未知错误”的CryptographicException 解密XML文档。
您对“Microsoft Enhanced Cryptographic Provider”和“X.509 certificate”有什么想法吗? 我的问题可以与这些相关吗?
答案 0 :(得分:4)
在尝试解密另一台PC时,解密功能抛出“错误数据”异常的原因是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类的here。
答案 1 :(得分:1)
不要重新发明加密协议。 你会错的。例如,错误处理存储在CSPs中的RSA密钥并期望它们神奇地出现在任何机器上。
要加密传输中的数据,请使用SSL / TLS。 .Net提供了与SslStream
开箱即用的功能。对于WCF,请参阅How to: Configure an IIS-hosted WCF service with SSL。