I am trying to use a
stylesheet when signing a xml document. I am adding the stylesheet to the ""
reference.
The stylesheet uses
a xsl:sort command and I always end up getting a
NullPointerException.
If I remove the
xsl:sort command from the stylesheet then it works fine.
Moreover, if I do
keep the xsl:sort command in the stylesheet, but add it to a reference within a
manifest then it works fine.
What makes me think
that this might be a bug is that I have tried two other xml signature libraries
and they both work fine in the first scenario described above (the one that
gives me the NullPointerException). I have tries XmlSec which is a C library and
IAIK IXSIL.
I am
using JDK1.3.1 and the latest versions of Xerces and
Xalan.
The code that I am
running is below.
Thanks.
--
Sanjay
public class
CreateSignature {
static org.apache.log4j.Category cat =
org.apache.log4j.Category.getInstance(CreateSignature.class.getName());
org.apache.log4j.Category.getInstance(CreateSignature.class.getName());
public static void main(String unused[]) throws Exception
{
Constants.setSignatureSpecNSprefix("");
Constants.setSignatureSpecNSprefix("");
String eForm = "<?xml version='1.0'
encoding='UTF-8'?>"
+ "<Class id='HereIAm'>"
+ "<Order Name='GAVIIFORMES'>"
+ "<Family Name='GAVIIDAE'>"
+ "<Species Scientific_Name='Gavia stellata'>Red-throated Loon.</Species>"
+ "<Species Scientific_Name='Gavia arctica'>Arctic Loon.</Species>"
+ "<Species Scientific_Name='Gavia pacifica'>Pacific Loon.</Species>"
+ "<Species Scientific_Name='Gavia immer'>Common Loon.</Species>"
+ "<Species Scientific_Name='Gavia adamsii'>Yellow-billed Loon.</Species>"
+ "</Family>"
+ "</Order>"
+ "<Order Name='TINAMIFORMES'>"
+ "<Family Name='TINAMIDAE'>"
+ "<Species Scientific_Name='Tinamus major'> Great Tinamou.</Species>"
+ "<Species Scientific_Name='Nothocercus'>Highland Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus soui'>Little Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus cinnamomeus'>Thicket Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus boucardi'>Slaty-breasted Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus kerriae'>Choco Tinamou.</Species>"
+ "</Family>"
+ "</Order>"
+ "</Class>";
+ "<Class id='HereIAm'>"
+ "<Order Name='GAVIIFORMES'>"
+ "<Family Name='GAVIIDAE'>"
+ "<Species Scientific_Name='Gavia stellata'>Red-throated Loon.</Species>"
+ "<Species Scientific_Name='Gavia arctica'>Arctic Loon.</Species>"
+ "<Species Scientific_Name='Gavia pacifica'>Pacific Loon.</Species>"
+ "<Species Scientific_Name='Gavia immer'>Common Loon.</Species>"
+ "<Species Scientific_Name='Gavia adamsii'>Yellow-billed Loon.</Species>"
+ "</Family>"
+ "</Order>"
+ "<Order Name='TINAMIFORMES'>"
+ "<Family Name='TINAMIDAE'>"
+ "<Species Scientific_Name='Tinamus major'> Great Tinamou.</Species>"
+ "<Species Scientific_Name='Nothocercus'>Highland Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus soui'>Little Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus cinnamomeus'>Thicket Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus boucardi'>Slaty-breasted Tinamou.</Species>"
+ "<Species Scientific_Name='Crypturellus kerriae'>Choco Tinamou.</Species>"
+ "</Family>"
+ "</Order>"
+ "</Class>";
String xslt = "<?xml
version='1.0'?>"
+ "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>"
+ "<xsl:output method='xml' indent='yes'/>"
+ "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>"
+ "<xsl:output method='xml' indent='yes'/>"
+ "<xsl:template
match='Class'>"
+ "<BirdInfo>"
+ "<xsl:apply-templates select='Order'>"
+ "<xsl:sort select='@Name'/>"
+ "</xsl:apply-templates>"
+ "</BirdInfo>"
+ "</xsl:template>"
+ "<BirdInfo>"
+ "<xsl:apply-templates select='Order'>"
+ "<xsl:sort select='@Name'/>"
+ "</xsl:apply-templates>"
+ "</BirdInfo>"
+ "</xsl:template>"
+ "<xsl:template
match='Order'>Order is: <xsl:value-of select='@Name'/>"
+ "<xsl:apply-templates select='Family'/><xsl:text>"
+ "</xsl:text>"
+ "</xsl:template>"
+ "<xsl:apply-templates select='Family'/><xsl:text>"
+ "</xsl:text>"
+ "</xsl:template>"
+ "<xsl:template
match='Family'>Family is: <xsl:value-of select='@Name'/>"
+ "<xsl:apply-templates select='Species | SubFamily | text()'/>"
+ "</xsl:template>"
+ "<xsl:apply-templates select='Species | SubFamily | text()'/>"
+ "</xsl:template>"
+ "<xsl:template
match='SubFamily'>SubFamily is <xsl:value-of select='@Name'/>"
+ "<xsl:apply-templates select='Species | text()'/>"
+ "</xsl:template>"
+ "<xsl:apply-templates select='Species | text()'/>"
+ "</xsl:template>"
+ "<xsl:template
match='Species'>"
+ "<xsl:choose>"
+ "<xsl:when test=\"name(..)='SubFamily'\">"
+ "<xsl:text> </xsl:text><xsl:value-of select='.'/><xsl:text> </xsl:text><xsl:value-of select='@Scientific_Name'/>"
+ "</xsl:when>"
+ "<xsl:otherwise>"
+ "<xsl:value-of select='.'/><xsl:text> </xsl:text><xsl:value-of select='@Scientific_Name'/>"
+ "</xsl:otherwise>"
+ "</xsl:choose>"
+ "</xsl:template>"
+ "<xsl:choose>"
+ "<xsl:when test=\"name(..)='SubFamily'\">"
+ "<xsl:text> </xsl:text><xsl:value-of select='.'/><xsl:text> </xsl:text><xsl:value-of select='@Scientific_Name'/>"
+ "</xsl:when>"
+ "<xsl:otherwise>"
+ "<xsl:value-of select='.'/><xsl:text> </xsl:text><xsl:value-of select='@Scientific_Name'/>"
+ "</xsl:otherwise>"
+ "</xsl:choose>"
+ "</xsl:template>"
+
"</xsl:stylesheet>"
;
;
//J-
//All the parameters for the keystore
String keystoreType = "JKS";
String keystoreFile = "c:/xml/my_keys/tomcat.jks";
String keystorePass = "tomcat";
String privateKeyAlias = "eform";
String privateKeyPass = "tomcat";
String certificateAlias = "sanjay";
File signatureFile = new File("zsignature.xml");
//J+
KeyStore ks = KeyStore.getInstance(keystoreType);
FileInputStream fis = new FileInputStream(keystoreFile);
//All the parameters for the keystore
String keystoreType = "JKS";
String keystoreFile = "c:/xml/my_keys/tomcat.jks";
String keystorePass = "tomcat";
String privateKeyAlias = "eform";
String privateKeyPass = "tomcat";
String certificateAlias = "sanjay";
File signatureFile = new File("zsignature.xml");
//J+
KeyStore ks = KeyStore.getInstance(keystoreType);
FileInputStream fis = new FileInputStream(keystoreFile);
//load the
keystore
ks.load(fis, keystorePass.toCharArray());
ks.load(fis, keystorePass.toCharArray());
//get the private key for
signing.
PrivateKey privateKey = (PrivateKey)ks.getKey(privateKeyAlias, privateKeyPass.toCharArray());
String keyFormat = privateKey.getFormat();
PrivateKey privateKey = (PrivateKey)ks.getKey(privateKeyAlias, privateKeyPass.toCharArray());
String keyFormat = privateKey.getFormat();
javax.xml.parsers.DocumentBuilderFactory
dbf =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilderFactory.newInstance();
//XML Signature needs to be namespace
aware
dbf.setNamespaceAware(true);
dbf.setNamespaceAware(true);
javax.xml.parsers.DocumentBuilder db =
dbf.newDocumentBuilder();
//The BaseURI is the URI that's used to
prepend to relative URIs
InputStream istream = new StringBufferInputStream(eForm);
org.w3c.dom.Document doc = db.parse(istream);
String BaseURI = signatureFile.toURL().toString();
//Create an XML Signature object from the document, BaseURI and
//signature algorithm (in this case DSA)
XMLSignature sig = new XMLSignature(doc, BaseURI,
XMLSignature.ALGO_ID_SIGNATURE_RSA);
InputStream istream = new StringBufferInputStream(eForm);
org.w3c.dom.Document doc = db.parse(istream);
String BaseURI = signatureFile.toURL().toString();
//Create an XML Signature object from the document, BaseURI and
//signature algorithm (in this case DSA)
XMLSignature sig = new XMLSignature(doc, BaseURI,
XMLSignature.ALGO_ID_SIGNATURE_RSA);
Element root = doc.getDocumentElement();
root.appendChild(sig.getElement());
root.appendChild(sig.getElement());
{
//create the transforms object for the Document/Reference
Transforms transforms = new Transforms(doc);
//create the transforms object for the Document/Reference
Transforms transforms = new Transforms(doc);
//First we have to strip
away the signature element (it's not part of
the
//signature calculations). The enveloped transform can be used for this.
//signature calculations). The enveloped transform can be used for this.
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
//Part of the signature
element needs to be canonicalized. It is a
kind
//of normalizing algorithm for XML. For more information please take a
//look at the W3C XML Digital Signature webpage.
//of normalizing algorithm for XML. For more information please take a
//look at the W3C XML Digital Signature webpage.
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
//Add the above Document/Reference
//Add the above Document/Reference
// xslt transform
org.w3c.dom.Document docxslt = db.parse(new ByteArrayInputStream(xslt.getBytes()));
Node xslElem = docxslt.getDocumentElement();
Node xslElemImported = doc.importNode(xslElem, true);
transforms.addTransform(Transforms.TRANSFORM_XSLT, (Element) xslElemImported);
sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
}
org.w3c.dom.Document docxslt = db.parse(new ByteArrayInputStream(xslt.getBytes()));
Node xslElem = docxslt.getDocumentElement();
Node xslElemImported = doc.importNode(xslElem, true);
transforms.addTransform(Transforms.TRANSFORM_XSLT, (Element) xslElemImported);
sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
}
{
//Add in the KeyInfo for the certificate that we used the private key of
X509Certificate cert =
(X509Certificate) ks.getCertificate(certificateAlias);
//Add in the KeyInfo for the certificate that we used the private key of
X509Certificate cert =
(X509Certificate) ks.getCertificate(certificateAlias);
sig.addKeyInfo(cert);
System.out.println("Start signing");
sig.sign(privateKey);
System.out.println("Finished signing");
}
System.out.println("Start signing");
sig.sign(privateKey);
System.out.println("Finished signing");
}
FileOutputStream f = new
FileOutputStream(signatureFile);
XMLUtils.outputDOMc14nWithComments(doc,
f);
f.close();
System.out.println("Wrote signature to " + BaseURI);
}
}
System.out.println("Wrote signature to " + BaseURI);
}
}