TransWikia.com

Firmar un XML con algoritmo sha256 con un archivo .pfx

Stack Overflow en español Asked by fsigu on December 20, 2021

Hols amigos estoy haciendo una aplicacion, que tiene que firmar un archivo xml mediante el algoritmo sha256, usando un archivo .pfx de firma electronica.

el codigo que tengo es el siguiente

public void Firmar()
    {
        string archivoFirma = @"C:archivosfirma.pfx";
        X509Certificate2 cert = new X509Certificate2(archivoFirma, "ClaveFirma", X509KeyStorageFlags.Exportable);
        RSACryptoServiceProvider crypt = (RSACryptoServiceProvider)cert.PrivateKey;



        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = true;
        xmlDoc.Load(@"c:archivosFA076.xml");
        SignXml(xmlDoc, crypt);
        xmlDoc.Save(@"c:archivosFA076Firmado.xml");
    }

    public void SignXml(XmlDocument xmlDoc, RSA rsaKey)
    {
        if (xmlDoc == null)
            throw new ArgumentException("xmlDoc");
        if (rsaKey == null)
            throw new ArgumentException("Key");


        SignedXml signedXml = new SignedXml(xmlDoc);
        signedXml.SigningKey = rsaKey;
        signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";



        Reference reference = new Reference();
        reference.Uri = "";
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);
        reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
        signedXml.AddReference(reference);
        signedXml.ComputeSignature();
        XmlElement xmlDigitalSignature = signedXml.GetXml();
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

    }

Justo al ejecutar la linea
signedXml.ComputeSignature();
me da el siguiente mensaje de error

Algoritmo especificado no es válido

Alguien de pronto que me pueda ayudar indicando que estoy haciendo mal??

One Answer

X509Certificate2carga la clave privada del archivo pfx file en el Microsoft Enhanced Cryptographic Provider v1.0 (provider type 1 a.k.a. PROV_RSA_FULL) el cual no tiene soporte para SHA-256. Existen otros proveedores de Crypto tales como Microsoft Enhanced RSA and AES Cryptographic Provider (provider type 24 a.k.a. PROV_RSA_AES) que sí tienen soporte de SHA-256. Aquí está la lista de proveedores y sus códigos.

Modifico tu código para cambiar el proveedor.

public void Firmar()
{
    string archivoFirma = @"C:archivosfirma.pfx";
    X509Certificate2 cert = new X509Certificate2(archivoFirma, "ClaveFirma", X509KeyStorageFlags.Exportable);

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.PreserveWhitespace = true;
    xmlDoc.Load(@"c:archivosFA076.xml");
    SignXml(xmlDoc, cert);
    xmlDoc.Save(@"c:archivosFA076Firmado.xml");
}

public void SignXml(XmlDocument xmlDoc, X509Certificate2 cert)
{
    if (xmlDoc == null)
        throw new ArgumentException("xmlDoc");
    if (cert == null)
        throw new ArgumentException("Cert");

    var exportedKeyMaterial = cert.PrivateKey.ToXmlString( /* includePrivateParameters = */ true);
    var key = new RSACryptoServiceProvider(new CspParameters(24 /* PROV_RSA_AES */));
    key.PersistKeyInCsp = false;
    key.FromXmlString(exportedKeyMaterial);

    SignedXml signedXml = new SignedXml(xmlDoc);
    signedXml.SigningKey = key;
    signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

    Reference reference = new Reference();
    reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
    reference.AddTransform(new XmlDsigExcC14NTransform());
    reference.Uri = ""; 
    signedXml.AddReference(reference);

    KeyInfo keyInfo = new KeyInfo();
    keyInfo.AddClause(new KeyInfoX509Data(cert));
    signedXml.KeyInfo = keyInfo;

    signedXml.ComputeSignature();
    XmlElement xmlDigitalSignature = signedXml.GetXml();
    xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

}

Answered by Sergio Parra Guerra on December 20, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP