Forum Discussion

wildview's avatar
wildview
Senior Member
7 years ago

WS-Security SOAP signing error - Help!

Hi, I'm completely new to using the WS-Security methods to sign an xml payload and need some help to understand why my SOAP signing code is throwing an exception error when trying to addReferencesToSign. I need to sign an xml document using a BinarySecurityToken type. There is something that I’m just not configuring correctly w/ the WSSecSignature method, the raw xml template or something else. Can someone please help me by looking at the code below to see what is missing or out of sequence?

 

Exception error on the addReferencesToSign method:

The sign.addReferencesToSign(signParts,secHeader) is throwing Error::signSoapMessage - No message with ID "noXMLSig" found in resource bundle "org/apache/xml/security/resource/xmlsecurity". Original Exception was a org.apache.wss4j.common.ext.WSSecurityException and message No message with ID "noEncElement" found in resource bundle "org/apache/xml/security/resource/xmlsecurity"


The Raw xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">>
    </wsse:Security>
  </Header>
  <soapenv:Body> 
    <OrganizationIdentification>Id</OrganizationIdentification>
  </soapenv:Body> 
</soapenv:Envelope>


Signing code:

import java.io.*;

// SOAP keystore imports
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.security.cert.Certificate

// SOAP xml document imports
import javax.xml.parsers.DocumentBuilder;
import org.apache.commons.io.IOUtils;
import org.apache.xml.security.Init;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.transforms.Transforms;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.ElementProxy;
import org.xml.sax.InputSource
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilderFactory;

// SOAP signing imports
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.crypto.Merlin;
import org.apache.wss4j.common.WSEncryptionPart
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.engine.WSSConfig
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.dom.message.WSSecHeader;
import org.apache.wss4j.dom.message.WSSecSignature;
import org.apache.wss4j.dom.message.WSSecTimestamp;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.dom.message.WSSecUsernameToken;

public ByteArrayOutputStream signSoapMessage(String xmlFile, File privateKeyFile) throws WSSecurityException {

    final int signatureValidityTime = 3600; // 1hour in seconds

    try {
        //WSSConfig config = new WSSConfig();
        //config.setWsiBSPCompliant(false);

        // Open keystore and create signingCert
        KeyStore keyStore = loadKeyStore(privateKeyFile);
        Key privateKey = keyStore.getKey(PRIVATE_KEY_ALIAS, PRIVATE_KEY_PASS.toCharArray());
        final X509Certificate signingCert = (X509Certificate)keyStore.getCertificate(PRIVATE_KEY_ALIAS);
        Certificate[] lChain = new Certificate[1];
        lChain[0]= signingCert;
        keyStore.setKeyEntry(PRIVATE_KEY_ALIAS, privateKey, KEY_STORE_PASS.toCharArray(), lChain);

        // Load XML message into document and build header
        Document document= xmlToDoc(xmlFile);
        WSSecHeader secHeader = new WSSecHeader(document);
        secHeader.setMustUnderstand(true);
        secHeader.insertSecurityHeader();

        // Setup timeStamp token to add
        WSSecTimestamp secTimeStamp = new WSSecTimestamp();
        secTimeStamp.setTimeToLive(signatureValidityTime);
        secTimeStamp.prepare(document);
        //secTimeStamp.prependToHeader(secHeader);

        // Setup userName token to add
        WSSecUsernameToken secUsernameToken = new WSSecUsernameToken();
        secUsernameToken.setPasswordType(WSConstants.PASSWORD_TEXT);
        secUsernameToken.setUserInfo(USER_INFO_NAME, USER_INFO_PWD);
        secUsernameToken.addNonce();
        secUsernameToken.addCreated();
        secUsernameToken.prepare(document);

        // Setup signature to sign document
        WSSecSignature sign = new WSSecSignature();
        String bstId = sign.getBSTTokenId();
        sign.appendBSTElementToHeader(secHeader);
        sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
        sign.setX509Certificate(signingCert);
        sign.setUserInfo(PRIVATE_KEY_ALIAS, new String(KEY_STORE_PASS.toCharArray()));
        sign.setUseSingleCertificate(true);
        sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
        sign.setDigestAlgo("http://www.w3.org/2000/09/xmldsig#sha1");
        sign.setSigCanonicalization(WSConstants.C14N_EXCL_OMIT_COMMENTS);

        // Add crypto properties to document
        Properties cxfProps = new Properties();
        cxfProps.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
        Crypto crypto = CryptoFactory.getInstance(cxfProps);
        ((Merlin) crypto).setKeyStore(keyStore);
        crypto.loadCertificate(new ByteArrayInputStream(signingCert.getEncoded()));
        sign.prepare(document, crypto, secHeader);

        // Add signing references to header
        List<WSEncryptionPart> signParts = new ArrayList<WSEncryptionPart>();
        signParts.add(new WSEncryptionPart(WSConstants.ELEM_BODY,WSConstants.URI_SOAP12_ENV, ""));
        signParts.add(new WSEncryptionPart(bstId));
        signParts.add(new WSEncryptionPart(secTimeStamp.getId(), WSConstants.WSU_NS, ""));

        // *** Throws exception on addReferencesToSign method below
        sign.addReferencesToSign(signParts,secHeader);
        List<Reference> referenceList = sign.addReferencesToSign(signParts,
                secHeader);
        sign.computeSignature(referenceList, false, null);
        document= sign.build(document, crypto, secHeader);

        // Write signed document to output stream
        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        outputStream.write(Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(document));

        //String result=DOM2Writer.nodeToString(signedDoc);

        // return signed payload
        return outputStream;

    } catch (Exception e) {
        dPrintln("Error::signSoapMessage - " + e.message);
        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE,e);
    }
}

Thanks in advance,
Rob

2 Replies

  • nmrao's avatar
    nmrao
    Champion Level 3
    What version are you using?
    This may not be the right forum.
    • Maheshreddy's avatar
      Maheshreddy
      New Contributor
      Hi,

      Can you help me.. we are also facing the same issue..
      The sign.addReferencesToSign(signParts,secHeader) is throwing Error::signSoapMessage - No message with ID "noXMLSig" found in resource bundle "org/apache/xml/security/resource/xmlsecurity".

      Attached my java code.. using wss4j 2.0 version. Please share the working example for the same for any version. We are in vritical time.