SOAP WS Security and Signing java - Yash-777/Axis1x_Soap GitHub Wiki

In SoapUI, click Preferences on the main toolbar or select File > Preferences and switch to the SSL Preferences page.

SSL Preferences
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.OutputKeys;
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 org.apache.commons.io.IOUtils;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

//dependency: groupId:xml-security, artifactId:xmlsec, version:1.3.0
//dependency: groupId:xalan, artifactId:xalan, version:2.7.1
public class SoapWSSSigning_Delivery {
    static boolean useProxy = false, isClassPath = true, isDataXML = true,isSSL = true;
    static String path = "C:/Yash/SOAP/",   
            privateKeyFilePath = path+"Baeldung.p12", passwordPrivateKey = "password", publicKeyFilePath = path+ "Baeldung.cer", 
            sslKeystoreFilePath = path+"Baeldung_SSL.crt", // Import to java/certs to find alias name.
                certSSLAlias = "Baeldung_SSL (2018)",
                inputFile = path+ "Soap1.xml";

    static String soapEndpointUrl = "https://******:1443/";
    static final String PROXY_ADDRESS = "****.net";
    static final int PROXY_PORT = 9400;
    
    static X509Certificate loadPublicKeyX509;
    static PrivateKey privateKey;
    static int liveTimeInSeconds = 5 * 60;
    // <wsu:Timestamp wsu:Id="Timestamp"><wsu:Created>2021-01-28T11:32:48.763Z</wsu:Created> <wsu:Expires>33:48.770Z</wsu:Expires></wsu:Timestamp>
    public static void main(String[] args) throws Exception {
        useProxy = true; isClassPath = false;
        soapMSGWSS_Req();
    }

    public static void soapMSGWSS_Req() throws Exception {
        InputStream privateKeyStream = getCerFileStream(isClassPath, privateKeyFilePath);
        InputStream publicKeyStream = getCerFileStream(isClassPath, publicKeyFilePath);
        InputStream sslCertificateStream = getCerFileStream(isClassPath, sslKeystoreFilePath);
        
        loadPublicKeyX509 = loadPublicKeyX509(publicKeyStream);
        //PublicKey publicKey = loadPublicKeyX509.getPublicKey();
        privateKey = loadPrivateKeyforSigning(privateKeyStream, passwordPrivateKey);
        
        SOAPMessage soapMsg = WS_Security_signature(inputFile, isDataXML);
        
        String soapMessage = getSoapMessageFromStream(soapMsg);
        System.out.println("SoapMessage: "+soapMessage);
        
        System.out.println("Initiate Request.");
        sendScheduleRequest(soapEndpointUrl, soapMessage, soapMsg, sslCertificateStream);
    }
    
    static HashMap<String, String> serverDetails = new HashMap<String, String>();
    static {
        addBCProvider();
        
        serverDetails.put("SoapWSDL", "");
        serverDetails.put("SoapBinding", "");
        serverDetails.put("MethodName", "");
        serverDetails.put("SOAPAction", "");
        
        serverDetails.put("User-Agent", "Apache-HttpClient");
        serverDetails.put("Accept-Encoding", "gzip,deflate,sdch");
        serverDetails.put("Content-Type", "text/xml;charset=UTF-8");
    }
    public static void sendScheduleRequest(String endpointUrl, String soapxmLasString, SOAPMessage soapMsg, InputStream sslCertificateStream) throws Exception {
        System.out.println("\n===== java.net.HttpURLConnection =====");
        
        URL url = new URL(null, endpointUrl);
        String protocol = url.getProtocol();
        System.out.println("Protocol: "+protocol);
        URLConnection connection;
        
        HttpsURLConnection connectionHttps = null;
        if (isSSL) {
            if (useProxy) {
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_ADDRESS, PROXY_PORT));
                connectionHttps = (HttpsURLConnection) url.openConnection(proxy);
            } else {
                connectionHttps = (HttpsURLConnection) url.openConnection();
            }
            connectionHttps.setHostnameVerifier(getHostnameVerifier());
            
