解密xml文档的问题 [英] Problem with decrypting xml document

查看:135
本文介绍了解密xml文档的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一些加密了一个包含用户凭据的XML配置文件的代码,以及解密该文件的代码。当我在本地机器上一起运行加密和解密时,它按预期工作。但是,当我部署程序时,只有解密代码,xml文件将不会解密。我得到一个加密异常:坏数据?
这是我的代码:

  public static void Encrypt(XmlDocument Doc,string ElementToEncrypt,string EncryptionElementID,RSA Alg, string keyname)
{
if(Doc == null)
throw new ArgumentNullException(Doc);
if(ElementToEncrypt == null)
throw new ArgumentNullException(Element to Encrypt);
if(EncryptionElementID == null)
throw new ArgumentNullException(EncryptionElementID);
if(Alg == null)
throw new ArgumentNullException(ALG);
//指定要加密的xml元素
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0]为XmlElement;

if(elementToEncrypt == null)
throw new XmlException(未找到指定的元素);
try
{
//创建会话密钥
RijndaelManaged sessionkey = new RijndaelManaged();
sessionkey.KeySize = 256;

//加密使用加密的exml对象并保存在字节数组
EncryptedXml exml = new EncryptedXml();
byte [] encryptedElement = exml.EncryptData(elementToEncrypt,sessionkey,false);

//构造一个EncryptedData对象,并使用所需的加密信息填充
//。

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,Alg,false);

ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);


//为KeyInfo元素创建一个新的DataReference元素
//。这个可选的
//元素指定哪个EncryptedData
//使用这个键。一个XML文档可以有
//多个EncryptedData元素使用
//不同的键。
DataReference dRef = new DataReference();

//指定EncryptedData URI。
dRef.Uri =#+ EncryptionElementID;


//向加密密钥添加数据引用

ek.AddReference(dRef);
//将加密的密钥添加到
// EncryptedData对象。

edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));

//创建一个新的KeyInfoName元素。
KeyInfoName kin = new KeyInfoName();



//将KeyInfoName元素添加到
// EncryptedKey对象。
ek.KeyInfo.AddClause(kin);
//将加密的元素数据添加到
// EncryptedData对象。
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////// //////
//将原始XmlDocument
//对象中的元素替换为EncryptedData元素。
////////////////////////////////////////// //////
EncryptedXml.ReplaceElement(elementToEncrypt,edElement,false);
}


catch(异常e)
{
throw e;
}
}


public static string Decrypt()
{
//创建XML文档对象并加载配置文件
XmlDocument xmlDoc = new XmlDocument();

try
{
xmlDoc.Load(config.xml);
}
catch(FileNotFoundException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();

}
catch(异常e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}

//为密钥
创建容器CspParameters cspParam = new CspParameters();
cspParam.KeyContainerName =XML_RSA_FTP_KEY;
cspParam.Flags = CspProviderFlags.UseMachineKeyStore;
//创建密钥并存储在容器
中RSACryptoServiceProvider ftpkey = new RSACryptoServiceProvider(cspParam);


//添加键名映射qnd解密文档
EncryptedXml exml = new EncryptedXml(xmlDoc);
exml.AddKeyNameMapping(ftpkey,ftpkey);
exml.DecryptDocument();

//传递解密文档以提取凭据方法
string details = Extract_Credentials(xmlDoc);

//返回解密日志详细信息
返回详细信息;

}

任何帮助将不胜感激。谢谢,Darren

解决方案

我将您的加密功能更改为不传入RSA Alg,而是创建RSACryptoServiceProvider rsaAlg, string Keyname param,这应该是在KeyContainerName的解密中使用的相同的字符串,XML_RSA_FTP_KEY



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



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

  public static void Encrypt(XmlDocument Doc,string ElementToEncrypt,string EncryptionElementID,string Keyname )
{
if(Doc == null)
throw new ArgumentNullException(Doc);
if(ElementToEncrypt == null)
throw new ArgumentNullException(Element to Encrypt);
if(EncryptionElementID == null)
throw new ArgumentNullException(EncryptionElementID);

//创建一个CspParameters对象并指定密钥容器的名称。
var cspParams = new CspParameters {KeyContainerName = Keyname}; //XML_RSA_FTP_KEY

//创建一个新的RSA密钥并将其保存在容器中。该密钥将加密
//对称密钥,然后将密钥加密到XML文档中。
var rsaAlg = new RSACryptoServiceProvider(cspParams);

//指定要加密的xml元素
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0]作为XmlElement;

if(elementToEncrypt == null)
throw new XmlException(未找到指定的元素);
try
{
//创建会话密钥
RijndaelManaged sessionkey = new RijndaelManaged();
sessionkey.KeySize = 256;

//加密使用加密的exml对象并保存在字节数组
EncryptedXml exml = new EncryptedXml();
byte [] encryptedElement = exml.EncryptData(elementToEncrypt,sessionkey,false);

//构造一个EncryptedData对象,并使用所需的加密信息填充
//。

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,rsaAlg,false);

ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);


//为KeyInfo元素创建一个新的DataReference元素
//。这个可选的
//元素指定哪个EncryptedData
//使用这个键。一个XML文档可以有
//多个EncryptedData元素使用
//不同的键。
DataReference dRef = new DataReference();

//指定EncryptedData URI。
dRef.Uri =#+ EncryptionElementID;


//向加密密钥添加数据引用

ek.AddReference(dRef);
//将加密的密钥添加到
// EncryptedData对象。

edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));

//使用EncryptionProperty元素保存关于密钥的更多信息。

//创建一个新的EncryptionPropertyXmlElement对象。
var property = new XmlDocument()。CreateElement(EncryptionProperty,EncryptedXml.XmlEncNamespaceUrl);

//设置EncryptionPropertyXmlElement对象的值
property.InnerText = RijndaelManagedEncryption.EncryptRijndael(Convert.ToBase64String(rsaAlg.ExportCspBlob(true)),
您的

//使用XmlElement对象创建EncryptionProperty对象
var encProperty = new EncryptionProperty(property);

//添加EncryptionKey对象的EncryptionProperty对象
ek.AddProperty(encProperty);

//创建一个新的KeyInfoName元素
KeyInfoName kin = new KeyInfoName();



//将KeyInfoName元素添加到
// EncryptedKey对象
ek.KeyInfo.AddClause(kin);
//添加加密的元素数据到
// EncryptedData对象
edElement.CipherData.CipherValue = enc ryptedElement;
////////////////////////////////////////// //////
//将原始XmlDocument
//对象中的元素替换为EncryptedData元素。
////////////////////////////////////////// //////
EncryptedXml.ReplaceElement(elementToEncrypt,edElement,false);
}


catch(异常)
{
throw;
}
}

public static string Decrypt()
{
//创建XML文档对象并加载配置文件
XmlDocument xmlDoc = new的XmlDocument();

try
{
xmlDoc.Load(config.xml);
}
catch(FileNotFoundException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();

}
catch(异常e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}

//为密钥
创建容器CspParameters cspParam = new CspParameters();
cspParam.KeyContainerName =XML_RSA_FTP_KEY;
cspParam.Flags = CspProviderFlags.UseMachineKeyStore;
//创建密钥并存储在容器
中RSACryptoServiceProvider ftpkey = new RSACryptoServiceProvider(cspParam);

var keyInfo = xmlDoc.GetElementsByTagName(EncryptionProperty)[0] .InnerText;
ftpkey.ImportCspBlob(
Convert.FromBase64String(RijndaelManagedEncryption.DecryptRijndael(keyInfo,
你的盐串在这里)));

//添加键名映射qnd解密文档
EncryptedXml exml = new EncryptedXml(xmlDoc);
exml.AddKeyNameMapping(ftpkey,ftpkey);
exml.DecryptDocument();

//传递解密文档以提取凭据方法
string details = Extract_Credentials(xmlDoc);

//返回解密日志详细信息
返回详细信息;

}

看看这里为RijndaelManagedEncryption类。


