miércoles, 25 de julio de 2012

Cifrar elementos XML con certificados X.509

using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            // Creando un objeto XmlDocument.
            XmlDocument xmlDoc = new XmlDocument();

            // cargando un archivo XML en el objeto XmlDocument.
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");
                
            // Abrir el Almacen X.509 "CurrentUser" en modo solo lectura.
            X509Store store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);

            // Coloca todos los certificados en un  objeto X509Certificate2Collection.
            X509Certificate2Collection certCollection = store.Certificates;

            X509Certificate2 cert = null;

            // Recorrer cada certificado y encontrar el certificado 
            // con el nombre apropiado.
            foreach (X509Certificate2 c in certCollection)
            {
                if (c.Subject == "CN=XML_ENC_TEST_CERT")
                {
                    cert = c;

                    break;
                }
            }

            if (cert == null)
            {
                throw new CryptographicException("El certificado X.509 no se pudo eliminar.");
            }

            // Cierra el almacen.
            store.Close();

            // Encripta el elemento "creditcard".
            Encrypt(xmlDoc, "creditcard", cert);

            // Graba el documento XML.
            xmlDoc.Save("test.xml");

            // Muestra el Xml encriptado en la consola.
            Console.WriteLine("Encrypted XML:");
            Console.WriteLine();
            Console.WriteLine(xmlDoc.OuterXml);

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

    }

    public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, X509Certificate2 Cert)
    {
        // Chequea el argumento  
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (ElementToEncrypt == null)
            throw new ArgumentNullException("ElementToEncrypt");
        if (Cert == null)
            throw new ArgumentNullException("Cert");

        ///////////////////////////////////////////////////
        // Busca el elemento especificado en el objeto 
        //  XmlDocument y crea un nuevo objeto XmlElemnt.
        ///////////////////////////////////////////////////
        XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
        // Genera una XmlException si el elemento no es encontrado.
        if (elementToEncrypt == null)
        {
            throw new XmlException("El elemento no ha sido encontrado");

        }

        ////////////////////////////////////////////////////
        // Crea una nueva instancia de la clase EncryptedXml
        // y usa  el XmlElement encriptado con el  
        // Certificado X.509.
        ////////////////////////////////////////////////////

        EncryptedXml eXml = new EncryptedXml();

        // Encripta el elemento.
        EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);

        ////////////////////////////////////////////////////
        // Remplaza el elemento del objeto XmlDocument original
        // con el elemento EncryptedData.
        ////////////////////////////////////////////////////
        EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    }
}