XML文件的解密仅适用于单机

时间:2013-06-20 08:51:31

标签: c# xml c#-4.0 encryption

我编写需要从互联网加密的XML文件下载的应用程序,解密并从中获取一些信息。

出于测试目的,我将我的XML文件放在公共链接中,当我运行应用程序时,我的行为不一致。

这是我的代码,它使用加密文件并使用我的解密方法解密它:

                const string settingsFileUrl = @"sharedlink.com...";
                XmlDocument myXmlDocument = new XmlDocument();
                myXmlDocument.Load(settingsFileUrl);

                CspParameters cspParams = new CspParameters();
                cspParams.KeyContainerName = @"gf154de4-12f1-430a-8210-63fde92fbb17";
                //This private key is here just for testing purpose
                RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
                Utilities.Decryptor.Decrypt(myXmlDocument, rsaKey, "rsaKey");

这是我的解密代码:

 internal class Decryptor
    {
        public static void Decrypt(XmlDocument Doc, RSA Alg, string KeyName)
        {
            // Check the arguments.   
            if (Doc == null)
                throw new ArgumentNullException("Doc");
            if (Alg == null)
                throw new ArgumentNullException("Alg");
            if (KeyName == null)
                throw new ArgumentNullException("KeyName");

            // Create a new EncryptedXml object.
            EncryptedXml exml = new EncryptedXml(Doc);

            // Add a key-name mapping. 
            // This method can only decrypt documents 
            // that present the specified key name.
            exml.AddKeyNameMapping(KeyName, Alg);

            // Decrypt the element.
            exml.DecryptDocument();

        }
    }

当我在我的主要机器上调试此代码时,一切都像魅力一样。 当我在我的辅助机器上进行调试时,我从行Utilities.Decryptor.Decrypt(myXmlDocument, rsaKey, "rsaKey");

中收到错误“错误数据”

我仔细检查过,我的辅助机器可以访问xml文件。 我不知道可能是什么问题。 请帮忙: - (


更新: 这是我的加密代码:

  public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string KeyName)
       {
           // Check the arguments. 
           if (Doc == null)
               throw new ArgumentNullException("Doc");
           if (ElementToEncrypt == null)
               throw new ArgumentNullException("ElementToEncrypt");
           if (EncryptionElementID == null)
               throw new ArgumentNullException("EncryptionElementID");
           if (Alg == null)
               throw new ArgumentNullException("Alg");
           if (KeyName == null)
               throw new ArgumentNullException("KeyName");

           //////////////////////////////////////////////// 
           // Find the specified element in the XmlDocument 
           // object and create a new XmlElemnt object. 
           ////////////////////////////////////////////////
           XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

           // Throw an XmlException if the element was not found. 
           if (elementToEncrypt == null)
           {
               throw new XmlException("The specified element was not found");

           }
           RijndaelManaged sessionKey = null;

           try
           {
               ////////////////////////////////////////////////// 
               // Create a new instance of the EncryptedXml class 
               // and use it to encrypt the XmlElement with the 
               // a new random symmetric key. 
               ////////////////////////////////////////////////// 

               // Create a 256 bit Rijndael key.
               sessionKey = new RijndaelManaged();
               sessionKey.KeySize = 256;

               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;
               // Create an EncryptionMethod element so that the 
               // receiver knows which algorithm to use for decryption.

               edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
               // Encrypt the session key and add it to an EncryptedKey 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 the DataReference to the EncryptedKey.
               ek.AddReference(dRef);
               // Add the encrypted key to the 
               // EncryptedData object.

               edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
               // Set the KeyInfo element to specify the 
               // name of the RSA key. 


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

               // Specify a name for the key.
               kin.Value = KeyName;

               // 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)
           {
               // re-throw the exception. 
               throw e;
           }
           finally
           {
               if (sessionKey != null)
               {
                   sessionKey.Clear();
               }

           }

       }

也许会有所帮助


更新2:

我在(MSDN)用户对加密方法的评论中找到了。 他写了下一条评论: 发布的示例无效,因为它们没有使用相同的密钥。不仅在不同的机器上:在同一台机器上运行程序两次也不应该工作(对我来说不起作用),因为它们每次都使用不同的随机密钥。 尝试在创建密钥后添加此代码:

key = new RijndaelManaged();

byte[] passwordBytes = Encoding.UTF8.GetBytes("Password1234"); //password here
byte[] saltBytes = Encoding.UTF8.GetBytes("Salt"); // salt here (another string)
PasswordDeriveBytes p = new PasswordDeriveBytes(passwordBytes, saltBytes);
// sizes are devided by 8 because [ 1 byte = 8 bits ]
key.IV = p.GetBytes(key.BlockSize / 8);
key.Key = p.GetBytes(key.KeySize / 8);

现在程序使用相同的密钥和初始向量,加密和解密应该适用于所有计算机。 另外,考虑将密钥重命名为算法,否则这是非常误导的。我说这是来自MSDN的一个糟糕的,不好用的例子。

我尝试过使用它,但我不确定在解密方法中我需要提供哪个键和哪个键。 也许你会比我更了解它。 THX

1 个答案:

答案 0 :(得分:3)

"gf154de4-12f1-430a-8210-63fde92fbb17"不是RSA私钥 - 它太短了。你将它分配给一个名为KeyContainerName的字段,所以我猜它只是一个私钥的名称,它通过Windows加密API存储在你的PC上。由于其他PC没有安装该密钥,因此无效。

我不是Windows加密专家,所以我不知道如何解决它,但我希望这可以帮助你找到答案!