EncryptedXml 解密文档方法引发"Bad Data"异常



我写了一个加密/解密流的代码块。代码在我的本地机器上运行。但是当我在网上发布我的代码解密函数抛出"坏数据"异常这是我的加密和解密函数

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页面,有如下注释

要在X.509证书中使用XML加密,您必须具有安装了Microsoft Enhanced Cryptographic Provider并安装了X.509证书必须使用增强的提供程序。如果你没有Microsoft增强加密提供程序安装或X.509证书不使用增强型提供程序,a将抛出带有"未知错误"的CryptographicException解密XML文档

你对"Microsoft Enhanced Cryptographic Provider"one_answers"X.509证书"有什么概念吗?我的问题和这些有关系吗?

在另一台PC上尝试解密时,解密函数抛出"坏数据"异常的原因是CspParameters链接到运行加密的PC上的会话。

cspParams对象需要在XML中嵌入和加密,以便在另一台PC上启用解密。幸运的是,我们可以使用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类

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

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

最新更新