Frage

Ich arbeite mit dem brasilianischen " Nota Fiscal Eletronica " Projekt, definieren, in dem sie eine standart Weise XML-Dokumente zu unterschreiben.

Vor kurzem begann sie zu verlangen, dass es absolut keine Leerzeichen zwischen den Tags, einschließlich der Signatur-Tags (*).

Wir passieren Apache XML Signature und ich kann nicht scheinen, um eine nicht vertiefte Signatur zu erzeugen.

Wenn ich die Leerzeichen nach Unterzeichnung entfernen, wird die Signatur gebrochen.

Ich kann die canonicalizer / Transformatoren setzen entweder ändern, da sie vordefiniert sind.

Ich konnte nicht eine Option oder Parameter in der XML Signature-API zur Steuerung Vertiefung oder Whitespaces finden.

Im Folgenden finden Sie den Code ein:

    // the element where to insert the signature
    Element element = ...;
    X509Certificate cert = ...;
    PrivateKey privateKey = ...;

    XMLSignature signer =
            new XMLSignature(doc, "http://xml-security",
            XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);

    element.appendChild(signer.getElement());

    Transforms transforms = new Transforms(doc);

    // Define as regras de transformação e canonicalização do documento
    // XML, necessário para fazer a verificação do parsing e da
    // assinatura pelos destinatários
    transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE); //, xpath.getElementPlusReturns());

    transforms.addTransform(Transforms.TRANSFORM_C14N_OMIT_COMMENTS); //,xpath.getElementPlusReturns());

    String id = "";

    id = ((Element) element.getElementsByTagName("infNFe").item(0)).getAttributeNode("Id").getNodeValue();

    signer.addDocument("#" + id, transforms, 
                       Constants.ALGO_ID_DIGEST_SHA1);
    signer.addKeyInfo(cert);
    signer.sign(privateKey);

Und unten ist die resultierende Signatur (Snippet):

<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe43110189716583000165550010000076011492273645">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>fas0ra5uRskQgRHSrIYhEjFEjKQ=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
2RGltUZy0HfNoiKtVanAeN+JUPyglWDuQNnMudSgA7kESoHBZ/q/GMbc+xMSN1eV8u7+2PxSKl1T
Zl592FWmCSAkL8pwMujDxJ4iTLU20Hf0dNF7oGcyB+g9GgbipW2udq0kwJLz6HzXUD/Evf/0y+3T
NtsXeIaA6A29ttD/UEs=
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
MIIFqTCCBJGgAwIBAgIEQeNSuzANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJicjETMBEGA1UE
ChMKSUNQLUJyYXNpbDEgMB4GA1UECxMXQ2FpeGEgRWNvbm9taWNhIEZlZGVyYWwxFDASBgNVBAMT
C0FDIENBSVhBIFBKMB4XDTEwMDYwODE5MjQwNVoXDTExMDYwODE5NTQwNVowgYQxCzAJBgNVBAYT
AmJyMRMwEQYDVQQKEwpJQ1AtQnJhc2lsMSAwHgYDVQQLExdDYWl4YSBFY29ub21pY2EgRmVkZXJh
bDEUMBIGA1UECxMLQUMgQ0FJWEEgUEoxKDAmBgNVBAMTH0EgQlVITEVSIFNBIENVUlRVTUU6NDA5
NDI0OTAwMTAwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOFxgvG35RQWgXec4zVrzoUHolnJ
fP76rpO2Vo40593W9Gf0WwHt36gVmli0ZeQitFmzFSoE5KhgXQGZg6RpV3WJUFcIrPBHPdqOSfiB
988kf962P+j8fZ38BNmo7TV9H9hMBkV9bD/QOe73wFDc+rT6/9io++Z+7/wup/3glKntAgMBAAGj
ggLOMIICyjAOBgNVHQ8BAf8EBAMCBeAwVwYDVR0gBFAwTjBMBgZgTAECAQkwQjBABggrBgEFBQcC
ARY0aHR0cDovL2ljcC5jYWl4YS5nb3YuYnIvcmVwb3NpdG9yaW8vZHBjYWNjYWl4YXBqLnBkZjAp
BgNVHSUEIjAgBggrBgEFBQcDAgYIKwYBBQUHAwQGCisGAQQBgjcUAgIwgbYGA1UdEQSBrjCBq4EV
YnVobGVyQGFidWhsZXIuY29tLmJyoD4GBWBMAQMEoDUEMzE0MDkxOTQ2NDA5NDI0OTAwMTAxMDg0
NDcwODE3NTAwMDAwODAzMjkyMjM1NlNTUCBSU6AeBgVgTAEDAqAVBBNOQUlSIEJVSExFUiBTQ0hO
RUNLoBkGBWBMAQMDoBAEDjg5NzE2NTgzMDAwMTY1oBcGBWBMAQMHoA4EDDAwMDAwMDAwMDAwMDCC
ATIGA1UdHwSCASkwggElMIGuoIGroIGohjJodHRwOi8vaWNwLmNhaXhhLmdvdi5ici9yZXBvc2l0
b3Jpby9BQ0NBSVhBUEoxLmNybIY0aHR0cDovL2ljcDIuY2FpeGEuZ292LmJyL3JlcG9zaXRvcmlv
Mi9BQ0NBSVhBUEoxLmNybIY8aHR0cDovL3JlcG9zaXRvcmlvLmljcGJyYXNpbC5nb3YuYnIvbGNy
L2NhaXhhL0FDQ0FJWEFQSjEuY3JsMHKgcKBupGwwajELMAkGA1UEBhMCYnIxEzARBgNVBAoTCklD
UC1CcmFzaWwxIDAeBgNVBAsTF0NhaXhhIEVjb25vbWljYSBGZWRlcmFsMRQwEgYDVQQDEwtBQyBD
QUlYQSBQSjEOMAwGA1UEAxMFQ1JMNDEwHwYDVR0jBBgwFoAUjkAvCv4T1ao5oHZ0htO8fcfx5c8w
CQYDVR0TBAIwADAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIDqDANBgkqhkiG9w0BAQUFAAOCAQEA
nZHUvdnZsiCIDjKm1zHehbtuDtDJha4O4FZ03J74Y+AxyAFs/4JED+xUvZ5jFuEsdqgA0V/dxUFy
Uz/ca10Ievd578GQdGwYl1GFhRtO/SlxeaOEf7eDdGOWXO3VmUA3NmNo0X8RRTIoifnhpDXu7RbN
5sijyH/uXyRFWX9XH2N0U/r3oJtNKXsvoUlbDrkalgkuLzLKsaEj0TkwisXO3cmMoWGuBpAZC+46
e4x/2vTqOvYkzZO+O9NLi0YWSYY7OJKiKBjMC6MzdlPM9VTkIwO9WvWEMdbU0/jhO2cMcVMzNZc1
r6ZmdTDrwqV3elSTkQtJ0RIZNgMJUn+Y8c7Aog==
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>

