Decrypt XML with digital certificate private password

Asked

Viewed 1,075 times

0

I need to decrypt this XML:

<?xml version="1.0" encoding="UTF-8"?>
<xenc:EncryptedData
        xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
        Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod
        Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:X509Data>
        <ds:X509Certificate></ds:X509Certificate>
    </ds:X509Data>
    <xenc:EncryptedKey
            xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
        <xenc:EncryptionMethod
                Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
        <xenc:CipherData>
            <xenc:CipherValue></xenc:CipherValue>
        </xenc:CipherData>
    </xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData>
    <xenc:CipherValue></xenc:CipherValue>
</xenc:CipherData>

This is my project I’m running:

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)
{

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

    string arquivoXML = "C:\\Teste-Desc\\1-23042015-0703-ACE58971ACE59070.xml";
    string thumbPrintCertificado = "BA71F3AA888E0197D945D2A0CDE21C7E694CE432";


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

    // Create a new TripleDES key. 
    TripleDESCryptoServiceProvider tDESkey = new TripleDESCryptoServiceProvider();
    X509Certificate2 cert = BuscaConfiguracaoCertificado(thumbPrintCertificado);
    RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)cert.PrivateKey;

    try
    {            
        Decrypt(xmlDoc, rsaKey);


        // 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
    {
        // Clear the TripleDES key.
        tDESkey.Clear();
    }

}

public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, TripleDESCryptoServiceProvider Alg)
{

    //////////////////////////////////////////////// 
    // 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");

    }

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

    EncryptedXml eXml = new EncryptedXml();

    byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Alg, false);

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


    EncryptedData edElement = new EncryptedData();

    edElement.Type = EncryptedXml.XmlEncElementUrl;


    // Create an EncryptionMethod element so that the  
    // receiver knows which algorithm to use for decryption. 
    // Determine what kind of algorithm is being used and 
    // supply the appropriate URL to the EncryptionMethod element.

    edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncTripleDESUrl);

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

}

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

    // 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("rsaKey", Alg);

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

}

public static X509Certificate2 BuscaConfiguracaoCertificado(string sDigitalThumbPrint)
{
    X509Certificate2 x509Cert = null;

    X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
    X509Certificate2Collection collection1 = null;
    collection1 = (X509Certificate2Collection)collection.Find(X509FindType.FindByThumbprint, sDigitalThumbPrint, false);

    for (int i = 0; i < collection1.Count; i++)
    {
        x509Cert = collection1[i];
    }

    return x509Cert;
}

}

But when it comes down to it:

exml.DecryptDocument();

It generates the following exception: Unable to recover decryption key.

Second manual of the TJMG I must use the private key of the digital certificate of the customer...

I don’t know what else to do...

  • What is the exception class? (and preferably, the stack trace, to let us know exactly which method launched it) I don’t know about XML encryption, but if I know more about the exception I can see if I can find something to help you determine the cause of the error. By the way, you has the private key of the customer’s digital certificate, don’t you? Who encrypted this document?

  • The TJMG who generates the XML, he uses the public key of the client certificate to encrypt it, now I have to use the private to decrypt... About how it works... http://selos.tjmg.jus.br/developer/solicitaca-stamps.html The exception and the dot I put on the last lines..

  • "The exception and the point I put in the last lines.." where? I don’t see, the question only says "It generates the following exception: It is not possible to recover the decryption key." I understand it’s that line of code that doesn’t work, but to know where the exception is originated, only with the stack trace. The exception class also helps when searching for a solution. (by the way, the exception text is the same, in Portuguese?)

  • I just noticed here that your XML specifies the encryption algorithm as AES256-CBC, but you are trying to decipher it using 3DES...

1 answer

1

Partial response

I don’t have an answer to your question, but reading the quoted documentation I can see what you’re doing wrong (which is a first step to fixing). I don’t know how to use this type of C# encryption (by the way, in no language) however, so I will just explain what is happening in order to guide you in the search for a solution:

  1. Your document is encrypted using AES 256, CBC mode, a type of encryption symmetrical:
    <xenc:EncryptionMethod
            Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
  1. The encryption key (which, being symmetric, serves both to encrypt and to decipher) is contained in the document itself:

    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        ...
        <xenc:EncryptedKey
        xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
            ...
            <xenc:CipherData>
                <xenc:CipherValue></xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedKey>
    </ds:KeyInfo>
    

    ...but not in flat format (of course, so anyone could decipher!): it was encrypted using another key - one key cipher key (key-encryption key - KEK).

    <xenc:EncryptionMethod
            Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
    

    As you pointed out, it was encrypted with the customer’s public certificate key (RSA 1.5), thus requiring the corresponding private key to decrypt.

The Java code shown as reference is performing these operations correctly. Commenting:

// Obtém uma instância da cifra RSA 1.5 (para a KEK)
cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);

// Referencia o elemento que contém o item criptografado
Element ee = (Element) doc.getElementsByTagName("xenc:EncryptedData").item(0);

// Obtém uma instância da cifra AES 256 (para os dados de fato)
// Estou assumindo que o modo CBC é o modo padrão, quando um não é especificado
cipher = XMLCipher.getInstance(XMLCipher.AES_256);

// Inicializa
cipher.init(XMLCipher.DECRYPT_MODE, null);

// Atribui a chave cifradora de chaves
cipher.setKEK(rsaKey);

// Faz todas as operações necessárias, nos elementos corretos
// - Decifra a chave AES usando a chave RSA fornecida
// - Decifra os dados usando a chave AES decifrada
return cipher.doFinal(doc, ee);

It is therefore necessary to perform these same operations in C#. I believe (but cannot confirm from experience) that this "How to" implements all necessary steps:

    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "XML_ENC_RSA_KEY";

    // Get the RSA key from the key container.  This key will decrypt 
    // a symmetric key that was imbedded in the XML document.
    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

    try
    {
        // Decrypt the elements.
        Decrypt(xmlDoc, rsaKey, "rsaKey");

        // Save the XML document.
        xmlDoc.Save("test.xml");
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
    finally
    {
        // Clear the RSA key.
        rsaKey.Clear();
    }

(The Decrypt is the same as you are already doing)

I can’t guarantee that this will solve your problem (how to find this key in key store, This is something I have no idea how it works), but it’s a step in the right direction.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.