Что неверного в этом примере MSDN All-In-One XML для шифрования / дешифрования? - PullRequest
0 голосов
/ 20 января 2011

Я слил XML Шифрование и Расшифровка из MSDN в тот же проект, приведенный ниже, и получаю сообщение об ошибке

"Невозможно получить расшифровку ключ». alt text

Самое странное, что я могу написать закрытый ключ до и после исключения, поэтому я не уверен в том, в чем может быть проблема. Объединенный код ниже.

   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 KeyInfo element.
           edElement.KeyInfo = new KeyInfo();

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

       }

   }
   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 throws Exception:  <--------------
       //
       // Unable to retrieve the decryption key".
       //
        exml.DecryptDocument();

   }
    static void Main(string[] args)
    {

        string containerName = "XML_ENC_RSA_KEY";

   ////////////////////////////////////////////////////////
    // Create and persist a key pair
   //  Save the Public portion of the keypair in a string we will use later

        // Create a new CspParameters object to specify
        // a key container.
        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = containerName;

        // 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.
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
        rsaKey.PersistKeyInCsp = true;
        Console.WriteLine(rsaKey.ToXmlString(false));
        string PublicKeyTest = rsaKey.ToXmlString(false);




  ////////////////////////////////////////////////////////
    // Encrypt using a new instance of the crypto provider and the public key string



 Console.WriteLine();
        Console.WriteLine();
        Console.WriteLine();
       var rsaKey2 = new RSACryptoServiceProvider();
       rsaKey2.FromXmlString(PublicKeyTest);
       Console.WriteLine(rsaKey2.ToXmlString(false));
       PublicKeyTest = rsaKey2.ToXmlString(false);


        // Create an XmlDocument object.
        XmlDocument xmlDoc = new XmlDocument();

        // Load an XML file into the XmlDocument object.
        try
        {
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        try
        {
            // Encrypt the "creditcard" element.
            Encrypt(xmlDoc, "creditcard", "EncryptedElement1", rsaKey2, "rsaKey");


            // Save the XML document.
            xmlDoc.Save("testOUT.xml");

            // Display the encrypted XML to the console.
            Console.WriteLine("Encrypted XML:");
            Console.WriteLine();
            Console.WriteLine(xmlDoc.OuterXml);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            // Clear the RSA key.
            rsaKey2.Clear(); 
        }


        Console.ReadLine();


 ////////////////////////////////////////////////////////
// Decrypt the output, using the internal CSP

          xmlDoc = new XmlDocument();

        // Load an XML file into the XmlDocument object.
        try
        {
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("testOUT.xml");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
         cspParams = new CspParameters();
        cspParams.KeyContainerName = containerName;

        // Get the RSA key from the key container.  This key will decrypt
        // a symmetric key that was imbedded in the XML document.
        var rsaKey3 = new RSACryptoServiceProvider(cspParams);
          Console.WriteLine(rsaKey3.ToXmlString(true));
        try
        {

            // Decrypt the elements, throws exception
            Decrypt(xmlDoc, rsaKey3, "rsaKey");

            // Save the XML document.
            xmlDoc.Save("test3.xml");

            // Display the encrypted XML to the console.
            Console.WriteLine();
            Console.WriteLine("Decrypted XML:");
            Console.WriteLine();
            Console.WriteLine(xmlDoc.OuterXml);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {

        }


        Console.ReadLine();

Полное исключение (e)

System.Security.Cryptography.CryptographicException: Невозможно получить ключ дешифрования. в System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument () в RemoteKey.Decrypt (XmlDocument Doc, RSA Alg, String KeyName) в C: \ Users \ Me \ ClientAgent \ Program.cs: линия 185 at RemoteKey.Main (String [] args) в C: \ Users \ Me \ ClientAgent \ Program.cs: линия 286

1 Ответ

1 голос
/ 20 января 2011

Ваша функция Encrypt пишет XML, который не содержит элемент KeyName, поэтому ваш вызов DecryptDocument не может найти ключ.

Я не стал больше вдаваться в то, почему ваш Encrypt пишет неполный XML, но вы можете найти другой пример функции Encrypt в MSDN здесь: AddKeyNameMapping Method .

Замените только свою функцию Encrypt на функцию в этом примере MSDN, изменив только тип аргумента функции для Alg с SymmetricAlgorithm на RSA, и удалите третий аргумент "EncryptedElement1" из вызова Encrypt в существующем коде, чтобы получить его компилировать, и он должен работать до конца вашего Decrypt и работать.

После того, как вы запустите это, вы можете работать в обратном направлении, глядя на различия в вашем Шифровании по сравнению с тем, что в этом примере, или просто оставить его, если он работает для вас.

...