            SSLSocketFactory sslSocketFactory = getCertificateFactoryBasedSSLContext(sslCertificateStream, certSSLAlias).getSocketFactory();
            if (sslSocketFactory != null) {
                connectionHttps.setSSLSocketFactory(sslSocketFactory);
            }
            connection = connectionHttps;
        } else {
            if (useProxy) {
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_ADDRESS, PROXY_PORT));
                connection = (HttpURLConnection) url.openConnection(proxy);
            } else {
                connection = (HttpURLConnection) url.openConnection();
            }
        }
        
        /*String authString = username + ":" + password;
        String authMsg = "Basic " + Base64.encode(authString.getBytes());
        connection.setRequestProperty("Authorization", authMsg);*/
        
        connection.setReadTimeout(100 * 1000); // java.net.SocketTimeoutException: Read timed out < connection.getResponseCode()
        connection.setConnectTimeout(20 * 1000);
        //setDoOutput=true causes the URLConnection to perform a POST operation
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(true);
        
        if (isSSL) {
            ((HttpsURLConnection) connection).setRequestMethod("POST");
        } else {
            ((HttpURLConnection) connection).setRequestMethod("POST");
        }
        
        connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.ACCEPT, "text/xml"); //The request body will be in XML format
        connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.9");
        connection.setRequestProperty("MethodName", serverDetails.get("MethodName") );
        connection.setRequestProperty("SOAPAction", serverDetails.get("SOAPAction") );
        connection.setRequestProperty("HTTP_ACCEPT_ENCODING", "gzip, deflate, br");
        connection.setRequestProperty("Accept-Encoding", serverDetails.get("Accept-Encoding"));
        //String soapxmLasString = getSoapMessage(request);
        connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE, "text/xml");// serverDetails.get("Content-Type")
        connection.setRequestProperty( "Content-Length", String.valueOf(soapxmLasString.length()));
        
        //DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
        //dataOutputStream.writeBytes(soapxmLasString);
        // https://stackoverflow.com/a/55350935/5081877
        OutputStream outputStream = connection.getOutputStream();
        soapMsg.writeTo(outputStream);outputStream.flush();
        
        Writer wr = new OutputStreamWriter(outputStream);
            wr.write(soapxmLasString);
            wr.flush();
        // java.lang.IllegalStateException: Already connected [Occurs At] After connection.getOutputStream(); trying to setRequestProperty() this occurs. 
            
        // https://gist.github.com/kodiyan/10022988
        String contentEncoding = connection.getContentEncoding();
        System.out.println("Encoding:"+ contentEncoding);
        
        long start = System.currentTimeMillis();
        int responseCode;
        String responseMessage;
        if (isSSL) {
            responseCode = ((HttpsURLConnection)connection).getResponseCode();
            responseMessage = ((HttpsURLConnection)connection).getResponseMessage();
        } else {
            responseCode = ((HttpURLConnection)connection).getResponseCode();
            responseMessage = ((HttpURLConnection)connection).getResponseMessage();
        }
        System.out.println("Response Code: " + responseCode + " " + responseMessage);
        
        String xmlRply = null ;
        String requestStatus = "Fail";
        if (responseCode == HttpURLConnection.HTTP_OK) {
            requestStatus = "Pass";
            
            InputStream inputStream = connection.getInputStream();
            xmlRply = getStreamContent(inputStream, contentEncoding);
        } else if (responseCode >= 400 && responseCode < 500) { // Response Code: 404 Not Found
            
        } else if (responseCode >= 500) { // Response Code: 500 Internal Server Error
            // Exception in thread "main" java.io.IOException: Server returned HTTP response code: 500 for URL: https://graphical.weather.gov:443/xml/SOAP_server/ndfdXMLserver.php
            InputStream errorStream;
            if (isSSL) {
                errorStream = ((HttpsURLConnection)connection).getErrorStream();
            } else {
                errorStream = ((HttpURLConnection)connection).getErrorStream();
            }
            xmlRply = getStreamContent(errorStream, contentEncoding);
        }
        
        long end = System.currentTimeMillis();
        String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());
        System.out.println("TIme taken Date:"+date+", TimeMillis:"+ (end-start));
        
        System.out.println("Reply: " + xmlRply);
        System.out.println("Request Status:"+ requestStatus);
    }
    public static HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {
            public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
                return true;
            }
        };
    }
    public static SSLContext getCertificateFactoryBasedSSLContext(InputStream clientCertificateStream, String ceritificateAlias) throws CertificateException, NoSuchAlgorithmException,
    KeyStoreException, IOException, KeyManagementException {
        SSLContext sslContext = null;
        BufferedInputStream bufferedInputStream = null;
        try {
            bufferedInputStream = new BufferedInputStream(clientCertificateStream);
        
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(bufferedInputStream);
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            keyStore.setCertificateEntry(ceritificateAlias, x509Certificate);
        
            trustManagerFactory.init(keyStore);
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bufferedInputStream.close();
            clientCertificateStream.close();
        }
        return sslContext;
    }
    public static String getStreamContent(InputStream input, String encoding) throws IOException {
        byte[] httpRply;
        String rply;
        httpRply = IOUtils.toByteArray(input);
        System.out.println("Byte Array:"+httpRply.toString());
        if (encoding == null) {
            rply = new String(httpRply);
        } else if ( encoding.equalsIgnoreCase("GZIP") ) { // https://stackoverflow.com/a/3627442/5081877
            rply = getGZIP(httpRply);
        } else { // "ISO-8859-1", ";TF-8"
            rply = new String(httpRply, encoding);
        }
        return rply;
    }
    @SuppressWarnings("deprecation")
    public static String getGZIP(byte[] zipBytes) {
        try {
            GZIPInputStream gzipInput = new GZIPInputStream( new ByteArrayInputStream(zipBytes) );
            return IOUtils.toString(gzipInput);
        } catch (IOException e) {
            throw new UncheckedIOException("Error while decompression!", e);
        }
    }
    
    @SuppressWarnings("unused")
    public static SOAPMessage WS_Security_signature(String inputFile, boolean isDataXML) throws Exception {
         String 
            WSSE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
            WSU_NS    = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
            DSIG_NS = "http://www.w3.org/2000/09/xmldsig#", // javax.xml.crypto.dsig.XMLSignature.XMLNS, Constants.SignatureSpecNS
            
            binarySecurityToken_Encoding = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary",
            binarySecurityToken_Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
            
            canonicalizationMethodAlog = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS,
            signatureMethodAlog = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256,
            transformAlog = Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS,
            // KeyEncryption Algorithm
            digestMethodAlog  =  "http://www.w3.org/2001/04/xmlenc#sha256", // Constants.ALGO_ID_DIGEST_SHA1, org.apache.ws.security.handler.WSHandlerConstants.SIG_DIGEST_ALGO
            certEncodedID_KeyIdentifier_WsuID = "X509Token", timeStampID = "Timestamp", signedBodyID = "MsgBody";
            
        SOAPMessage soapMsg;
        Document docBody;
        if (isDataXML) {
            System.out.println("Sample DATA xml - Create SOAP Message");
            MessageFactory messageFactory = MessageFactory.newInstance("SOAP 1.1 Protocol");
            SOAPMessage soapMessage = messageFactory.createMessage();
            soapMsg = soapMessage;
            
            InputStream xmlStream = getCerFileStream(isClassPath, inputFile); 
            String xmlContent = getDiskFileStream_Lines(xmlStream);
            
            // <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            xmlContent=xmlContent.replaceAll("\\<\\?xml(.+?)\\?\\>", "").trim();
            xmlContent = "<SendScheduleMessageRequest xmlns=\"http://www.ote-cr.cz/schema/service/etso/schedule-v1\">"
                    +xmlContent
                    +"</SendScheduleMessageRequest>";
            //System.out.println("xmlContent:"+xmlContent);
            docBody = getDocument(xmlContent.trim(), true);
            System.out.println("Data Document: "+docBody.getDocumentElement());
        } else {
            System.out.println("SOAP XML with Envelope");
            
            Document doc = getDocument(inputFile, false); // SOAP MSG removing comment elements
            String docStr = toStringDocument(doc); // https://stackoverflow.com/a/2567443/5081877
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(docStr.getBytes());
            
            MimeHeaders mimeHeaders = new MimeHeaders();
            // SOAPMessage message = MessageFactory.newInstance().createMessage(null, fileInputStream);
            SOAPMessage message = MessageFactory.newInstance("SOAP 1.2 Protocol").createMessage(mimeHeaders, byteArrayInputStream);
            soapMsg = message;
            
            docBody = soapMsg.getSOAPBody().extractContentAsDocument();
            System.out.println("SOAP DATA Document: "+docBody.getDocumentElement());
        }
        // A new SOAPMessage object contains: SOAPPart object SOAPEnvelope object SOAPBody object SOAPHeader object 
        SOAPPart soapPart = soapMsg.getSOAPPart();
        SOAPEnvelope soapEnv = soapPart.getEnvelope();
        SOAPHeader soapHeader = soapEnv.getHeader(); // soapMessage.getSOAPHeader();
        SOAPBody soapBody = soapEnv.getBody(); // soapMessage.getSOAPBody()
        soapBody.addDocument(docBody);
        
        soapEnv.setPrefix("soapenv");
        soapEnv.removeNamespaceDeclaration("SOAP-ENV");
        soapHeader.setPrefix("soapenv");
        soapHeader.removeNamespaceDeclaration("SOAP-ENV");
        soapBody.setPrefix("soapenv");
        soapBody.removeNamespaceDeclaration("SOAP-ENV");
        
        soapMsg.saveChanges();
        // <SendScheduleMessageRequest xmlns="http://www.ote-cr.cz/schema/service/etso/schedule-v1">
        //SOAPElement addChildElement = soapBody.addChildElement("SendScheduleMessageRequest");
        //addChildElement.setAttribute("xmlns", "http://www.ote-cr.cz/schema/service/etso/schedule-v1");
        
        soapBody.addAttribute(soapEnv.createName("Id", "wsu", WSU_NS), signedBodyID);
        if (soapHeader == null) {
            soapHeader = soapEnv.addHeader();
            System.out.println("Provided SOAP XML does not contains any Header part. So creating it.");
        }
        
        // Adding NameSpaces to Envelope
        soapEnv.addNamespaceDeclaration("wsse", WSSE_NS);
        soapEnv.addNamespaceDeclaration("wsu", WSU_NS);
        soapEnv.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema");
        soapEnv.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance");
        
        // <wsse:Security> element adding to Header Part
        SOAPElement securityElement = soapHeader.addChildElement("Security", "wsse", WSSE_NS);
        //securityElement.addNamespaceDeclaration("wsu", WSU_NS);
        
        // (ii) Add Binary Security Token.
        // <wsse:BinarySecurityToken EncodingType="...#Base64Binary" ValueType="...#X509v3" wsu:Id="X509Token">The base64 encoded value of the ROS digital certificate.</wsse:BinarySecurityToken>
        SOAPElement binarySecurityToken = securityElement.addChildElement("BinarySecurityToken", "wsse");
        binarySecurityToken.setAttribute("ValueType", binarySecurityToken_Value);
        binarySecurityToken.setAttribute("EncodingType", binarySecurityToken_Encoding);
        binarySecurityToken.setAttribute("wsu:Id", certEncodedID_KeyIdentifier_WsuID);
            byte[] certByte = loadPublicKeyX509.getEncoded();
            String encodeToString = Base64.getEncoder().encodeToString(certByte);
        binarySecurityToken.addTextNode(encodeToString);
        
        //(iii) Add TimeStamp element - <wsu:Timestamp wsu:Id="TS">
        SOAPElement timestamp = securityElement.addChildElement("Timestamp", "wsu");
        timestamp.addAttribute(soapEnv.createName("Id", "wsu", WSU_NS), timeStampID);
            String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSX";
            DateTimeFormatter timeStampFormatter = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
        timestamp.addChildElement("Created", "wsu").setValue(timeStampFormatter.format(ZonedDateTime.now().toInstant().atZone(ZoneId.of("UTC"))));
        timestamp.addChildElement("Expires", "wsu").setValue(timeStampFormatter.format(ZonedDateTime.now().plusSeconds(liveTimeInSeconds).toInstant().atZone(ZoneId.of("UTC"))));

        // (iv) Add signature element
        // <wsse:Security> <ds:Signature> <ds:KeyInfo> <wsse:SecurityTokenReference>
        SOAPElement securityTokenReference = securityElement.addChildElement("SecurityTokenReference", "wsse");
        SOAPElement reference = securityTokenReference.addChildElement("Reference", "wsse");
        reference.setAttribute("URI", "#"+certEncodedID_KeyIdentifier_WsuID); // <wsse:BinarySecurityToken wsu:Id="X509Token"
        
        // <ds:SignedInfo>
        String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());

        //Digest method - <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        javax.xml.crypto.dsig.DigestMethod digestMethod = xmlSignatureFactory.newDigestMethod(digestMethodAlog, null);
        
        ArrayList<Transform> transformList = new ArrayList<Transform>();
        //Transform - <ds:Reference URI="#Body">
        Transform envTransform = xmlSignatureFactory.newTransform(transformAlog, (TransformParameterSpec) null);
        transformList.add(envTransform);
            //References <ds:Reference URI="#Body">
            ArrayList<Reference> refList = new ArrayList<Reference>();
                Reference refTS   = xmlSignatureFactory.newReference("#"+timeStampID,  digestMethod, transformList, null, null);
                Reference refBody = xmlSignatureFactory.newReference("#"+signedBodyID, digestMethod, transformList, null, null);
            refList.add(refBody);
            refList.add(refTS);

        javax.xml.crypto.dsig.CanonicalizationMethod cm = xmlSignatureFactory.newCanonicalizationMethod(canonicalizationMethodAlog, (C14NMethodParameterSpec) null);

        javax.xml.crypto.dsig.SignatureMethod sm = xmlSignatureFactory.newSignatureMethod(signatureMethodAlog, null);
        SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(cm, sm, refList);

        DOMSignContext signContext = new DOMSignContext(privateKey, securityElement);
        signContext.setDefaultNamespacePrefix("ds");
        signContext.putNamespacePrefix(DSIG_NS, "ds");
        signContext.putNamespacePrefix(WSU_NS, "wsu");

        signContext.setIdAttributeNS(soapBody, WSU_NS, "Id");
        signContext.setIdAttributeNS(timestamp, WSU_NS, "Id");

        KeyInfoFactory keyFactory = KeyInfoFactory.getInstance();
        DOMStructure domKeyInfo = new DOMStructure(securityTokenReference);
        javax.xml.crypto.dsig.keyinfo.KeyInfo keyInfo = keyFactory.newKeyInfo(java.util.Collections.singletonList(domKeyInfo));
        javax.xml.crypto.dsig.XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);
        //signContext.setBaseURI("");

        signature.sign(signContext);
        return soapMsg;
    }
    


    public static void addBCProvider() {
        // java.security.NoSuchProviderException: no such provider: BC
        if (Security.getProvider(org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) == null) {
            //System.out.println("JVM Installing BouncyCastle Security Providers to the Runtime");
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        } else {
            //System.out.println("JVM Installed with BouncyCastle Security Providers");
        }
    }
    public static X509Certificate loadPublicKeyX509(InputStream cerFileStream) throws CertificateException, NoSuchProviderException {
        CertificateFactory    certificateFactory = CertificateFactory.getInstance("X.509", "BC");
        X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(cerFileStream);
        return x509Certificate;
    }
    public static PrivateKey loadPrivateKeyforSigning(InputStream cerFileStream, String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchProviderException {
        KeyStore keyStore = KeyStore.getInstance("PKCS12"); //, "BC");
        keyStore.load(cerFileStream, password.toCharArray());
        
        Enumeration<String> keyStoreAliasEnum = keyStore.aliases();
        PrivateKey privateKey = null;
        String alias = null;
        while ( keyStoreAliasEnum.hasMoreElements() ) {
            alias = keyStoreAliasEnum.nextElement();
            if (password != null) {
                System.out.println("alias:"+alias);
                privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
                
                X509Certificate x509Certificate = (X509Certificate) keyStore.getCertificate(alias);
                PublicKey publicKey = x509Certificate.getPublicKey();
                System.out.println("loadPublicKey : "+ publicKey);
                System.out.println("privateKey : "+privateKey);
                
                //loadPublicKeyX509 = x509Certificate;
            }
        }
        return privateKey;
    }
    public static InputStream getCerFileStream(boolean isClassPath, String fileName) throws FileNotFoundException {
        InputStream stream = null;
        if (isClassPath) {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            stream = classLoader.getResourceAsStream(fileName);
        } else {
            stream = new FileInputStream(fileName);
        }
        return stream;
    }
    public static String getDiskFileStream_Lines( InputStream fileStream ) throws IOException {
        StringBuffer text = new StringBuffer();
        BufferedReader br = new BufferedReader( new java.io.InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }
    public static Document getDocument(String xmlData, boolean isXMLData) throws Exception {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        dbFactory.setNamespaceAware(true);
        dbFactory.setIgnoringComments(true);
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc;
        if (isXMLData) {
            InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
            doc = dBuilder.parse(ips);
        } else {
            doc = dBuilder.parse( new File(xmlData) );
        }
        return doc;
    }

    public static String getSoapMessages(SOAPMessage soapMessage) throws Exception {
        SOAPEnvelope soapEnv = soapMessage.getSOAPPart().getEnvelope();
        Document ownerDocument = soapEnv.getOwnerDocument();
        String stringDocument = toStringDocument(ownerDocument);
        //System.out.println("SoapMessage: "+stringDocument);
        return stringDocument;
    }
    public static String toStringDocument(Document doc) throws TransformerException {
        StringWriter sw = new StringWriter();
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

        transformer.transform(new DOMSource(doc), new StreamResult(sw));
        return sw.toString();
    }
    public static String getSoapMessageFromStream(SOAPMessage soapMessage) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        soapMessage.writeTo(outputStream);
        String codepage = "UTF-8";
        String stringDocument = new String( outputStream.toByteArray(), codepage );
        //System.out.println("SoapMessage form Stram: "+stringDocument);
        return stringDocument;
    }
}
⚠️ **GitHub.com Fallback** ⚠️