xml_dsig_rsa_key with the signedinfo firmar con certificado .net xml xml-signature

with - Prefijo XML firmado.NET



xml signature java (3)

¿Hay alguna manera de establecer el prefijo en la Firma de un Documento XML Firmado (clase SignedXml en .Net)?

Entonces, en lugar de:

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#> ... </Signature>

Podría tener lo siguiente:

<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#> ... </ds:Signature>


Antes que nada, realmente no hay una buena razón para hacer esto. Las dos formas son funcionalmente equivalentes. Cualquier procesador XML de buen comportamiento los manejará de forma absolutamente idéntica. Por lo tanto, a menos que intente hablar con una aplicación que no implementa correctamente los espacios de nombres XML, es mejor (IMO) simplemente dejar el formulario predeterminado solo. (E incluso en ese caso, sería mejor, si es posible, obtener la aplicación defectuosa reparada en su lugar).

Dicho esto, puede establecer manualmente el prefijo en XmlElement que SignedXml.GetXml () devuelve y sus elementos secundarios usando XPath de esta manera:

XmlElement signature = signedXml.GetXml(); foreach (XmlNode node in signature.SelectNodes( "descendant-or-self::*[namespace-uri()=''http://www.w3.org/2000/09/xmldsig#'']")) { node.Prefix = "ds"; }


No se puede hacer. Si modifica el XML después de que se ha firmado, es posible que no se pueda verificar, como fue el caso en el ejemplo anterior. IMO es una falla en la implementación de firma digital de MSFT con la que tendrá que convivir.

Mucha gente dirá que no hay razón para hacer esto, y que son técnicamente correctos. Pero cuando se trata de un gran proveedor (es decir, un gobierno o banco estatal), buena suerte para que cambien de su parte. La mayoría de las implementaciones de referencia lo incluyen.

ACTUALIZACIÓN: la firma firma todo en el elemento SignedInfo, por lo que si va a actualizar ese elemento después del hecho, entonces la firma ya no es válida. Has "manipulado" el mensaje.


Se puede hacer, pero es necesario modificar la clase SignedXml para agregar el prefijo antes de obtener el valor de resumen del nodo SignedInfo.

El método ComputeSignature se modificará para agregar el parámetro de prefijo

public void ComputeSignature(string prefix){...}

Cuando se llama a este método, calcula el valor de la firma digiriendo el valor del nodo SignedInfo, si obtiene este valor sin el prefijo "ds" y luego agrega el prefijo obtendrá una firma no válida, por lo que tendrá que agregar el prefijo ANTES de obtener el valor de resumen del nodo signedinfo.

Este valor de resumen se genera en el método GetC14NDigest, por lo que este método se modificará para agregar el parámetro de prefijo y agregar el prefijo ANTES de obtener el valor de resumen

private byte[] GetC14NDigest(HashAlgorithm hash, string prefix) { XmlDocument document = new XmlDocument(); document.PreserveWhitespace = false; XmlElement e = this.SignedInfo.GetXml(); //get the signedinfo nodes document.AppendChild(document.ImportNode(e, true)); Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject; SetPrefix(prefix, document.DocumentElement); /*Set the prefix before getting the HASH*/ canonicalizationMethodObject.LoadInput(document); return canonicalizationMethodObject.GetDigestedOutput(hash); }

Ok, entonces ahora tienes el valor Signature de los nodos SignedInfo CON el prefijo "ds", dicho eso, todavía NO tienes el xml con el prefijo, así que si llamas al método GetXml obtendrás el xml sin el prefijo y, por supuesto, porque el valor de la firma se calculó teniendo en cuenta el prefijo ds, tendrá una firma no válida. Para evitar eso y obtener la estructura xml con el prefijo, debe modificar el método GetXml, agregar el parámetro de prefijo y llamar al método SetPrefix que agregará el prefijo "ds" a todos los nodos en Signature Xml.

public XmlElement GetXml(string prefix) { XmlElement e = this.GetXml(); SetPrefix(prefix, e); //return the xml structure with the prefix return e; }

Dejaré aquí la clase con esas modificaciones

CLASE DE CLASE

internal sealed class CustomSignedXml : SignedXml { XmlElement obj = null; public CustomSignedXml (XmlDocument xml) : base(xml) { } public CustomSignedXml (XmlElement xmlElement) : base(xmlElement) { } public XmlElement GetXml(string prefix) { XmlElement e = this.GetXml(); SetPrefix(prefix, e); return e; } public void ComputeSignature(string prefix) { this.BuildDigestedReferences(); AsymmetricAlgorithm signingKey = this.SigningKey; if (signingKey == null) { throw new CryptographicException("Cryptography_Xml_LoadKeyFailed"); } if (this.SignedInfo.SignatureMethod == null) { if (!(signingKey is DSA)) { if (!(signingKey is RSA)) { throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed"); } if (this.SignedInfo.SignatureMethod == null) { this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; } } else { this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1"; } } SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription; if (description == null) { throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated"); } HashAlgorithm hash = description.CreateDigest(); if (hash == null) { throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed"); } this.GetC14NDigest(hash, prefix); this.m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash); } private byte[] GetC14NDigest(HashAlgorithm hash, string prefix) { XmlDocument document = new XmlDocument(); document.PreserveWhitespace = false; XmlElement e = this.SignedInfo.GetXml(); document.AppendChild(document.ImportNode(e, true)); Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject; SetPrefix(prefix, document.DocumentElement); //Set the prefix before getting the HASH canonicalizationMethodObject.LoadInput(document); return canonicalizationMethodObject.GetDigestedOutput(hash); } private void BuildDigestedReferences() { Type t = typeof(SignedXml); MethodInfo m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance); m.Invoke(this, new object[] { }); } private void SetPrefix(string prefix, XmlNode node) { foreach (XmlNode n in node.ChildNodes) SetPrefix(prefix, n); node.Prefix = prefix; } }

Y la forma de usarlo

CustomSignedXml signedXml = new CustomSignedXml(); . .//your code . //compute the signature with the "ds" prefix signedXml.ComputeSignature("ds"); //get the xml of the signature with the "ds" prefix XmlElement xmlDigitalSignature = signedXml.GetXml("ds");