C# 解密xml文档时出现问题

C# 解密xml文档时出现问题,c#,encryption,C#,Encryption,我编写了一些代码,对包含用户凭据的XML配置文件进行了加密,还编写了解密该文件的代码。当我在本地机器上同时运行加密和解密时,它会按预期工作。但是,当我部署程序时,仅使用解密代码,xml文件将不会解密。我得到一个加密异常:坏数据? 这是我的密码: public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string Keyname)

我编写了一些代码,对包含用户凭据的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");
        //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;

    }

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

显而易见的问题是如何将XML\u RSA\u FTP\u密钥私钥移动到服务器


如果您没有执行任何操作,
decrypt()
-方法将在XML\u RSA\u FTP\u密钥容器中生成一个新密钥对。此密钥将无法解密使用其他密钥加密的数据,并给出“坏数据”例外。

明显的问题是如何将XML\u RSA\u FTP\u密钥私钥移动到服务器


如果您没有执行任何操作,
decrypt()
-方法将在XML\u RSA\u FTP\u密钥容器中生成一个新密钥对。此密钥将无法解密使用其他密钥加密的数据,并给出“坏数据”异常。

我在使用EncryptedXml类X.509 certs时收到了相同的错误,并且我忘记将证书私钥的访问权授予解密进程的进程/任务所有者。所以,别忘了授予对私钥的访问权

我知道,当您在使用自定义/共享RSA-CSP密钥加密的web场中的所有服务器上共享web.config文件时,您还需要将容器中的密钥共享给需要解密web.config中密文的所有服务器。从服务器场中每个服务器上的容器导入密钥后,需要授予对asp.net应用程序在IIS中运行的应用程序池标识的访问权限。请参阅aspnet_regiis.exe工具的-pc、-px、-pi和-pa参数,了解如何分别创建、导出、导入和授权对RSA密钥的访问()。这是另一个很好的资源:

为了使这在实践中更具确定性,我在IIS中的域服务帐户下运行了我的应用程序,创建了一个自定义共享RSA密钥,通过我的web场导入,授予对域服务帐户密钥的访问权限,然后使用特定密钥加密web.config的敏感部分(请参阅aspnet_regiis.exe上的-pef和-pdf参数)

如果您正在加密应用程序设置,您可能需要考虑创建自定义的App.Copy/Web.CONFIG节(如果您不热衷于加密所有的“AppSt设置”)。然后,使用ASPNETSyReasix.EX.EXT右键加密它,在部署过程中分发受保护Web.CONFIG。(您可能会将加密的web.config与应用程序一起打包)。内置的configProtectionProvider可以透明地加密/解密app.config和web.config部分,非常方便

以下是文件中此类加密节的外观示例:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

 <configSections>
    <section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler"/>
 </configSections>

  <configProtectedData>
    <providers>
      <add name="MyKeyProvider"
           type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
           keyContainerName="MyKey"
           useMachineContainer="true" />
    </providers>
  </configProtectedData>

  <secureAppSettings configProtectionProvider="MyKeyProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>deadbeef</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>cafef00d</CipherValue>
      </CipherData>
    </EncryptedData>
  </secureAppSettings>

</configuration>

Rsa密钥
死牛肉
cafef00d

如您所见,开箱即用配置保护对XML EncryptedData使用相同的框架,但只为您执行所有加密工作。如果您正确授予私钥访问权限,则这对windows服务和桌面应用程序的工作方式相同。

我在使用EncryptedXml类X.509 cer时收到相同的错误ts,我忘了向解密进程的进程/任务所有者授予对证书私钥的访问权限。因此,不要忘了授予对私钥的访问权限

我知道,当您在使用自定义/共享RSA-CSP密钥加密的web场中的所有服务器上共享web.config文件时,您还需要将容器中的密钥共享给需要解密web.config中密文的所有服务器。一旦从场中每个服务器上的容器导入密钥,您需要t访问asp.net应用程序在IIS中运行的应用程序池标识。请参阅aspnet_regiis.exe工具的-pc、-px、-pi和-pa参数,了解如何分别创建、导出、导入和授权访问RSA密钥()。这是另一个很好的资源:

为了使这在实践中更具确定性,我在IIS中的域服务帐户下运行了我的应用程序,创建了一个自定义共享RSA密钥,通过我的web场导入,授予对域服务帐户密钥的访问权限,然后使用特定密钥加密web.config的敏感部分(请参阅aspnet_regiis.exe上的-pef和-pdf参数)

如果您正在加密应用程序设置,您可能需要考虑创建自定义的App.Copy/Web.CONFIG节(如果您不热衷于加密所有的“AppSt设置”)。然后,使用ASPNETSyReasix.EX.EXT右键加密它,在部署过程中分发受保护Web.CONFIG。(您可能会将加密的web.config与应用程序一起打包)。内置的configProtectionProvider可以透明地加密/解密app.config和web.config部分,非常方便

以下是文件中此类加密节的外观示例:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

 <configSections>
    <section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler"/>
 </configSections>

  <configProtectedData>
    <providers>
      <add name="MyKeyProvider"
           type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
           keyContainerName="MyKey"
           useMachineContainer="true" />
    </providers>
  </configProtectedData>

  <secureAppSettings configProtectionProvider="MyKeyProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>deadbeef</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>cafef00d</CipherValue>
      </CipherData>
    </EncryptedData>
  </secureAppSettings>

</configuration>

Rsa密钥
死牛肉
cafef00d

如您所见,开箱即用配置保护对XML EncryptedData使用相同的框架,但只为您执行所有加密工作。如果您正确授予私钥访问权限,则这对windows服务和桌面应用程序的工作方式相同。

我将您的加密函数更改为不传入RSA Alg,而是创建RSACryptServiceProv