You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@santuario.apache.org by Colm O hEigeartaigh <co...@apache.org> on 2012/01/03 15:53:34 UTC
Re: xmlsec test
Hi Paul,
Could you create a test-case for this and I'll take a look?
Colm.
On Tue, Dec 27, 2011 at 9:01 PM, Paul <pp...@yahoo.com> wrote:
>
> I have a question about signing xml and then using xpaths against the new
> signature tags in the xml. In one case a co-worker checked in some code that
> had a very subtle change - here is a simplified example:
>
> (xmlsec 1.4.5)
>
> ...
> Document doc = dbf.newDocumentBuilder().parse( new FileInputStream(
> fileName ) );
>
> DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(),
> doc.getDocumentElement());
>
> XMLSignature signature = fac.newXMLSignature(si, ki);
>
> signature.sign(dsc);
>
> if ( doTransform == true )
> {
> OutputStream os = new FileOutputStream(outputFilename);
> TransformerFactory tf = TransformerFactory.newInstance();
> Transformer trans = tf.newTransformer();
> trans.transform(new DOMSource(doc), new StreamResult(os));
>
> doc = dbf.newDocumentBuilder().parse( new FileInputStream(
> outputFilename ) );
> }
> ...
>
> If I set the doTransform variable to true, then all of the code works as
> designed. On the other hand, if I set doTransform to false and just use the doc
> directly, then xpaths looking for "Signature" will fail. So, it seems that this
> last transformation step is required? Or another way of looking at it - you
> can't just have one Document object for operations both before signing and
> after signing - there has to be one transformation that takes place. I'm
> thinking about this in terms of server performance where there may be 50 - 100
> threads signing stuff at the same time.
>
> thanks,
> Paul.
>
>
>
--
Colm O hEigeartaigh
Talend Community Coder
http://coders.talend.com
Re: xmlsec test
Posted by Paul <pp...@yahoo.com>.
Thanks Colm for the explanation. I was able to get the test code to run as
expected.
Paul.
Re: xmlsec test
Posted by Colm O hEigeartaigh <co...@apache.org>.
Hi Paul,
The problem is that your Document is not namespace aware. Change the
following line:
> docFactory.setNamespaceAware( false );
to
> docFactory.setNamespaceAware( true );
Now you need to update your XPath expressions with the "ds" prefix, e.g.:
"/aaa/ds:Signature",
"/aaa/ds:Signature/ds:SignedInfo/ds:Reference/ds:DigestValue/text()",
and finally pass in org.apache.xml.security.test.DSNamespaceContext to
the executeXPath method as the NamespaceContext implementation. Then
the XPaths work without the final transformation step.
Colm.
On Thu, Jan 26, 2012 at 10:21 PM, Paul <pp...@yahoo.com> wrote:
>
> Sorry about not getting back to this issue - I was on vacation and then had the
> flu...
>
> I reworked the example to remove the p12 file and now everything is standalone.
> The only thing needed is an xmlsec jar file to use and in my test I was using
> 1.4.5.
>
> I don't have a JIRA login so I thought I would post the complete code here:
>
> -------------------------------------------------------------
> import java.io.ByteArrayInputStream;
> import java.io.ByteArrayOutputStream;
> import java.io.File;
> import java.io.FileInputStream;
> import java.io.StringWriter;
> import java.security.KeyPair;
> import java.security.KeyPairGenerator;
> import java.security.KeyStore;
> import java.security.Security;
> import java.security.cert.X509Certificate;
> import java.util.ArrayList;
> import java.util.Collections;
> import java.util.List;
>
> import javax.xml.crypto.dsig.CanonicalizationMethod;
> import javax.xml.crypto.dsig.DigestMethod;
> import javax.xml.crypto.dsig.Reference;
> import javax.xml.crypto.dsig.SignatureMethod;
> import javax.xml.crypto.dsig.SignedInfo;
> import javax.xml.crypto.dsig.Transform;
> import javax.xml.crypto.dsig.XMLSignature;
> import javax.xml.crypto.dsig.XMLSignatureFactory;
> import javax.xml.crypto.dsig.dom.DOMSignContext;
> import javax.xml.crypto.dsig.keyinfo.KeyInfo;
> import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
> import javax.xml.crypto.dsig.keyinfo.KeyValue;
> import javax.xml.crypto.dsig.keyinfo.X509Data;
> import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
> import javax.xml.crypto.dsig.spec.TransformParameterSpec;
> import javax.xml.namespace.NamespaceContext;
> import javax.xml.namespace.QName;
> import javax.xml.parsers.DocumentBuilder;
> import javax.xml.parsers.DocumentBuilderFactory;
> import javax.xml.transform.Transformer;
> import javax.xml.transform.TransformerException;
> import javax.xml.transform.TransformerFactory;
> import javax.xml.transform.dom.DOMSource;
> import javax.xml.transform.stream.StreamResult;
> import javax.xml.xpath.XPath;
> import javax.xml.xpath.XPathConstants;
> import javax.xml.xpath.XPathExpression;
> import javax.xml.xpath.XPathFactory;
>
> import org.w3c.dom.Document;
> import org.w3c.dom.NodeList;
>
>
> public class XmlSignerWithDoTransformIssue
> {
> public static void main( String[] args )
> {
> try
> {
> Tester tester = new Tester();
> System.out.println( "-----------------------------------
> ------------------" );
> tester.signAndDoXpaths( true );
> System.out.println( "-----------------------------------
> ------------------" );
> tester.signAndDoXpaths( false );
> }
> catch ( Exception ex )
> {
> System.out.println( "ex = " + ex.toString() );
> ex.printStackTrace();
> }
> }
> }
>
> class Tester
> {
>
> public void signAndDoXpaths( boolean doFinalTransform )
> throws Exception
> {
>
> System.out.println( "running w/ doFinalTransform set to " +
> doFinalTransform + "\n\n" );
>
> String xml =
> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
> "<aaa>" +
> " <bbb>PD94bWwgdm</bbb>" +
>
> "</aaa>";
>
> DocumentBuilderFactory docFactory =
> DocumentBuilderFactory.newInstance();
> docFactory.setNamespaceAware( false );
> DocumentBuilder builder = docFactory.newDocumentBuilder();
> Document doc = builder.parse( new ByteArrayInputStream(
> xml.getBytes() ) );
>
> XMLSignatureFactory fac = XMLSignatureFactory.getInstance
> ("DOM");
>
> Reference ref = fac.newReference
> ("", fac.newDigestMethod(DigestMethod.SHA1, null),
> Collections.singletonList
> (fac.newTransform
> (Transform.ENVELOPED, (TransformParameterSpec) null)),
> null, null);
>
> SignedInfo si = fac.newSignedInfo
> (fac.newCanonicalizationMethod
> (CanonicalizationMethod.INCLUSIVE,
> (C14NMethodParameterSpec) null),
> fac.newSignatureMethod( SignatureMethod.RSA_SHA1, null),
> Collections.singletonList(ref));
>
> KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
> kpg.initialize(512);
> KeyPair kp = kpg.generateKeyPair();
>
> KeyInfoFactory kif = fac.getKeyInfoFactory();
> KeyValue kv = kif.newKeyValue(kp.getPublic());
>
> KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
>
> DOMSignContext dsc = new DOMSignContext(kp.getPrivate(),
> doc.getDocumentElement());
>
> XMLSignature signature = fac.newXMLSignature(si, ki);
> signature.sign(dsc);
>
> // Output the resulting document - this seems to be a critical
> step that allows
> // stuff like xpaths to work
> if ( doFinalTransform == true )
> {
> ByteArrayOutputStream baos = new ByteArrayOutputStream
> ();
> TransformerFactory tf = TransformerFactory.newInstance
> ();
> Transformer trans = tf.newTransformer();
> trans.transform( new DOMSource(doc), new StreamResult(
> baos ) );
> String signedString = baos.toString();
> ByteArrayInputStream bais = new ByteArrayInputStream(
> signedString.getBytes() );
>
> doc = docFactory.newDocumentBuilder().parse( bais );
> }
>
> System.out.println( "xml signed successfully");
>
> System.out.println( "xml:\n" + convertDocToString( doc ) );
>
> String[] xpathList = new String[]
> {
> "/aaa/Signature",
> "/aaa/Signature/SignedInfo/Reference/DigestValue/text
> ()",
> "/aaa/Signature/SignatureValue/text()",
> "/aaa/Signature/KeyInfo/X509Data/X509Certificate/text
> ()",
> "/aaa/ns:Signature",
> };
>
> System.out.println( "\nrunning xpaths: \n" );
>
> for ( String xPathFromList : xpathList )
> {
> if ( xPathFromList.contains( "substring" ) ||
> xPathFromList.contains( "concat" ) )
> executeXPath( doc, xPathFromList,
> XPathConstants.STRING, null );
> else
> executeXPath( doc, xPathFromList,
> XPathConstants.NODESET, null );
> }
> }
>
> public Object executeXPath( Document doc, String strExpr, QName
> xpathConstant,
> NamespaceContext nsCtx ) throws Exception
> {
> Object result = null;
>
> System.out.println( "----" + strExpr + "----" );
>
> XPathFactory xpathFactory = XPathFactory.newInstance();
> XPath xpath = xpathFactory.newXPath();
>
> if ( nsCtx != null )
> xpath.setNamespaceContext( nsCtx );
>
> XPathExpression expr = xpath.compile( strExpr );
>
> if ( xpathConstant.equals( XPathConstants.NODESET ) )
> {
>
> result = expr.evaluate( doc, xpathConstant /*
> XPathConstants.NODESET */ );
>
> NodeList nodes = (NodeList) result;
> int len = nodes.getLength();
> System.out.println( "num nodes = " + len );
> for (int i = 0; i < nodes.getLength(); i++)
> {
> System.out.println( nodes.item( i ).getNodeName
> () );
> System.out.println( nodes.item( i ).getNodeValue
> () );
> //System.out.println( nodes.item( i ).getBaseURI
> () );
> //nodes.item( i ).get
> }
>
> }
> else if ( xpathConstant.equals( XPathConstants.NUMBER ) )
> {
> result = expr.evaluate( doc,
> xpathConstant /*XPathConstants.NUMBER */ );
> double dResult = Double.parseDouble( result.toString
> () );
> System.out.println( "number = " + dResult );
> }
> else if ( xpathConstant.equals( XPathConstants.STRING ) )
> {
> result = expr.evaluate( doc, xpathConstant );
> String str = result.toString();
> System.out.println( "string = " + str );
> }
>
> System.out.println( "-----------------" );
>
> return result;
> }
>
> private String convertDocToString( Document doc )
> {
> try
> {
> DOMSource domSource = new DOMSource( doc );
> StringWriter writer = new StringWriter();
> StreamResult result = new StreamResult( writer );
> TransformerFactory tf = TransformerFactory.newInstance
> ();
> Transformer transformer = tf.newTransformer();
> transformer.transform( domSource, result );
> writer.flush();
> return writer.toString();
> }
> catch ( TransformerException ex )
> {
> ex.printStackTrace();
> return null;
> }
> }
> }
> -----------------------------------------------------
>
>
>
> thanks,
> Paul.
>
>
--
Colm O hEigeartaigh
Talend Community Coder
http://coders.talend.com
Re: xmlsec test
Posted by Paul <pp...@yahoo.com>.
Sorry about not getting back to this issue - I was on vacation and then had the
flu...
I reworked the example to remove the p12 file and now everything is standalone.
The only thing needed is an xmlsec jar file to use and in my test I was using
1.4.5.
I don't have a JIRA login so I thought I would post the complete code here:
-------------------------------------------------------------
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class XmlSignerWithDoTransformIssue
{
public static void main( String[] args )
{
try
{
Tester tester = new Tester();
System.out.println( "-----------------------------------
------------------" );
tester.signAndDoXpaths( true );
System.out.println( "-----------------------------------
------------------" );
tester.signAndDoXpaths( false );
}
catch ( Exception ex )
{
System.out.println( "ex = " + ex.toString() );
ex.printStackTrace();
}
}
}
class Tester
{
public void signAndDoXpaths( boolean doFinalTransform )
throws Exception
{
System.out.println( "running w/ doFinalTransform set to " +
doFinalTransform + "\n\n" );
String xml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<aaa>" +
" <bbb>PD94bWwgdm</bbb>" +
"</aaa>";
DocumentBuilderFactory docFactory =
DocumentBuilderFactory.newInstance();
docFactory.setNamespaceAware( false );
DocumentBuilder builder = docFactory.newDocumentBuilder();
Document doc = builder.parse( new ByteArrayInputStream(
xml.getBytes() ) );
XMLSignatureFactory fac = XMLSignatureFactory.getInstance
("DOM");
Reference ref = fac.newReference
("", fac.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList
(fac.newTransform
(Transform.ENVELOPED, (TransformParameterSpec) null)),
null, null);
SignedInfo si = fac.newSignedInfo
(fac.newCanonicalizationMethod
(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod( SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair();
KeyInfoFactory kif = fac.getKeyInfoFactory();
KeyValue kv = kif.newKeyValue(kp.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
DOMSignContext dsc = new DOMSignContext(kp.getPrivate(),
doc.getDocumentElement());
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
// Output the resulting document - this seems to be a critical
step that allows
// stuff like xpaths to work
if ( doFinalTransform == true )
{
ByteArrayOutputStream baos = new ByteArrayOutputStream
();
TransformerFactory tf = TransformerFactory.newInstance
();
Transformer trans = tf.newTransformer();
trans.transform( new DOMSource(doc), new StreamResult(
baos ) );
String signedString = baos.toString();
ByteArrayInputStream bais = new ByteArrayInputStream(
signedString.getBytes() );
doc = docFactory.newDocumentBuilder().parse( bais );
}
System.out.println( "xml signed successfully");
System.out.println( "xml:\n" + convertDocToString( doc ) );
String[] xpathList = new String[]
{
"/aaa/Signature",
"/aaa/Signature/SignedInfo/Reference/DigestValue/text
()",
"/aaa/Signature/SignatureValue/text()",
"/aaa/Signature/KeyInfo/X509Data/X509Certificate/text
()",
"/aaa/ns:Signature",
};
System.out.println( "\nrunning xpaths: \n" );
for ( String xPathFromList : xpathList )
{
if ( xPathFromList.contains( "substring" ) ||
xPathFromList.contains( "concat" ) )
executeXPath( doc, xPathFromList,
XPathConstants.STRING, null );
else
executeXPath( doc, xPathFromList,
XPathConstants.NODESET, null );
}
}
public Object executeXPath( Document doc, String strExpr, QName
xpathConstant,
NamespaceContext nsCtx ) throws Exception
{
Object result = null;
System.out.println( "----" + strExpr + "----" );
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
if ( nsCtx != null )
xpath.setNamespaceContext( nsCtx );
XPathExpression expr = xpath.compile( strExpr );
if ( xpathConstant.equals( XPathConstants.NODESET ) )
{
result = expr.evaluate( doc, xpathConstant /*
XPathConstants.NODESET */ );
NodeList nodes = (NodeList) result;
int len = nodes.getLength();
System.out.println( "num nodes = " + len );
for (int i = 0; i < nodes.getLength(); i++)
{
System.out.println( nodes.item( i ).getNodeName
() );
System.out.println( nodes.item( i ).getNodeValue
() );
//System.out.println( nodes.item( i ).getBaseURI
() );
//nodes.item( i ).get
}
}
else if ( xpathConstant.equals( XPathConstants.NUMBER ) )
{
result = expr.evaluate( doc,
xpathConstant /*XPathConstants.NUMBER */ );
double dResult = Double.parseDouble( result.toString
() );
System.out.println( "number = " + dResult );
}
else if ( xpathConstant.equals( XPathConstants.STRING ) )
{
result = expr.evaluate( doc, xpathConstant );
String str = result.toString();
System.out.println( "string = " + str );
}
System.out.println( "-----------------" );
return result;
}
private String convertDocToString( Document doc )
{
try
{
DOMSource domSource = new DOMSource( doc );
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult( writer );
TransformerFactory tf = TransformerFactory.newInstance
();
Transformer transformer = tf.newTransformer();
transformer.transform( domSource, result );
writer.flush();
return writer.toString();
}
catch ( TransformerException ex )
{
ex.printStackTrace();
return null;
}
}
}
-----------------------------------------------------
thanks,
Paul.
Re: xmlsec test
Posted by Colm O hEigeartaigh <co...@apache.org>.
Could you submit the code as a working test-case (imports/keys etc.)
in a new JIRA here?
https://issues.apache.org/jira/browse/SANTUARIO
Colm.
On Tue, Jan 3, 2012 at 8:24 PM, Paul <pp...@yahoo.com> wrote:
> Hi Colm,
>
> run the code below w/ doFinalTransform true or false to see the difference...
>
> when transform is true, you will see the sig block found:
>
> ----/aaa/Signature----
> num nodes = 1
> Signature
> null
>
> but w/ transform false, you will see not found:
>
> ----/aaa/Signature----
> num nodes = 0
>
>
>
>
> I have combined code from a few different classes here to simplify things:
>
>
> public void signAndDoXpaths2()
> throws Exception
> {
> boolean doFinalTransform = true;
> String certFileName = "testcert.p12";
> String certPw = "123456";
>
> String xml =
> "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
> "<aaa>" +
> " <bbb>PD94bWwgdm</bbb>" +
>
> "</aaa>";
>
> DocumentBuilderFactory docFactory =
> DocumentBuilderFactory.newInstance();
> docFactory.setNamespaceAware( false );
> DocumentBuilder builder = docFactory.newDocumentBuilder();
> Document doc = builder.parse( new ByteArrayInputStream(
> xml.getBytes() ) );
>
> XMLSignatureFactory fac = XMLSignatureFactory.getInstance
> ("DOM");
>
> Reference ref = fac.newReference
> ("", fac.newDigestMethod(DigestMethod.SHA1, null),
> Collections.singletonList
> (fac.newTransform
> (Transform.ENVELOPED, (TransformParameterSpec) null)),
> null, null);
>
> // Create the SignedInfo.
> SignedInfo si = fac.newSignedInfo
> (fac.newCanonicalizationMethod
> (CanonicalizationMethod.INCLUSIVE,
> (C14NMethodParameterSpec) null),
> fac.newSignatureMethod( SignatureMethod.RSA_SHA1, null),
> Collections.singletonList(ref));
>
> if (Security.getProvider("BC") == null)
> {
> Security.addProvider( new
> org.bouncycastle.jce.provider.BouncyCastleProvider() );
> }
>
> KeyStore ks = null;
> ks = KeyStore.getInstance( "PKCS12", "BC" );
> File certFile = new File( certFileName );
> ks.load( new FileInputStream( certFile ), certPw.toCharArray
> () );
>
> String keyAlias = (String) ks.aliases().nextElement();
>
>
> X509Certificate cert = null;
> KeyStore.PrivateKeyEntry keyEntry = null;
>
> keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry
> (
> keyAlias,
> new KeyStore.PasswordProtection(
> certPw.toCharArray() )
> );
>
> cert = (X509Certificate) keyEntry.getCertificate();
>
> // Create the KeyInfo containing the X509Data.
> KeyInfoFactory kif = fac.getKeyInfoFactory();
> List x509Content = new ArrayList();
> x509Content.add(cert.getSubjectX500Principal().getName());
> x509Content.add(cert);
> X509Data xd = kif.newX509Data(x509Content);
> KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
>
> DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey
> (), doc.getDocumentElement());
> XMLSignature signature = fac.newXMLSignature(si, ki);
> signature.sign(dsc);
>
>
> // Output the resulting document - this seems to be a critical
> step that allows
> // stuff like xpaths to work
> if ( doFinalTransform == true )
> {
> byte[] outputData = new byte[ 10000 ];
> ByteArrayOutputStream baos = new ByteArrayOutputStream
> ();
> TransformerFactory tf = TransformerFactory.newInstance
> ();
> Transformer trans = tf.newTransformer();
> trans.transform( new DOMSource(doc), new StreamResult(
> baos ) );
> String signedString = baos.toString();
> ByteArrayInputStream bais = new ByteArrayInputStream(
> signedString.getBytes() );
>
> doc = docFactory.newDocumentBuilder().parse( bais );
> }
>
> System.out.println( "xml signed successfully");
>
> System.out.println( "xml:\n" + convertDocToString( doc ) );
>
> String[] xpathList = new String[]
> {
> "/aaa/Signature",
> "/aaa/Signature/SignedInfo/Reference/DigestValue/text
> ()",
> "/aaa/Signature/SignatureValue/text()",
> "/aaa/Signature/KeyInfo/X509Data/X509Certificate/text
> ()",
> "/aaa/ns:Signature",
> };
>
> for ( String xPathFromList : xpathList )
> {
> if ( xPathFromList.contains( "substring" ) ||
> xPathFromList.contains( "concat" ) )
> executeXPath( doc, xPathFromList,
> XPathConstants.STRING, null );
> else
> executeXPath( doc, xPathFromList,
> XPathConstants.NODESET, null );
> }
> }
>
>
>
> public Object executeXPath( Document doc, String strExpr, QName
> xpathConstant,
> NamespaceContext nsCtx ) throws Exception
> {
> Object result = null;
>
> System.out.println( "----" + strExpr + "----" );
>
> XPathFactory xpathFactory = XPathFactory.newInstance();
> XPath xpath = xpathFactory.newXPath();
>
> if ( nsCtx != null )
> xpath.setNamespaceContext( nsCtx );
>
> XPathExpression expr = xpath.compile( strExpr );
>
> if ( xpathConstant.equals( XPathConstants.NODESET ) )
> {
>
> result = expr.evaluate( doc, xpathConstant /*
> XPathConstants.NODESET */ );
>
> NodeList nodes = (NodeList) result;
> int len = nodes.getLength();
> System.out.println( "num nodes = " + len );
> for (int i = 0; i < nodes.getLength(); i++)
> {
> System.out.println( nodes.item( i ).getNodeName
> () );
> System.out.println( nodes.item( i ).getNodeValue
> () );
> //System.out.println( nodes.item( i ).getBaseURI
> () );
> //nodes.item( i ).get
> }
>
> }
> else if ( xpathConstant.equals( XPathConstants.NUMBER ) )
> {
> result = expr.evaluate( doc,
> xpathConstant /*XPathConstants.NUMBER */ );
> double dResult = Double.parseDouble( result.toString
> () );
> System.out.println( "number = " + dResult );
> }
> else if ( xpathConstant.equals( XPathConstants.STRING ) )
> {
> result = expr.evaluate( doc, xpathConstant );
> String str = result.toString();
> System.out.println( "string = " + str );
> }
>
> System.out.println( "-----------------" );
>
> return result;
> }
>
> private String convertDocToString( Document doc )
> {
> try
> {
> DOMSource domSource = new DOMSource( doc );
> StringWriter writer = new StringWriter();
> StreamResult result = new StreamResult( writer );
> TransformerFactory tf = TransformerFactory.newInstance
> ();
> Transformer transformer = tf.newTransformer();
> transformer.transform( domSource, result );
> writer.flush();
> return writer.toString();
> }
> catch ( TransformerException ex )
> {
> ex.printStackTrace();
> return null;
> }
> }
>
>
>
--
Colm O hEigeartaigh
Talend Community Coder
http://coders.talend.com
Re: xmlsec test
Posted by Paul <pp...@yahoo.com>.
Hi Colm,
run the code below w/ doFinalTransform true or false to see the difference...
when transform is true, you will see the sig block found:
----/aaa/Signature----
num nodes = 1
Signature
null
but w/ transform false, you will see not found:
----/aaa/Signature----
num nodes = 0
I have combined code from a few different classes here to simplify things:
public void signAndDoXpaths2()
throws Exception
{
boolean doFinalTransform = true;
String certFileName = "testcert.p12";
String certPw = "123456";
String xml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<aaa>" +
" <bbb>PD94bWwgdm</bbb>" +
"</aaa>";
DocumentBuilderFactory docFactory =
DocumentBuilderFactory.newInstance();
docFactory.setNamespaceAware( false );
DocumentBuilder builder = docFactory.newDocumentBuilder();
Document doc = builder.parse( new ByteArrayInputStream(
xml.getBytes() ) );
XMLSignatureFactory fac = XMLSignatureFactory.getInstance
("DOM");
Reference ref = fac.newReference
("", fac.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList
(fac.newTransform
(Transform.ENVELOPED, (TransformParameterSpec) null)),
null, null);
// Create the SignedInfo.
SignedInfo si = fac.newSignedInfo
(fac.newCanonicalizationMethod
(CanonicalizationMethod.INCLUSIVE,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod( SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));
if (Security.getProvider("BC") == null)
{
Security.addProvider( new
org.bouncycastle.jce.provider.BouncyCastleProvider() );
}
KeyStore ks = null;
ks = KeyStore.getInstance( "PKCS12", "BC" );
File certFile = new File( certFileName );
ks.load( new FileInputStream( certFile ), certPw.toCharArray
() );
String keyAlias = (String) ks.aliases().nextElement();
X509Certificate cert = null;
KeyStore.PrivateKeyEntry keyEntry = null;
keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry
(
keyAlias,
new KeyStore.PasswordProtection(
certPw.toCharArray() )
);
cert = (X509Certificate) keyEntry.getCertificate();
// Create the KeyInfo containing the X509Data.
KeyInfoFactory kif = fac.getKeyInfoFactory();
List x509Content = new ArrayList();
x509Content.add(cert.getSubjectX500Principal().getName());
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey
(), doc.getDocumentElement());
XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
// Output the resulting document - this seems to be a critical
step that allows
// stuff like xpaths to work
if ( doFinalTransform == true )
{
byte[] outputData = new byte[ 10000 ];
ByteArrayOutputStream baos = new ByteArrayOutputStream
();
TransformerFactory tf = TransformerFactory.newInstance
();
Transformer trans = tf.newTransformer();
trans.transform( new DOMSource(doc), new StreamResult(
baos ) );
String signedString = baos.toString();
ByteArrayInputStream bais = new ByteArrayInputStream(
signedString.getBytes() );
doc = docFactory.newDocumentBuilder().parse( bais );
}
System.out.println( "xml signed successfully");
System.out.println( "xml:\n" + convertDocToString( doc ) );
String[] xpathList = new String[]
{
"/aaa/Signature",
"/aaa/Signature/SignedInfo/Reference/DigestValue/text
()",
"/aaa/Signature/SignatureValue/text()",
"/aaa/Signature/KeyInfo/X509Data/X509Certificate/text
()",
"/aaa/ns:Signature",
};
for ( String xPathFromList : xpathList )
{
if ( xPathFromList.contains( "substring" ) ||
xPathFromList.contains( "concat" ) )
executeXPath( doc, xPathFromList,
XPathConstants.STRING, null );
else
executeXPath( doc, xPathFromList,
XPathConstants.NODESET, null );
}
}
public Object executeXPath( Document doc, String strExpr, QName
xpathConstant,
NamespaceContext nsCtx ) throws Exception
{
Object result = null;
System.out.println( "----" + strExpr + "----" );
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
if ( nsCtx != null )
xpath.setNamespaceContext( nsCtx );
XPathExpression expr = xpath.compile( strExpr );
if ( xpathConstant.equals( XPathConstants.NODESET ) )
{
result = expr.evaluate( doc, xpathConstant /*
XPathConstants.NODESET */ );
NodeList nodes = (NodeList) result;
int len = nodes.getLength();
System.out.println( "num nodes = " + len );
for (int i = 0; i < nodes.getLength(); i++)
{
System.out.println( nodes.item( i ).getNodeName
() );
System.out.println( nodes.item( i ).getNodeValue
() );
//System.out.println( nodes.item( i ).getBaseURI
() );
//nodes.item( i ).get
}
}
else if ( xpathConstant.equals( XPathConstants.NUMBER ) )
{
result = expr.evaluate( doc,
xpathConstant /*XPathConstants.NUMBER */ );
double dResult = Double.parseDouble( result.toString
() );
System.out.println( "number = " + dResult );
}
else if ( xpathConstant.equals( XPathConstants.STRING ) )
{
result = expr.evaluate( doc, xpathConstant );
String str = result.toString();
System.out.println( "string = " + str );
}
System.out.println( "-----------------" );
return result;
}
private String convertDocToString( Document doc )
{
try
{
DOMSource domSource = new DOMSource( doc );
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult( writer );
TransformerFactory tf = TransformerFactory.newInstance
();
Transformer transformer = tf.newTransformer();
transformer.transform( domSource, result );
writer.flush();
return writer.toString();
}
catch ( TransformerException ex )
{
ex.printStackTrace();
return null;
}
}