SignPartialMessageProcessor.java

/*
 * AdroitLogic UltraESB Enterprise Service Bus
 *
 * Copyright (c) 2010-2012 AdroitLogic Private Ltd. (http://adroitlogic.org). All Rights Reserved.
 *
 * GNU Affero General Public License Usage
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
 * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program (See LICENSE-AGPL.TXT).
 * If not, see http://www.gnu.org/licenses/agpl-3.0.html
 *
 * Commercial Usage
 *
 * Licensees holding valid UltraESB Commercial licenses may use this file in accordance with the UltraESB Commercial
 * License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written
 * agreement between you and AdroitLogic.
 *
 * If you are unsure which license is appropriate for your use, or have questions regarding the use of this file,
 * please contact AdroitLogic at info@adroitlogic.com
 */
/*
 * Modificato da Link.it (https://link.it) per supportare le seguenti funzionalità:
 * - firma e cifratura degli attachments
 * - cifratura con chiave simmetrica
 * - supporto CRL 
 * 
 * Copyright (c) 2011-2024 Link.it srl (https://link.it). 
 * 
 */
package org.openspcoop2.security.message.soapbox;

import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.SOAPElement;

import org.adroitlogic.soapbox.CryptoUtil;
import org.adroitlogic.soapbox.InvalidMessageDataException;
import org.adroitlogic.soapbox.MessageSecurityContext;
import org.adroitlogic.soapbox.Processor;
import org.adroitlogic.soapbox.SBConstants;
import org.adroitlogic.soapbox.SecurityConfig;
import org.adroitlogic.soapbox.SecurityFailureException;
import org.adroitlogic.soapbox.SignatureRequest;
import org.apache.wss4j.common.WSS4JConstants;
import org.openspcoop2.message.OpenSPCoop2SoapMessage;
import org.openspcoop2.message.xml.MessageXMLUtils;
import org.openspcoop2.security.message.constants.WSSAttachmentsConstants;
import org.openspcoop2.utils.xml.AbstractXMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
 * SignPartialMessageProcessor
 *
 * Author of the original AdroitLogic code:
 * @author asankha
 *
 * Authors of the Link.it modification to the code:
 * @author Andrea Poli (apoli@link.it)
 * @author Giovanni Bussu (bussu@link.it)
 * @author $Author$
 * @version $Rev$, $Date$
 */
public class SignPartialMessageProcessor implements Processor {

	public static final QName TIMESTAMP = new QName(SBConstants.WSU, "Timestamp");
	
	protected List<QName> signQNames;
    protected List<Boolean> elementsSignatureContent;
    protected List<AttachmentPart> signAttachments;
    protected OpenSPCoop2SoapMessage message;
	public void setMessage(OpenSPCoop2SoapMessage message) {
		this.message = message;
	}
	protected String actor;
	protected boolean mustUnderstand;
	public void setActor(String actor) {
		this.actor = actor;
	}
	public void setMustUnderstand(boolean mustUnderstand) {
		this.mustUnderstand = mustUnderstand;
	}
    
	public SignPartialMessageProcessor() {
		this.signQNames = new ArrayList<QName>();
		this.signAttachments = new ArrayList<AttachmentPart>();
		this.elementsSignatureContent = new ArrayList<Boolean>();
	}
	
	public void addElementToSign(QName element , boolean content) {
		this.signQNames.add(element);
		this.elementsSignatureContent.add(content);
	}
	
	public void addAttachmentsToSign(AttachmentPart part , boolean content) {
		this.signAttachments.add(part);
	}
	
