Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify SOAP request using the X509 certificate

I have a SOAP server. The SOAP request that is receiving at the server has ws security headers. Following are the main nodes of the request XML.

  1. BinarySecurityToken (X509PKIPathv1 certificate)
  2. DigestMethod
  3. DigestValue
  4. SignatureValue
  5. SecurityTokenReference

  6. Data (data that is send by client in SOAP body)

I have to verify the request using the certificate (.cer files) which is provided by the client (sender of the request).

What are the steps to validate the requests? Please explain the concept. No libraries are available for doing this. After a long research I am able to match BinarySecurityToken with base64_encode($certFile) $certFile is the requester's certifiate. Now I am researching how to matchDigestValue with what.

like image 289
Kiren S Avatar asked Oct 16 '15 08:10

Kiren S


1 Answers

WS-Security headers can be verified by the following. I have written an utility for that. Have a look at it.

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.security.KeyStore;
import java.security.Provider;
import java.security.PublicKey;
import java.security.cert.X509Certificate;

import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;


public class WSUtil {
    public static void main(String[] args) throws Exception {

        String req = "SOAPMESSAGE";
        Document p = createXMLDocument(req);
        InputStream inStream = new FileInputStream("certificate.p12"); //Provide your certificate file

        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(inStream, "pass".toCharArray()); //Certificate password - pass

        String alias = ks.aliases().nextElement();
        X509Certificate certificate = (X509Certificate) ks.getCertificate(alias);

        validateSignature(p.getElementsByTagName("ds:Signature").item(0),p.getElementsByTagName("soapenv:Body").item(0),certificate.getPublicKey());//True if the message is valid
    }

    public static Document createXMLDocument(String xmlString) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder;
        Document document = null;
        try {
            builder = factory.newDocumentBuilder();
            document = builder.parse(new InputSource(
                    new StringReader(xmlString)));
        } catch (Exception e) {
            throw e;
        }
        return document;
    }

    private static boolean validateSignature(Node signatureNode, Node bodyTag, PublicKey publicKey) {
        boolean signatureIsValid = false;
        try {
            // Create a DOM XMLSignatureFactory that will be used to unmarshal the
            // document containing the XMLSignature
            String providerName = System.getProperty
                    ("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",
                    (Provider) Class.forName(providerName).newInstance());

            // Create a DOMValidateContext and specify a KeyValue KeySelector
            // and document context
            DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(publicKey), signatureNode);
            valContext.setIdAttributeNS((Element) bodyTag, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id");

            // Unmarshal the XMLSignature.
            XMLSignature signature = fac.unmarshalXMLSignature(valContext);
            // Validate the XMLSignature.
            signatureIsValid = signature.validate(valContext); 

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return signatureIsValid;
    }
}

Note You have to provide the SOAP message as it is. You shouldn't do any XML format or any empty space somewhere. The security added SOAP message is very sensitive. Even a space at the end will make the SOAP message as invalid.

like image 153
Pasupathi Rajamanickam Avatar answered Sep 18 '22 08:09

Pasupathi Rajamanickam