Beachten Sie die (unerwünschte) Zeilenumbrüche.

Jede Hilfe würde sehr geschätzt werden.

Vielen Dank im Voraus.

(*) Zur Verdeutlichung: das neue Regel verbietet Leerzeichen (oder irgendein anderer Text) zwischen Element-only-Tags. Als Beispiel wäre die erlaubt :

<a><b>
  text
  inside
  tag
</b></a>

, während dies wäre verboten :

<a>
<b>text</b>
</a>

, weil auf dem letzteren Fall wird die Leerzeichen (Zeilenumbrüche) zwischen zwei Tags, oder, mit anderen Worten, in einem Element-only-Tag gesetzt.

Andere Tipps

die Signaturblöcke codieren binäre Informationen als Base64, die muss folgen einige Formatierungen einschließlich Zeilenumbrüche (siehe http://en.wikipedia.org/wiki/Base64 ). So kann man einfach sie nicht entfernen, ohne ändern, um die Informationen.

ein besserer Weg zu redure Netzwerkverkehr ist comression zu verwenden, bevor Daten gesendet werden.

Zum Glück XML Signature heißt Open Source , so dass ich glaube, dass Sie den Quellcode erhalten müssen und hacken es Ihre selbst.

Wahrscheinlich wird Ihre Lösung andere in der Zukunft helfen, schaffen so einen Patch und schicken Sie es an dem Projekt zurück.

Viel Glück!

:) :)

Ich fand eine (beschämend) Lösung.

Es ist nicht die erwartete Lösung, aber:. Apache-API mit javax.xml.crypto API ersetzen

Hier ist der geänderte Code:

// the element where to insert the signature
Element element = ...;
X509Certificate cert = ...;
PrivateKey privateKey = ...;
// Create a DOM XMLSignatureFactory that will be used to
// generate the enveloped signature.
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

// Create a Reference to the enveloped document (in this case,
// you are signing the whole document, so a URI of "" signifies
// that, and also specify the SHA1 digest algorithm and
// the ENVELOPED Transform.
List<Transform> transformList = new ArrayList<Transform>();
TransformParameterSpec tps = null;
Transform envelopedTransform;
try {
    envelopedTransform = fac.newTransform(Transform.ENVELOPED,
            tps);
    Transform c14NTransform = fac.newTransform(
            "http://www.w3.org/TR/2001/REC-xml-c14n-20010315", tps);

    transformList.add(envelopedTransform);
    transformList.add(c14NTransform);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException("Erro inesperado: " + e.getMessage(), e);
} catch (InvalidAlgorithmParameterException e) {
    throw new RuntimeException("Erro inesperado: " + e.getMessage(), e);
}

// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = fac.getKeyInfoFactory();
List<Serializable> x509Content = new ArrayList<Serializable>();
x509Content.add(cert);
javax.xml.crypto.dsig.keyinfo.X509Data xd = kif.newX509Data(x509Content);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

// Obtem elemento do documento a ser assinado, será criado uma
// REFERENCE para o mesmo
Element el = (Element) element.getElementsByTagName(subTag).item(0);
String id = el.getAttribute("Id");

// Create a DOM XMLSignatureFactory that will be used to
// generate the enveloped signature.

Reference ref;
javax.xml.crypto.dsig.SignedInfo si;
try {
    ref = fac.newReference("#" + id, fac.newDigestMethod(
            DigestMethod.SHA1, null), transformList, null, null);

    // Create the SignedInfo.
    si = fac.newSignedInfo(fac.newCanonicalizationMethod(
            CanonicalizationMethod.INCLUSIVE,
            (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
            Collections.singletonList(ref));
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException("Erro inesperado: " + e.getMessage(), e);
} catch (InvalidAlgorithmParameterException e) {
    throw new RuntimeException("Erro inesperado: " + e.getMessage(), e);
}

// Create the XMLSignature, but don't sign it yet.
javax.xml.crypto.dsig.XMLSignature signature = fac.newXMLSignature(si, ki);

// Marshal, generate, and sign the enveloped signature.
// Create a DOMSignContext and specify the RSA PrivateKey and
// location of the resulting XMLSignature's parent element.
DOMSignContext dsc = new DOMSignContext(privateKey, element);
signature.sign(dsc);

Diese API erzeugt die Signatur ohne Leerzeichen zwischen den Tags überhaupt.

Still möchte eine Lösung für Apache-API, um zu sehen, da dieser Code sehr schon reift, und wir würden nicht wie Risiko so viel wie die gesamte Signatur Implementierung ändern.

Wir brauchen nur den „wahren“ Wert auf die „ignoreLineBreaks“ Parameter zu setzen, Ursache‘der Standardwert ist falsch und dies ermöglicht es den Signatur API Zeilenumbrüche

hinzufügen

Hier ist der Code zu vermeiden oder zu entfernen Zeilenumbrüche

Field f = XMLUtils.class.getDeclaredField("ignoreLineBreaks");
f.setAccessible(true);
f.set(null, Boolean.TRUE);

dann werden wir können sicherstellen, dass der neue Wert stimmt mit der nächsten Codezeile

System.err.println(XMLUtils.ignoreLineBreaks());

Ich hatte das gleiche Problem und das ist für mich gearbeitet.

Sie können versuchen:

System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");

XML Signature Zeichen Teil eines XML-Dokument mit einem bestimmten Elemente beginnen (das heißt eine Unterstruktur, DOM), nachdem er mit einem C14N Algorithmus normiert. Der Standard C14N Algorithmus Sie Konserven Zeilenumbrüche und Leerräume (siehe http: // www .w3.org / TR / XML-C14N # Beispiel-WhitespaceInContent ).

So alle Zeilenumbrüche in dem signierten Teil des Originaldokumentes (einschließlich zwischen dem letzten Tag der Daten und dem <Signature>-Tag, und zwischen </Signature> und dem nächsten schließenden Tag) * muss aufbewahrt werden, um nicht die Unterschrift zu ändern. Die Zeilenumbrüche und Leerzeichen im Signature Element selbst sind nicht wichtig und kann ohne Änderung der Signatur entfernt werden.

Hier ein Beispiel:

<root id="signedpart">
  <data>
     ...
  </data>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
     <SignedInfo>
       <Reference URI="#signedpart">
          ...
       </Reference>
     </SignedInfo>
  </Signature>
</root> 

Hier sind Ihre Möglichkeiten:

  1. definieren Sie Ihren eigenen C14N Algorithmus, die Leerzeichen und Zeilenumbrüche durch sie selbst entfernen. Ich würde dies als die andere Seite davon abhalten muß auch diesen Nicht-Standard-C14N Algorithmus verwenden.

  2. Entfernen Zeilenumbrüche ein Leerzeichen aus XML vor Wenn Sie sich es (und möglicherweise Leerzeichen entfernen in Unterschrift danach)

mit dem Beispiel dies werden Sie die folgende signierte XML:

<root id="signedpart"><data>...</data><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
       <Reference URI="#signedpart">
          ...
       </Reference>
     </SignedInfo>
  </Signature></root>

und nach Räumen in Unterschrift Entfernen

<root id="signedpart"><data>...</data><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><Reference URI="#signedpart">...</Reference></SignedInfo></Signature></root>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top