    @Override
	public void process(SecurityConfig secConfig, MessageSecurityContext msgSecCtx) {

    	AbstractXMLUtils xmlUtils = MessageXMLUtils.getInstance(this.message.getFactory());
    	
        SignatureRequest signReq = msgSecCtx.getSignatureRequest();

       // System.out.println("SIGN XMLSEC["+this.useXMLSec+"]");
        
        
        // *** ensure existence of the wsse:Security header, and create one if none exists ***
        Element wsseSecurityElem = null;
        try{
        	wsseSecurityElem = WSSUtils.getWSSecurityHeader(msgSecCtx.getDocument(), this.actor, this.mustUnderstand);
        }catch(Exception e){
			throw new SecurityFailureException(e.getMessage(), e);
		}
        
        
        
        
        // *** we will not sign an already signed document ***
        if (CryptoUtil.getFirstChildOrNull(wsseSecurityElem, SBConstants.DS, "Signature") != null) {
            throw new InvalidMessageDataException("Message is already signed");
        }

        
        
    
        // **** grab certificate used to sign, and find out the algorithm to be used ****
        X509Certificate[] certs = secConfig.getCertificatesByAlias(signReq.getCertAlias());
        String sigAlgoURI = signReq.getSignatureAlgoURI();
        if (sigAlgoURI == null) {
            if ("DSA".equalsIgnoreCase(certs[0].getPublicKey().getAlgorithm())) {
            	sigAlgoURI = org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_DSA;
            } else if ("RSA".equalsIgnoreCase(certs[0].getPublicKey().getAlgorithm())) {
            	sigAlgoURI = org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA;
            } else {
                throw new SecurityFailureException("Signature algorithm not specified, and cannot be auto detected");
            }
        }

        
        
        
        // **** create XMLSignature engine ****
        // NOTA:
        // Vi sono fondamentalmente due versioni di XMLSignature con classi correlate.
        // - com.sun.org.apache.xml.internal.security.signature: presente nel runtime di java
        // - org.apache.xml.security.signature: presente in xmlsec-2.1.7.jar
        //
        // A seconda della versione utilizzata devono essere implementate delle classi a corredo:
        // - com.sun.org.apache.xml.internal.security.transforms.TransformSpi implementato tramite org.openspcoop2.security.message.signature.SunAttachmentContentTransform
        // - org.apache.xml.security.transforms.TransformSpi implementato tramite org.openspcoop2.security.message.signature.XMLSecAttachmentContentTransform
        // NOTA: L'implementazione del Transformer tramite le classi della Sun cosi come realizzate usano metodi diversi presenti su Java 1.6 patch 26 o maggiore rispetto a Java 7.
        //		 Java 1.7 ha modificato i metodi della classe astratta com.sun.org.apache.xml.internal.security.transforms.TransformSpi
        //	     Il codice seguente e' stato scritto per poter effettuare i test incrociati sulle due versioni adeguando le classi utilizzate rispetto ad una variabile cablata nel codice
        //		 definita in org.openspcoop2.security.message.soapbox.MessageSecurityContext_soapbox.USE_XMLSEC_IMPL
        // 
        // A seconda della versione utilizzata devono inoltre essere implementate le classe di risoluzione delle signature reference
        // - com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi implementata tramite org.openspcoop2.security.message.signature.SunEnvelopeIdResolver
        // - org.apache.xml.security.utils.resolver.ResourceResolverSpi implementata tramite org.openspcoop2.security.message.signature.XMLSecEnvelopeIdResolver
        
        // NOTA: Tutto il discorso sopra e' terminato con java 11
        
        Document doc = msgSecCtx.getDocument();
        Element env = doc.getDocumentElement();
        org.apache.xml.security.signature.XMLSignature sigXMLSec = null;
        if (org.apache.xml.security.c14n.Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS.equals(signReq.getC14nAlgoURI())) {
            Element canonicalizationMethodElem = doc.createElementNS(SBConstants.DS, "ds:CanonicalizationMethod");
            canonicalizationMethodElem.setAttribute("Algorithm", signReq.getC14nAlgoURI());
              
            try {
            	org.apache.xml.security.algorithms.SignatureAlgorithm signatureAlgorithm = new org.apache.xml.security.algorithms.SignatureAlgorithm(doc, sigAlgoURI);
            	sigXMLSec = new org.apache.xml.security.signature.XMLSignature(doc, null, signatureAlgorithm.getElement(), canonicalizationMethodElem);
            	sigXMLSec.setId(SignPartialMessageProcessor.getSignId());
            } catch (Exception e) {
                throw new SecurityFailureException("Error signing document with credentials of alias : " +
                    signReq.getCertAlias() + " using algorithm : " + sigAlgoURI +
                    " and c14n with : " + signReq.getC14nAlgoURI(), e);
            }

        } else {
            try {
            	sigXMLSec = new org.apache.xml.security.signature.XMLSignature(doc, null, sigAlgoURI, signReq.getC14nAlgoURI());
            	sigXMLSec.setId(SignPartialMessageProcessor.getSignId());
            } catch (Exception e) {
                throw new SecurityFailureException("Error signing document with credentials of alias : " +
                    signReq.getCertAlias() + " using algorithm : " + sigAlgoURI +
                    " and c14n with : " + signReq.getC14nAlgoURI(), e);
            }
        }

        
        
        
        
        
        // ** Definizione degli elementi da firmare **
        // by default the elements to sign are the body and timestamp
        if(this.signQNames.isEmpty() && this.signAttachments.isEmpty()) {
        	this.signQNames.add(new QName(env.getNamespaceURI(), "Body"));
        	this.elementsSignatureContent.add(false);
        	this.signQNames.add(SignPartialMessageProcessor.TIMESTAMP);
        	this.elementsSignatureContent.add(false);
        }
        
        List<Element> signElements = new ArrayList<Element>();
        List<Boolean> signTypeElements = new ArrayList<Boolean>();
        for (int i = 0; i < this.signQNames.size(); i++) {
        	QName name = this.signQNames.get(i);
        	signElements.add(CryptoUtil.getFirstChild(env, name.getNamespaceURI(), name.getLocalPart()));
        	signTypeElements.add(this.elementsSignatureContent.get(i));
		}
        
        
        // ** Firma degli elementi indicati presenti nella SOAP Envelope **
        signElements(signElements,signTypeElements, signReq, sigXMLSec);
        
        
        // ** Firma degli attachments indicati **
        sigXMLSec.addResourceResolver(org.openspcoop2.security.message.signature.XMLSecEnvelopeIdResolver.getInstance(this.message));
        signAttachments(xmlUtils, this.signAttachments, signReq, sigXMLSec, doc);
        
        
        
        // ** Creazione del SignatureHeaderBlock e firma **
        // NOTA:
        // La creazione del SignatureHeaderBlock puo' essere gestita tramite una utility fornita dalla SunJava: com.sun.xml.wss.core.SignatureHeaderBlock
        // tale classe richiede pero' l'utilizzo proprio della XMLSignature Engine della Sun.
        // Altrimenti e' possibile agire direttamente tramite XMLSignature Engine in entrambe le soluzioni.
        // Di seguito il boolean useSignatureHeaderBlock cablato nel codice serve proprio a switchare tra le due soluzioni
        
        Element signatureElem = null;
	       
    	try {
    		    	
    		signatureElem = convertToSoapElement(sigXMLSec);
    		
    		if (signReq.isWsiBPCompliant()) {
    			HashSet<String> prefixes = new HashSet<String>();
    			prefixes.addAll(getInclusivePrefixes(signatureElem, false));
        		Element canonicalizationMethodElem = (Element) signatureElem.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "CanonicalizationMethod").item(0);
        		org.apache.xml.security.transforms.params.InclusiveNamespaces inclusiveNamespaces = 
         			   new  org.apache.xml.security.transforms.params.InclusiveNamespaces(doc, prefixes);
         	   	canonicalizationMethodElem.appendChild(inclusiveNamespaces.getElement());
    		}
    		
    		sigXMLSec.sign(secConfig.getPrivateKeyByAlias(signReq.getCertAlias()));
    		signatureElem = convertToSoapElement(sigXMLSec);
        	
    	 } catch (Exception e) {
            throw new SecurityFailureException("Error signing document using alias : " + signReq.getCertAlias(), e);
        }
        
        
        
