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

Reply via email to