I have written some code that has encrypted an XML config file containing user credentials, and also the code to decrypt that file. When I run the encryption and decryption together on my local machine it works as expected. However, when I deploy the program, with only the decrypt code, the xml file will not decrypt. I get a cryptographic Exception: Bad Data? Here is my code:

    public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string Keyname)
    {
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (ElementToEncrypt == null)
            throw new ArgumentNullException("Element to Encrypt");
        if (EncryptionElementID == null)
            throw new ArgumentNullException("EncryptionElementID");
        if (Alg == null)
            throw new ArgumentNullException("ALG");
        //specify which xml elements to encrypt
        XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

        if (elementToEncrypt == null)
            throw new XmlException("The specified element was not found");
        try
        {
            //create session key
            RijndaelManaged sessionkey = new RijndaelManaged();
            sessionkey.KeySize = 256;

            //encrypt using Encrypted exml object and hold in byte array
            EncryptedXml exml = new EncryptedXml();
            byte[] encryptedElement = exml.EncryptData(elementToEncrypt, sessionkey, false);

            //Construct an EncryptedData object and populate
            // it with the desired encryption information.

            EncryptedData edElement = new EncryptedData();
            edElement.Type = EncryptedXml.XmlEncElementUrl;
            edElement.Id = EncryptionElementID;

            edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
            //encrypt the session key and add it encrypted key element
            EncryptedKey ek = new EncryptedKey();

            byte[] encryptedKey = EncryptedXml.EncryptKey(sessionkey.Key, Alg, false);

            ek.CipherData = new CipherData(encryptedKey);
            ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);


            // Create a new DataReference element
            // for the KeyInfo element.  This optional
            // element specifies which EncryptedData
            // uses this key.  An XML document can have
            // multiple EncryptedData elements that use
            // different keys.
            DataReference dRef = new DataReference();

            // Specify the EncryptedData URI.
            dRef.Uri = "#" + EncryptionElementID;


           //add data reference to encrypted key

            ek.AddReference(dRef);
            //Add the encrypted key to the
            // EncryptedData object.

            edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));

         // Create a new KeyInfoName element.
        KeyInfoName kin = new KeyInfoName();



        // Add the KeyInfoName element to the
        // EncryptedKey object.
        ek.KeyInfo.AddClause(kin);
        // Add the encrypted element data to the
        // EncryptedData object.
        edElement.CipherData.CipherValue = encryptedElement;
        ////////////////////////////////////////////////////
        // Replace the element from the original XmlDocument
        // object with the EncryptedData element.
        ////////////////////////////////////////////////////
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    }


        catch (Exception e)
        {
            throw e;
        }
    }


    public static string Decrypt()
    {
            //create XML documentobject and load config file
            XmlDocument xmlDoc = new XmlDocument();

            try
            {
                xmlDoc.Load("config.xml");
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
            }

            //create container for key
            CspParameters cspParam = new CspParameters();
            cspParam.KeyContainerName = "XML_RSA_FTP_KEY";
            cspParam.Flags = CspProviderFlags.UseMachineKeyStore;
            //create key and store in container
            RSACryptoServiceProvider ftpkey = new RSACryptoServiceProvider(cspParam);


            //add keyname mapping qnd decrypt the document
            EncryptedXml exml = new EncryptedXml(xmlDoc);
            exml.AddKeyNameMapping("ftpkey", ftpkey);
            exml.DecryptDocument();

            //pass decrypted document to extract credentials method
            string details =  Extract_Credentials(xmlDoc);

            //return decrypted log in details
            return details;

    }

Any help would be appreciated. Thanks, Darren

解决方案

I changed your Encrypt function to not pass in the RSA Alg, but rather create the RSACryptoServiceProvider rsaAlg, using the string Keyname param, this should be the same string used in the Decrypt for the KeyContainerName, "XML_RSA_FTP_KEY"

The reason the Decryption functions throws "Bad Data" exception when trying to Decrypt on another PC is that the CspParameters is linked to the session on the PC where the Encryption was run.

The cspParams object will need to be embedded and encrypted in the XML to enable Decryption on another PC. Luckily there is EncryptionProperty we can use for this.