        // *** create and attach the keyinfo element ***
        addKeyInfo(signatureElem, doc, signReq, msgSecCtx, secConfig, wsseSecurityElem);

    }
    
    
    
    protected void addKeyInfo(Element signatureElem,Document doc,SignatureRequest signReq,MessageSecurityContext msgSecCtx,
    		SecurityConfig secConfig,Element wsseSecurityElem){
    	// //OLDMETHODCHENONGESTIVA ISSUER: signatureElem.appendChild(CryptoUtil.createKeyInfoElement(doc, signReq, msgSecCtx, secConfig));
        signatureElem.appendChild(WSSUtils.createKeyInfoElement(doc, signReq, msgSecCtx, secConfig));
        Element firstChild = CryptoUtil.getFirstElementChild(wsseSecurityElem);
        if (firstChild != null) {
            wsseSecurityElem.insertBefore(signatureElem, firstChild);
        } else {
            wsseSecurityElem.appendChild(signatureElem);
        }

        NodeList nl = wsseSecurityElem.getElementsByTagNameNS(SBConstants.WSSE, "BinarySecurityToken");
        for (int i=0; i<nl.getLength(); i++) {
            wsseSecurityElem.insertBefore(nl.item(i), signatureElem);
        }
    }
    

    
    private Element convertToSoapElement(org.apache.xml.security.utils.ElementProxy proxy) {
        org.w3c.dom.Element elem = proxy.getElement();
        if(elem instanceof SOAPElement)
            return elem;
        return (Element) proxy.getDocument().importNode(elem, true);
    }

    
    
    /**
     * Get the List of inclusive prefixes from the DOM Element argument 
     */
    public List<String> getInclusivePrefixes(Element target, boolean excludeVisible) {
        List<String> result = new ArrayList<>();
        Node parent = target;
        while (parent.getParentNode() != null &&
            !(Node.DOCUMENT_NODE == parent.getParentNode().getNodeType())) {
            parent = parent.getParentNode();
            NamedNodeMap attributes = parent.getAttributes();
            for (int i = 0; i < attributes.getLength(); i++) {
                Node attribute = attributes.item(i);
                if (WSS4JConstants.XMLNS_NS.equals(attribute.getNamespaceURI())) {
                    if ("xmlns".equals(attribute.getNodeName())) {
                        //System.out.println("FOUND #default per "+parent.getLocalName());
                    	result.add("#default");
                    } else {
                    	//System.out.println("FOUND "+attribute.getLocalName()+" per "+parent.getLocalName());
                        result.add(attribute.getLocalName());
                    }
                }
            }
        }

        //System.out.println("SIZE PRIMA EXCLUDE: "+result.size());
        
        if (excludeVisible == true) {
            NamedNodeMap attributes = target.getAttributes();
            for (int i = 0; i < attributes.getLength(); i++) {
                Node attribute = attributes.item(i);
                if (WSS4JConstants.XMLNS_NS.equals(attribute.getNamespaceURI())) {
                    if ("xmlns".equals(attribute.getNodeName())) {
                    	//System.out.println("REMOVE #default per "+target.getLocalName());
                    	result.remove("#default");
                    } else {
                    	//System.out.println("REMOVE "+attribute.getLocalName()+" per "+target.getLocalName());
                    	result.remove(attribute.getLocalName());
                    }
                }
                if (attribute.getPrefix() != null) {
                	//System.out.println("REMOVE PREFIX "+attribute.getPrefix()+" per "+target.getLocalName());
                	result.remove(attribute.getPrefix());
                }
            }

            if (target.getPrefix() == null) {
            	//System.out.println("REMOVE TARGET #default per "+target.getLocalName());
            	result.remove("#default");
            } else {
            	//System.out.println("REMOVE TARGET PREFIX "+target.getPrefix()+" per "+target.getLocalName());
            	result.remove(target.getPrefix());
            }
        }

        //System.out.println("SIZE FINALE: "+result.size());
        
        return result;
    }
    
