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;
		}
	}