Skip to content

Commit fae61b1

Browse files
change sign method (#6)
1 parent b0e1e0c commit fae61b1

File tree

3 files changed

+86
-35
lines changed

3 files changed

+86
-35
lines changed

src/main/java/io/github/project/openubl/xmlbuilderlib/xml/XMLSigner.java

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,9 @@
3434
import java.io.IOException;
3535
import java.security.InvalidAlgorithmParameterException;
3636
import java.security.NoSuchAlgorithmException;
37-
import java.security.NoSuchProviderException;
3837
import java.security.PrivateKey;
3938
import java.security.cert.X509Certificate;
40-
import java.util.ArrayList;
4139
import java.util.Collections;
42-
import java.util.List;
4340

4441
public class XMLSigner {
4542

@@ -48,36 +45,28 @@ public static Document signXML(
4845
String referenceID,
4946
X509Certificate certificate,
5047
PrivateKey privateKey
51-
) throws ParserConfigurationException, NoSuchAlgorithmException, XMLSignatureException, InvalidAlgorithmParameterException, MarshalException, IOException, SAXException {
48+
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, XMLSignatureException, MarshalException, IOException, SAXException, ParserConfigurationException {
5249
Document document = XmlSignatureHelper.convertStringToXMLDocument(text);
5350
return signXML(document, referenceID, certificate, privateKey);
5451
}
5552

5653
public static Document signXML(
57-
Document copyDocument,
54+
Document document,
5855
String referenceID,
5956
X509Certificate certificate,
6057
PrivateKey privateKey
6158
) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, MarshalException, XMLSignatureException, ParserConfigurationException {
62-
// Document copyDocument = XMLUtils.cloneDocument(document);
63-
64-
addUBLExtensions(copyDocument);
65-
addUBLExtension(copyDocument);
66-
Node nodeExtensionContent = addExtensionContent(copyDocument);
67-
68-
XMLSignatureFactory signatureFactory;
69-
// Try to install the Santuario Provider - fall back to the JDK provider if this does
70-
// not work
71-
try {
72-
signatureFactory = XMLSignatureFactory.getInstance("DOM", "ApacheXMLDSig");
73-
} catch (NoSuchProviderException ex) {
74-
signatureFactory = XMLSignatureFactory.getInstance("DOM");
75-
}
59+
addUBLExtensions(document);
60+
addUBLExtension(document);
61+
Node nodeExtensionContent = addExtensionContent(document);
7662

77-
DOMSignContext signContext = new DOMSignContext(privateKey, copyDocument.getDocumentElement());
63+
// Start the signing process
64+
DOMSignContext signContext = new DOMSignContext(privateKey, document.getDocumentElement());
7865
signContext.setDefaultNamespacePrefix("ds");
7966
signContext.setParent(nodeExtensionContent);
8067

68+
XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
69+
8170
Reference reference = signatureFactory.newReference("",
8271
signatureFactory.newDigestMethod(DigestMethod.SHA1, null),
8372
Collections.singletonList(signatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null);
@@ -86,25 +75,14 @@ public static Document signXML(
8675
signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
8776
signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(reference));
8877

89-
// Certificate
90-
List<X509Certificate> x509Content = new ArrayList<>();
91-
x509Content.add(certificate);
92-
9378
KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
94-
X509Data xdata = keyInfoFactory.newX509Data(x509Content);
79+
X509Data xdata = keyInfoFactory.newX509Data(Collections.singletonList(certificate));
9580
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(xdata));
9681

97-
// Sign
98-
XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
82+
XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo, null, referenceID, null);
9983
signature.sign(signContext);
10084

101-
Element elementParent = (Element) signContext.getParent();
102-
if ((referenceID != null) && (elementParent.getElementsByTagName("ds:Signature") != null)) {
103-
Element elementSignature = (Element) elementParent.getElementsByTagName("ds:Signature").item(0);
104-
elementSignature.setAttribute("Id", referenceID);
105-
}
106-
107-
return copyDocument;
85+
return document;
10886
}
10987

11088
private static void addUBLExtensions(Document document) {

src/main/java/io/github/project/openubl/xmlbuilderlib/xml/XmlSignatureHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public static void transformNonTextNodeToOutputStream(Node node, OutputStream os
8282

8383
public static byte[] getBytesFromDocument(Document outputDoc) throws Exception {
8484
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
85-
XmlSignatureHelper.transformNonTextNodeToOutputStream(outputDoc, outStream, false, "UTF-8");
85+
XmlSignatureHelper.transformNonTextNodeToOutputStream(outputDoc, outStream, false, "ISO-8859-1");
8686
return outStream.toByteArray();
8787
}
8888

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Copyright 2019 Project OpenUBL, Inc. and/or its affiliates
3+
* and other contributors as indicated by the @author tags.
4+
*
5+
* Licensed under the Eclipse Public License - v 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.eclipse.org/legal/epl-2.0/
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package io.github.project.openubl.xmlbuilderlib.xml;
18+
19+
import io.github.project.openubl.xmlbuilderlib.integrationtest.utils.CertificateDetails;
20+
import io.github.project.openubl.xmlbuilderlib.integrationtest.utils.CertificateDetailsFactory;
21+
import org.junit.jupiter.api.Test;
22+
import org.w3c.dom.Document;
23+
import org.w3c.dom.NodeList;
24+
25+
import javax.xml.crypto.dsig.Reference;
26+
import javax.xml.crypto.dsig.XMLSignature;
27+
import javax.xml.crypto.dsig.XMLSignatureFactory;
28+
import javax.xml.crypto.dsig.dom.DOMValidateContext;
29+
import javax.xml.parsers.DocumentBuilderFactory;
30+
import java.io.InputStream;
31+
import java.util.Iterator;
32+
33+
import static org.junit.jupiter.api.Assertions.assertTrue;
34+
35+
public class XMLSignerTest {
36+
37+
@Test
38+
public void signXML() throws Exception {
39+
// Given
40+
InputStream ksInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("LLAMA-PE-CERTIFICADO-DEMO-10467793549.pfx");
41+
CertificateDetails CERTIFICATE = CertificateDetailsFactory.create(ksInputStream, "password");
42+
43+
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("xml/invoice_specialCharacters.xml");
44+
45+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
46+
dbf.setNamespaceAware(true);
47+
Document documentToSign = dbf.newDocumentBuilder().parse(is);
48+
49+
// When
50+
Document signedDocument = XMLSigner.signXML(documentToSign, "PROJECT-OPENUBL", CERTIFICATE.getX509Certificate(), CERTIFICATE.getPrivateKey());
51+
52+
// Then
53+
NodeList nodeList = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
54+
if (nodeList.getLength() == 0) {
55+
throw new Exception("Cannot find Signature element");
56+
}
57+
58+
DOMValidateContext valContext = new DOMValidateContext(CERTIFICATE.getX509Certificate().getPublicKey(), nodeList.item(0));
59+
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
60+
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
61+
boolean coreValidity = signature.validate(valContext);
62+
assertTrue(coreValidity);
63+
64+
boolean signatureValidity = signature.getSignatureValue().validate(valContext);
65+
assertTrue(signatureValidity);
66+
67+
Iterator<Reference> i = signature.getSignedInfo().getReferences().iterator();
68+
for (int j = 0; i.hasNext(); j++) {
69+
boolean refValid = i.next().validate(valContext);
70+
assertTrue(refValid);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)