//    protected void signAttachments(List<AttachmentPart> part, SignatureRequest signReq, SignatureHeaderBlock signatureHeaderBlock) throws Exception {
    protected void signAttachments(AbstractXMLUtils xmlUtils,
    		List<AttachmentPart> part, SignatureRequest signReq,
    		org.apache.xml.security.signature.XMLSignature sigXMLSec,
    		Document d) {
		
    	try {
    		// Specifica in Web Services Security SOAP Messages With Attachments (Swa) Profile 1.1
    		// 5.4.4 Processing Rules for Attachment Signing
    		// The processing rule for signing is modified based on the SOAP Message Security rules
    		// After determining which attachments are to be included as references in a signature, create a
    		// <ds:Signature> element in a <wsse:Security> header block targeted at the recipient, including a
    		// <ds:Reference> for each attachment to be protected by the signature. Additional <ds:Reference>
    		// elements may refer to content in the SOAP envelope to be included in the signature.
    		
    		// 1. MIME Part Canonicalize the content of the attachment, as appropriate to the MIME type of the part, as
        	// outlined in section 4.4.2 Attachments of an XML content type require Exclusive XML Canonicalization
        	// without comments[Excl-Canon].
    		
    		// 2. If MIME headers are to be included in the signature, perform MIME header canonicalization as
    		// outlined in section 4.4.1.
    		
        	//3. Determine the CID scheme URL to be used to reference the part and set the <ds:Reference> URL
    		// attribute value to this URL.
    		
    		// 4. Include a <ds:Transforms> element in the <ds:Reference>. This <ds:Transforms> element MUST
        	// include a <ds:Transform> element with the Algorithm attribute having the full URL value specified
        	// earlier in this profile – corresponding to either the Attachment-Complete-Signature-Transform or
        	// Attachment-Content-Signature-Transform, depending on what is to be included in the hash calculation.
        	// This MUST be the first transform listed. The <ds:Transform> element MUST NOT contain any
        	// transform for a MIME transfer encoding purpose (e.g. base64 encoding) since transfer encoding is left
        	// to the MIME layer as noted in section 2. This does not preclude the use of XML Transforms, including a
        	// base64 transform, for other purposes.
    		
        	// 5. Extract the appropriate portion of the MIME part consistent with the selected transform.
        	
        	// 6. Create the <ds:Reference> hash value as outlined in the W3C XML Digital Signature	Recommendation.
    		
    		// For each attachment Reference, perform the following steps:
    		if(this.signAttachments==null || this.signAttachments.size()<=0){
    			return;
    		}
	        for(AttachmentPart p : this.signAttachments){ 
	        	
	        	String uri = p.getContentId();
        		if (uri != null) {                
					if(uri.startsWith("<")){
						uri = "cid:" + uri.substring(1, uri.length()-1);
					}else{
						uri = "cid:" + uri;
					}
				} else {
					uri = p.getContentLocation();
				}
        		
        		//Document d = this.message.getSOAPHeader().getOwnerDocument();
        		
    			org.apache.xml.security.transforms.Transforms transforms = 
        				new org.apache.xml.security.transforms.Transforms(d);
        		transforms.addTransform(WSSAttachmentsConstants.ATTACHMENT_CONTENT_SIGNATURE_TRANSFORM_URI);
        		
        		String contentType = p.getContentType();
        		if("text/xml".equals(contentType)){
        			//transforms.addTransform(com.sun.org.apache.xml.internal.security.transforms.Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
        			if (signReq.isWsiBPCompliant()) {
        				byte[]raw = p.getRawContentBytes();
        				Element signElement = xmlUtils.newElement(raw);
        				transforms.item(0).getElement().appendChild(new org.apache.xml.security.transforms.params.InclusiveNamespaces(
        						d, CryptoUtil.getInclusivePrefixes(signElement, true)).getElement());
        			}
        		}
        		/*else{
        			transforms.addTransform(com.sun.org.apache.xml.internal.security.transforms.Transforms.TRANSFORM_BASE64_DECODE);
        		}*/
    			
    			sigXMLSec.addDocument(uri, transforms, signReq.getDigestAlgoURI());
        		
	        	//signatureHeaderBlock.addSignedInfoReference(uri, transforms, signReq.getDigestAlgoURI());
	        	
//	        	byte[]raw = p.getRawContentBytes();
//	        	String contentType = p.getContentType();
//	        	com.sun.org.apache.xml.internal.security.transforms.Transforms transforms = 
//        				new com.sun.org.apache.xml.internal.security.transforms.Transforms(d);
//	        	
//	        	// 1. MIME Part Canonicalize the content of the attachment, as appropriate to the MIME type of the part, as
//	        	// outlined in section 4.4.2 Attachments of an XML content type require Exclusive XML Canonicalization
//	        	// without comments[Excl-Canon].
//	        	if("text/xml".equals(contentType)){
//	        		Element signElement = this.xmlUtils.newElement(raw);
//	        		transforms.addTransform(com.sun.org.apache.xml.internal.security.transforms.Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
//	        		if (signReq.isWsiBPCompliant()) {
//	        			transforms.item(0).getElement().appendChild(new InclusiveNamespaces(
//	        					signElement.getOwnerDocument(), CryptoUtil.getInclusivePrefixes(signElement, true)).getElement());
//	        		}
//	        	}
//	        	else{
//	        		Canonicalizer canonicalizer = CanonicalizerFactory.getCanonicalizer(contentType);
//	        		byte[] canonicalize = canonicalizer.canonicalize(raw);
//	        		transforms = 
//	        				new com.sun.org.apache.xml.internal.security.transforms.Transforms(d);
//	        		transforms.addTransform(com.sun.org.apache.xml.internal.security.transforms.Transforms.TRANSFORM_BASE64_DECODE);
//	        		transforms.addBase64Text(Base64.encode(canonicalize));
//	        	}
//	        	
//        		// 2. If MIME headers are to be included in the signature, perform MIME header canonicalization as
//        		// outlined in section 4.4.1.
//        		// TODO
//	        	
//	        	//3. Determine the CID scheme URL to be used to reference the part and set the <ds:Reference> URL
//        		//attribute value to this URL.
//	        	String uri = p.getContentId();
//        		if (uri != null) {                
//					uri = "cid:" + uri.substring(1, uri.length()-1);
//				} else {
//					uri = p.getContentLocation();
//				}
//	        
//	        	// 4. Include a <ds:Transforms> element in the <ds:Reference>. This <ds:Transforms> element MUST
//	        	// include a <ds:Transform> element with the Algorithm attribute having the full URL value specified
//	        	// earlier in this profile – corresponding to either the Attachment-Complete-Signature-Transform or
//	        	// Attachment-Content-Signature-Transform, depending on what is to be included in the hash calculation.
//	        	// This MUST be the first transform listed. The <ds:Transform> element MUST NOT contain any
//	        	// transform for a MIME transfer encoding purpose (e.g. base64 encoding) since transfer encoding is left
//	        	// to the MIME layer as noted in section 2. This does not preclude the use of XML Transforms, including a
//	        	// base64 transform, for other purposes.
//        		
//	        	// 5. Extract the appropriate portion of the MIME part consistent with the selected transform.
//	        	
//	        	// 6. Create the <ds:Reference> hash value as outlined in the W3C XML Digital Signature	Recommendation.
//	        	
//        		signatureHeaderBlock.addSignedInfoReference(uri, transforms, signReq.getDigestAlgoURI());
	        	
	        }
        } catch(Exception e) {
        	throw new SecurityFailureException("Error signing attachments", e);
        }
    	

    }
    
    private void signElements(List<Element> signList,List<Boolean> signTypeList, SignatureRequest signReq, 
    		org.apache.xml.security.signature.XMLSignature sigXMLSec) {    
    //OLDMETHOD: private void signElements(List<Element> signList,List<Boolean> signTypeList, SignatureRequest signReq, XMLSignature sig) {
      
		for (int i = 0; i < signList.size(); i++) {
			
			Element signElement = signList.get(i);
			@SuppressWarnings("unused")
			Boolean content = signTypeList.get(i);

            String signId = null;
            try {
                signId = signElement.getAttributeNS(SBConstants.WSU, "Id");
                if (signId == null || signId.length() == 0) {
                    signId = signElement.getAttribute("Id");
                }
                if (signId == null || signId.length() == 0) {
                    signId = SignPartialMessageProcessor.getSignId();
                    //signElement.setAttributeNS(SBConstants.WSU, "wsu:Id", signId);
                    CryptoUtil.setWsuId(signElement,  signId);
                } 

            	 org.apache.xml.security.transforms.Transforms transforms = new org.apache.xml.security.transforms.Transforms(signElement.getOwnerDocument());
                 transforms.addTransform(org.apache.xml.security.transforms.Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
                 //OLDMETHOD: Transforms transforms = new Transforms(signElement.getOwnerDocument());
              	//OLDMETHOD: transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
                 if (signReq.isWsiBPCompliant()) {

                 	transforms.item(0).getElement().appendChild(new org.apache.xml.security.transforms.params.InclusiveNamespaces(
                         signElement.getOwnerDocument(), CryptoUtil.getInclusivePrefixes(signElement, true)).getElement());
                 	
                 }
                 sigXMLSec.addDocument("#" + signId, transforms, signReq.getDigestAlgoURI());

            } catch (Exception e) {
                throw new SecurityFailureException("Error processing signature for element : {" +
                    signElement.getNamespaceURI() + "}" + signElement.getLocalName() + " with Id : " + signId, e);
            }
        }
    }
    
	
	public static String getSignId(){
		//return CryptoUtil.getRandomId();
		return MessageSecurityContext_soapbox.getWsuIdAllocator().createId(CryptoUtil.getRandomId(), null);
	}
}