Skip to main content

Signing XML documents with XAdES BES recommendation

1 reply [Last post]
krake
Offline
Joined: 2008-09-24
Points: 0

Hello everybody!

I'm working in a project about signing XML documents with the XAdES BES recommendation and I'm having many problems with that.

Following this recommendation I have to sign the document in a specific way and I'm having problems with the URI References that I must use.

The aspect of the XML Signed File must be like this:

<?xml version="1.0" encoding="UTF-8"?>

--Original File Base64 encoded--

RphAGnFD7dGYDFixRCsvGV880PY=

RphAGnFD7dGYDFixRCsvGV880PY=

RphAGnFD7dGYDFixRCsvGV880PY=

oCUazdm7uURsCh57SgKNcBQMF3IvDNmgie7ataaE0Rn1twpPoPfZ7IuWG0Ihy3hzAPBsWkd3ZOc6
CgUYZgUNtPz7lvwTbtb5Zh5HWw1u5i7yZ4nyXv1vN1MXUkDEd8IdDLKZ3kcZLdEtNRrIyS2UjKr+
p1HLW/ldRlXh4IlvWAA=

--X509Certificate public key content--

2008-09-23T10:14:33Z

To make a XML document like this I'm using de xmldsig libraries and following these steps:
1. Instance the XML signature factory:
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM", new org.jcp.xml.dsig.internal.dom.XMLDSigRI());

2. Make the list of references:
Reference fileRef = fac.newReference("#idSignedFile", fac.newDigestMethod(DigestMethod.SHA1, null));
Reference certRef = fac.newReference("#idKeyInfo", fac.newDigestMethod(DigestMethod.SHA1, null));
Reference dateRef = fac.newReference("#idSignedProperties", fac.newDigestMethod(DigestMethod.SHA1, null));
List refList = new ArrayList();
refList.add(fileRef);
refList.add(certRef);
refList.add(dateRef);

3. Make the SignedInfo structure:
SignedInfo si1 = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.unmodifiableList(refList));

4. Read the original file, encoding it with Base64 algorithm and add the result to the parts element:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
FileInputStream fis = new FileInputStream("C:/tmp/original_file.xml");
String sBase64 = new String(new Base64().encode(getString(fis).getBytes()));
Document documento = dbf.newDocumentBuilder().newDocument();
Element elRaiz = (Element) documento.appendChild(documento.createElement("documento"));
Element elPart = documento.createElement("parts");
elPart.setAttribute("Encoding","urn:ietf-org:base64");
elPart.setAttribute("FileName","fileName.xml");
elPart.setAttribute("Id","idSignedFile");
elPart.appendChild(documento.createTextNode(sBase64));
elRaiz.appendChild(elPart);

5. Retrieve the X509 certificate:
String sKeyStore = System.getProperty("javax.net.ssl.keyStore");
String sKeyStorePass = System.getProperty("javax.net.ssl.keyStorePassword");
String sKeyStoreType = System.getProperty("javax.net.ssl.keyStoreType");
KeyStore ks = KeyStore.getInstance(sKeyStoreType);
fisKS = new FileInputStream(sKeyStore);
ks.load(fisKS, sKeyStorePass.toCharArray());
X509Certificate cert = (X509Certificate) ks.getCertificate("certName");
PrivateKey key = (PrivateKey) ks.getKey("certName", "password".toCharArray());

6. Create the KeyInfo structure:
KeyInfoFactory kif = fac.getKeyInfoFactory();
X509Data xd = kif.newX509Data(Collections.singletonList(cert));
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd), "idKeyInfo");

7. Create the QualifyingProperties structure:
Document doc = dbf.newDocumentBuilder().newDocument();
Element elQualifProp = doc.createElement("QualifyingProperties");
Element elSignedSignatureProperties = doc.createElement("SignedSignatureProperties");
Element elSignedProperties = doc.createElement("SignedProperties");
elSignedProperties.setAttribute("id", "idSignedProperties");
Element elTime = doc.createElement("SigningTime");
elTime.appendChild(doc.createTextNode(fdate2String(new Date(), "yyyy-MM-dd'T'HH:mm:ss")));
elSignedSignatureProperties.appendChild(elTime);
elSignedProperties.appendChild(elSignedSignatureProperties);
elQualifProp.appendChild(elSignedProperties);
elQualifProp.setAttribute("Target", "idSignature");

8. Create the Object structure:
XMLObject object = fac.newXMLObject(Collections.singletonList(new DOMStructure(elQualifProp)), "idObject", null, null);

9. Create de DOMSignContext
DOMSignContext dsc = new DOMSignContext(key, documento.getDocumentElement());

10. Create the XMLSignature structure and sign de document:
XMLSignature signature1 = fac.newXMLSignature(si1, ki, Collections.singletonList(object), "idSignature", "idSignedInfo");
signature1.sign(dsc);

In the number 10 step, the sign method throws this exception:

javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: java.lang.NullPointerException
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
at firma.FirmanteXML.situNueva(FirmanteXML.java:245)
at firma.FirmanteXML.main(FirmanteXML.java:43)XMLSignatureException

Caused by: javax.xml.crypto.URIReferenceException: java.lang.NullPointerException
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(Unknown Source)
... 6 more
Caused by: java.lang.NullPointerException
at org.apache.xml.security.utils.IdResolver.isElement(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getEl(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getElementBySearching(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getElementById(Unknown Source)
at org.apache.xml.security.utils.resolver.implementations.ResolverFragment.engineResolve(Unknown Source)
at org.apache.xml.security.utils.resolver.ResourceResolver.resolve(Unknown Source)
... 7 more
javax.xml.crypto.URIReferenceException: java.lang.NullPointerException
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
at firma.FirmanteXML.situNueva(FirmanteXML.java:245)
at firma.FirmanteXML.main(FirmanteXML.java:43)
Caused by: java.lang.NullPointerException
at org.apache.xml.security.utils.IdResolver.isElement(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getEl(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getElementBySearching(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getElementById(Unknown Source)
at org.apache.xml.security.utils.resolver.implementations.ResolverFragment.engineResolve(Unknown Source)
at org.apache.xml.security.utils.resolver.ResourceResolver.resolve(Unknown Source)
... 7 more
javax.xml.crypto.URIReferenceException: java.lang.NullPointerException
at org.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.dereference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMReference.digest(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.digestReference(Unknown Source)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(Unknown Source)
at firma.FirmanteXML.situNueva(FirmanteXML.java:245)
at firma.FirmanteXML.main(FirmanteXML.java:43)
Caused by: java.lang.NullPointerException
at org.apache.xml.security.utils.IdResolver.isElement(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getEl(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getElementBySearching(Unknown Source)
at org.apache.xml.security.utils.IdResolver.getElementById(Unknown Source)
at org.apache.xml.security.utils.resolver.implementations.ResolverFragment.engineResolve(Unknown Source)
at org.apache.xml.security.utils.resolver.ResourceResolver.resolve(Unknown Source)
... 7 more

Does anybody know how to resolve the problem with de URI References?

Thank you very much in advance.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
krake
Offline
Joined: 2008-09-24
Points: 0

The problem is solved.

It was that that the document have to exist before making the References ->

In the 4th step, the document must exist before reference it. I.e. :
FileInputStream fis = new FileInputStream("C:/tmp/fileB64Codec.xml");
Document documento = dbf.newDocumentBuilder().parse(fis);

Where the document "C:/tmp/fileB64Codec.xml" already contains the original file codified in Base64 format. This is the content of this file:


--Original File Base64 encoded--