Search code examples
javaxmlsoapcertificatejax-rpc

Sign XML document in Header


i have this code and it works good, but the problem is that i want to add the sign in the header instead of the body.

I have tried changing DOMSignContext but nothing works

Any help will be very appreciated

Than you very much in advance

public boolean handleRequest(MessageContext context) {
    System.out.println("Inside handleRequest");
    SOAPMessageContext soapMsgCtx = null;
    try {

        soapMsgCtx = (SOAPMessageContext) context;
        SOAPMessage soapMessage = soapMsgCtx.getMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope soapEnvelope = soapMsgCtx.getMessage().getSOAPPart().getEnvelope();
        soapEnvelope.addNamespaceDeclaration("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        soapEnvelope.addNamespaceDeclaration("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
        SOAPHeader soapHeader = soapEnvelope.addHeader();
        SOAPElement security = soapHeader.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

        soapHeader.addHeaderElement(soapEnvelope.createName("Signature", "SOAP-SEC", "http://schemas.xmlsoap.org/soap/security/2000-12"));


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

        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream(new File("C:\\keystoreRegistradores")), "passkeystore".toCharArray());
        KeyStore.PrivateKeyEntry keyEntry
                = (KeyStore.PrivateKeyEntry) ks.getEntry("alias", new KeyStore.PasswordProtection("1111".toCharArray()));
        X509Certificate cert = (X509Certificate) keyEntry.getCertificate();

        KeyInfoFactory kif = fac.getKeyInfoFactory();
        List x509Content = new ArrayList();
        //x509Content.add(cert.getSubjectX500Principal().getName());
        X509IssuerSerial x509IssuerSerial = kif.newX509IssuerSerial(cert.getSubjectX500Principal().getName(), cert.getSerialNumber());
        x509Content.add(x509IssuerSerial);
        x509Content.add(cert);
        X509Data xd = kif.newX509Data(x509Content);
        KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse(new FileInputStream("C:/xmlsigned.xml"));

        DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement());

        XMLSignature signature = fac.newXMLSignature(si, ki);

        signature.sign(dsc);

        OutputStream os = new FileOutputStream("C:/xml.xml");
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(doc), new StreamResult(os));

    } catch (SOAPException e) {
        logSOAPMessage(soapMsgCtx);
        e.printStackTrace();
    } catch (Exception e) {
        logSOAPMessage(soapMsgCtx);
        e.printStackTrace();
    }
    return true;
}

Solution

  • Ok, i have found the answer by:

    Node node = doc.getElementsByTagName("wsse:Security").item(0);
    
            DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), node);
    

    Instead of

    DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), doc.getDocumentElement());