public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, string Keyname)
    {
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (ElementToEncrypt == null)
            throw new ArgumentNullException("Element to Encrypt");
        if (EncryptionElementID == null)
            throw new ArgumentNullException("EncryptionElementID");

        // Create a CspParameters object and specify the name of the key container.
        var cspParams = new CspParameters { KeyContainerName = Keyname }; //"XML_RSA_FTP_KEY"

        // Create a new RSA key and save it in the container.  This key will encrypt 
        // a symmetric key, which will then be encryped in the XML document.
        var rsaAlg = new RSACryptoServiceProvider(cspParams);

        //specify which xml elements to encrypt
        XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

        if (elementToEncrypt == null)
            throw new XmlException("The specified element was not found");
        try
        {
            //create session key
            RijndaelManaged sessionkey = new RijndaelManaged();
            sessionkey.KeySize = 256;

            //encrypt using Encrypted exml object and hold in byte array
            EncryptedXml exml = new EncryptedXml();
            byte[] encryptedElement = exml.EncryptData(elementToEncrypt, sessionkey, false);

            //Construct an EncryptedData object and populate
            // it with the desired encryption information.

            EncryptedData edElement = new EncryptedData();
            edElement.Type = EncryptedXml.XmlEncElementUrl;
            edElement.Id = EncryptionElementID;

            edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
            //encrypt the session key and add it encrypted key element
            EncryptedKey ek = new EncryptedKey();

            byte[] encryptedKey = EncryptedXml.EncryptKey(sessionkey.Key, rsaAlg, false);

            ek.CipherData = new CipherData(encryptedKey);
            ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);


            // Create a new DataReference element
            // for the KeyInfo element.  This optional
            // element specifies which EncryptedData
            // uses this key.  An XML document can have
            // multiple EncryptedData elements that use
            // different keys.
            DataReference dRef = new DataReference();

            // Specify the EncryptedData URI.
            dRef.Uri = "#" + EncryptionElementID;


            //add data reference to encrypted key

            ek.AddReference(dRef);
            //Add the encrypted key to the
            // EncryptedData object.

            edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));

            // 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(rsaAlg.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);

            // Create a new KeyInfoName element.
            KeyInfoName kin = new KeyInfoName();



            // Add the KeyInfoName element to the
            // EncryptedKey object.
            ek.KeyInfo.AddClause(kin);
            // Add the encrypted element data to the
            // EncryptedData object.
            edElement.CipherData.CipherValue = encryptedElement;
            ////////////////////////////////////////////////////
            // Replace the element from the original XmlDocument
            // object with the EncryptedData element.
            ////////////////////////////////////////////////////
            EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
        }


        catch (Exception)
        {
            throw;
        }
    }

    public static string Decrypt()
    {
        //create XML documentobject and load config file
        XmlDocument xmlDoc = new XmlDocument();

        try
        {
            xmlDoc.Load("config.xml");
        }
        catch (FileNotFoundException e)
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
        }

        //create container for key
        CspParameters cspParam = new CspParameters();
        cspParam.KeyContainerName = "XML_RSA_FTP_KEY";
        cspParam.Flags = CspProviderFlags.UseMachineKeyStore;
        //create key and store in container
        RSACryptoServiceProvider ftpkey = new RSACryptoServiceProvider(cspParam);

        var keyInfo = xmlDoc.GetElementsByTagName("EncryptionProperty")[0].InnerText;
        ftpkey.ImportCspBlob(
            Convert.FromBase64String(RijndaelManagedEncryption.DecryptRijndael(keyInfo,
                "Your Salt string here")));

        //add keyname mapping qnd decrypt the document
        EncryptedXml exml = new EncryptedXml(xmlDoc);
        exml.AddKeyNameMapping("ftpkey", ftpkey);
        exml.DecryptDocument();

        //pass decrypted document to extract credentials method
        string details = Extract_Credentials(xmlDoc);

        //return decrypted log in details
        return details;

    }

Have a look here for the RijndaelManagedEncryption class.

这篇关于解密xml文档的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