You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ws.apache.org by Ma...@fiducia.de on 2010/11/24 13:39:42 UTC

possible bug in the class "WSSecEncrypt"


Hallo team,

it's my first post for this project, and the first one for an open source
project as well. Thus i kindly pleas to excuse my mistakes, should i have
done some.

I'm currently developing an web service framework for the Fiducia, germany
(huge Java banking project). My current task is to encrypt some parts of
the SOAP-Headers, containing attachments.

The structure of the SOAP-Message is like this:
---
<xml...>
<soapenv:Envelope>
   <soapenv:Header>
      <myNS:Header1>
      <!-- XML data-->
      </myNS:Header1>
      <myNS:Header2>
      <!-- XML data-->
      </myNS:Header2>
      ...
      <myNS:Attachments>
         <myNS:attachment>
            <!-- binary data base64 encoded -->
         </myNS:attachment>
         <myNS:attachment>
            <!-- binary data base64 encoded -->
         </myNS:attachment>
         <myNS:attachment>
            <!-- binary data base64 encoded -->
         </myNS:attachment>
         ...
      </myNS:Attachments>
      ...
      <myNS:HeaderX>
      <!-- XML data-->
      </myNS:HeaderX>
   </soapenv:Header>
   <soapenv:Body>
      <!-- XML data-->
   </soapenv:Body>
</soapenv:Envelope>
---

The attachments will be extracted later in their own MIME multipart parts,
using MTOM.
My problem is now, that i cannot encrypt the attachments separately from
each other. I can encrypt the whole Attachments-header using:
---
WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments", "
myNS-URI", "Content");
encryptionParts.add(encryptionPart);
---
But if I want to encrypt the attachment-elements separately using:
---
WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
"myNS-URI", "Content");
encryptionParts.add(encryptionPart);
---
then only the firs one will be encrypted. The others will not.

I have quickly analysed the class
org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495
and following, especially the one  with:
---
body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
---
Well, this line finds only one (the first one) element with the given name,
and not all of them. Then I implemented some work aound - not pretty, but
working - and now this class canencrypt all the elements with the given
name.
here is the modified method:
---
private Vector doEncryption(
        Document doc,
        SecretKey secretKey,
        KeyInfo keyInfo,
        Vector references
    ) throws WSSecurityException {

        XMLCipher xmlCipher = null;
        try {
            xmlCipher = XMLCipher.getInstance(symEncAlgo);
        } catch (XMLEncryptionException e3) {
            throw new WSSecurityException(
                WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
            );
        }

        Vector encDataRef = new Vector();

        boolean cloneKeyInfo = false;
        for (int part = 0; part < references.size(); part++) {
            WSEncryptionPart encPart = (WSEncryptionPart) references.get
(part);

            String idToEnc = encPart.getId();
            String elemName = encPart.getName();
            String nmSpace = encPart.getNamespace();
            String modifier = encPart.getEncModifier();
            //
            // Third step: get the data to encrypt.
            //
            //Element body = null;
            if (idToEnc != null) {
                Element element =
                    WSSecurityUtil.findElementById(
                        document.getDocumentElement(), idToEnc,
WSConstants.WSU_NS
                    );
                if (element == null) {
                    element =
                        WSSecurityUtil.findElementById(document
.getDocumentElement(), idToEnc, null);
                }
                if (element == null) {
                    throw new WSSecurityException(
                        WSSecurityException.FAILURE,
                        "noEncElement",
                        new Object[] {"{" + nmSpace + "}" + elemName}
                    );
                }
                String encRef = encryptPart(document, encPart, element,
keyInfo, xmlCipher, secretKey);
                encDataRef.add(encRef);
            } else {
                NodeList elements = document.getElementsByTagNameNS
(nmSpace, elemName);
                if(elements == null || elements.getLength() <= 0) {
                    throw new WSSecurityException(
                            WSSecurityException.FAILURE,
                            "noEncElement",
                            new Object[] {"{" + nmSpace + "}" + elemName}
                        );
                }
                for(int i = 0; i < elements.getLength(); i++) {
                    Element element = (Element)elements.item(i);
                    String encRef = encryptPart(document, encPart, element,
keyInfo, xmlCipher, secretKey);
                    encDataRef.add(encRef);
                }
            }
        }
        return encDataRef;
    }
---

and here is the ne private method used by the modified one:
---
private String encryptPart(Document doc, WSEncryptionPart encPart, Element
element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey ) throws
WSSecurityException
    {
        Vector encDataRef = new Vector();

        String modifier = encPart.getEncModifier();

        boolean content = modifier.equals("Content") ? true : false;
        String xencEncryptedDataId = wssConfig.getIdAllocator().createId(
"EncDataId-", element);
        encPart.setEncId(xencEncryptedDataId);

        boolean cloneKeyInfo = true;

        if (keyInfo == null) {
            keyInfo = new KeyInfo(document);
            SecurityTokenReference secToken = new SecurityTokenReference(
document);
            Reference ref = new Reference(document);
            if (encKeyIdDirectId) {
                ref.setURI(encKeyId);
            } else {
                ref.setURI("#" + encKeyId);
            }
            if (encKeyValueType != null) {
                ref.setValueType(encKeyValueType);
            }
            secToken.setReference(ref);
            keyInfo.addUnknownElement(secToken.getElement());
            Element keyInfoElement = keyInfo.getElement();
            keyInfoElement.setAttributeNS(
                WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX,
WSConstants.SIG_NS
            );
        }
        //
        // Fourth step: encrypt data, and set necessary attributes in
        // xenc:EncryptedData
        //
        try {
            if (modifier.equals("Header")) {

                Element elem =
                    doc.createElementNS(
                        WSConstants.WSSE11_NS, "wsse11:" + WSConstants.
ENCRYPTED_HEADER
                    );
                WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
WSConstants.WSSE11_PREFIX);
                String wsuPrefix =
                    WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
WSConstants.WSU_PREFIX);
                elem.setAttributeNS(
                    WSConstants.WSU_NS, wsuPrefix + ":Id",
                    wssConfig.getIdAllocator().createId("EncHeader-",
element)
                );

                NamedNodeMap map = element.getAttributes();

                for (int i = 0 ; i < map.getLength() ; i++) {
                    Attr attr = (Attr)map.item(i);
                    if (attr.getNamespaceURI().equals(WSConstants.
URI_SOAP11_ENV)
                        || attr.getNamespaceURI().equals(WSConstants.
URI_SOAP12_ENV)) {
                        String soapEnvPrefix =
                            WSSecurityUtil.setNamespace(
                                elem, attr.getNamespaceURI(), WSConstants.
DEFAULT_SOAP_PREFIX
                            );
                        elem.setAttributeNS(
                            attr.getNamespaceURI(),
                            soapEnvPrefix + ":" + attr.getLocalName(),
                            attr.getValue()
                        );
                    }
                }

                xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
                EncryptedData encData = xmlCipher.getEncryptedData();
                encData.setId(xencEncryptedDataId);
                encData.setKeyInfo(keyInfo);
                xmlCipher.doFinal(doc, element, content);

                Element encDataElem =
                    WSSecurityUtil.findElementById(
                        document.getDocumentElement(), xencEncryptedDataId,
null
                    );
                Node clone = encDataElem.cloneNode(true);
                elem.appendChild(clone);
                encDataElem.getParentNode().appendChild(elem);
                encDataElem.getParentNode().removeChild(encDataElem);
            } else {
                xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
                EncryptedData encData = xmlCipher.getEncryptedData();
                encData.setId(xencEncryptedDataId);
                encData.setKeyInfo(keyInfo);
                xmlCipher.doFinal(doc, element, content);
            }
            if (cloneKeyInfo) {
                keyInfo = new KeyInfo((Element) keyInfo.getElement
().cloneNode(true), null);
            }
        } catch (Exception e2) {
            throw new WSSecurityException(
                WSSecurityException.FAILED_ENCRYPTION, null, null, e2
            );
        }
        return xencEncryptedDataId;

    }
---


I've just extraced the part of the old method responsible for the
encryption/marking of one Element and I call it for all found parts.
Perheadps you can discuss this modification and biuld it in one of the next
version - should it be approved.

And there is one more suggestion - the class "WSEncryptionPart"... Since
wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The
lookup is done only by the namespaceURI and local name. Perheaps it will be
used in one of the future versions. But - what if the namespace/local name
does not correspond to the XPath? And if we have the XPath then we can use
only it, and forget the namespace/local name.
So it would be nice, if the class WSEncryptionPart would have all the
currently used constructors, and beside this  new one with the XPath.
 Something like this:
---
//old ones:
WSEncryptionPart(String id)
WSEncryptionPart(String id, String encMod)
WSEncryptionPart(String id, String encMod,int type)
WSEncryptionPart(String nm, String nmspace, String encMod)
WSEncryptionPart(String nm, String nmspace, String encMod, int type)

//new ones:
WSEncryptionPart(String xPath, String encMod)
WSEncryptionPart(String xPath, String encMod, int type)
---
and the newly added methods for setting and getting the xpath can be
deleted.
The search for the given element in the document can be then done by xpath
_or_ the old way, depending on the parameter set.



Greetings,

Marcin Markiewicz



----------------------------------------------------------------------------------------------------------------------------------------------


Fiducia IT AG
Fiduciastraße 20
76227 Karlsruhe

Sitz der Gesellschaft: Karlsruhe
AG Mannheim HRB 100059

Vorsitzender des Aufsichtsrats: Gregor Scheller
Vorsitzender des Vorstands: Michael Krings
Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger

Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
----------------------------------------------------------------------------------------------------------------------------------------------

RE: possible bug in the class "WSSecEncrypt"

Posted by Martin Gainty <mg...@hotmail.com>.
Goddag Marcin

another way of accomplishing the objective is to refactor WSEncryptionPart to be an abstract class
and force the concrete classes extending WSEncryptionPart to implement XPath in constructors,accessors and mutators

In order for this to pass muster you'll need to build testcases which calls these new methods to 
work for single element input
as well as XMLPath extracted groups

what criteria are you using to build the Vector for doEncryption?

Vielen Danke,
Martin 
______________________________________________ 
Verzicht und Vertraulichkeitanmerkung/Note de déni et de confidentialité
 
Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene Empfaenger sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte Weiterleitung oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht dient lediglich dem Austausch von Informationen und entfaltet keine rechtliche Bindungswirkung. Aufgrund der leichten Manipulierbarkeit von E-Mails koennen wir keine Haftung fuer den Inhalt uebernehmen.
Ce message est confidentiel et peut être privilégié. Si vous n'êtes pas le destinataire prévu, nous te demandons avec bonté que pour satisfaire informez l'expéditeur. N'importe quelle diffusion non autorisée ou la copie de ceci est interdite. Ce message sert à l'information seulement et n'aura pas n'importe quel effet légalement obligatoire. Étant donné que les email peuvent facilement être sujets à la manipulation, nous ne pouvons accepter aucune responsabilité pour le contenu fourni.




Subject: possible bug in the class "WSSecEncrypt"
To: wss4j-dev@ws.apache.org
CC: marcin.markiewicz@gmx.de
From: Marcin.Markiewicz@fiducia.de
Date: Wed, 24 Nov 2010 13:39:42 +0100


Hallo team,



it's my first post for this project, and the first one for an open source project as well. Thus i kindly pleas to excuse my mistakes, should i have done some.



I'm currently developing an web service framework for the Fiducia, germany (huge Java banking project). My current task is to encrypt some parts of the SOAP-Headers, containing attachments.



The structure of the SOAP-Message is like this:

---

<xml...>

<soapenv:Envelope>

   <soapenv:Header>

      <myNS:Header1> 

      <!-- XML data-->

      </myNS:Header1>

      <myNS:Header2>

      <!-- XML data-->

      </myNS:Header2>

      ...

      <myNS:Attachments>

         <myNS:attachment>

            <!-- binary data base64 encoded -->

         </myNS:attachment>

         <myNS:attachment>

            <!-- binary data base64 encoded -->

         </myNS:attachment>

         <myNS:attachment>

            <!-- binary data base64 encoded -->

         </myNS:attachment>

         ...

      </myNS:Attachments>

      ...

      <myNS:HeaderX>

      <!-- XML data-->

      </myNS:HeaderX>

   </soapenv:Header>

   <soapenv:Body>

      <!-- XML data-->

   </soapenv:Body>

</soapenv:Envelope>

---



The attachments will be extracted later in their own MIME multipart parts, using MTOM.

My problem is now, that i cannot encrypt the attachments separately from each other. I can encrypt the whole Attachments-header using:

---

WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments", "myNS-URI", "Content");

encryptionParts.add(encryptionPart);

---

But if I want to encrypt the attachment-elements separately using:

---

WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment", "myNS-URI", "Content");

encryptionParts.add(encryptionPart);

---

then only the firs one will be encrypted. The others will not.



I have quickly analysed the class org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495 and following, especially the one  with:

---

body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);

---

Well, this line finds only one (the first one) element with the given name, and not all of them. Then I implemented some work aound - not pretty, but working - and now this class canencrypt all the elements with the given name.

here is the modified method:

---

private Vector doEncryption(

        Document doc, 

        SecretKey secretKey,

        KeyInfo keyInfo, 

        Vector references

    ) throws WSSecurityException {



        XMLCipher xmlCipher = null;

        try {

            xmlCipher = XMLCipher.getInstance(symEncAlgo);

        } catch (XMLEncryptionException e3) {

            throw new WSSecurityException(

                WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3

            );

        }



        Vector encDataRef = new Vector();



        boolean cloneKeyInfo = false;

        for (int part = 0; part < references.size(); part++) {

            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);



            String idToEnc = encPart.getId();

            String elemName = encPart.getName();

            String nmSpace = encPart.getNamespace();

            String modifier = encPart.getEncModifier();

            //

            // Third step: get the data to encrypt.

            //

            //Element body = null;

            if (idToEnc != null) {

                Element element = 

                    WSSecurityUtil.findElementById(

                        document.getDocumentElement(), idToEnc, WSConstants.WSU_NS

                    );

                if (element == null) {

                    element = 

                        WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc, null);

                }

                if (element == null) {

                    throw new WSSecurityException(

                        WSSecurityException.FAILURE,

                        "noEncElement", 

                        new Object[] {"{" + nmSpace + "}" + elemName}

                    );

                }

                String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher, secretKey);

                encDataRef.add(encRef);                

            } else {

                NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);

                if(elements == null || elements.getLength() <= 0) {

                    throw new WSSecurityException(

                            WSSecurityException.FAILURE,

                            "noEncElement", 

                            new Object[] {"{" + nmSpace + "}" + elemName}

                        );                    

                }

                for(int i = 0; i < elements.getLength(); i++) {

                    Element element = (Element)elements.item(i);

                    String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher, secretKey);

                    encDataRef.add(encRef);                

                }                

            }

        }

        return encDataRef;

    }

---



and here is the ne private method used by the modified one:

---

private String encryptPart(Document doc, WSEncryptionPart encPart, Element element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey ) throws WSSecurityException

    {

        Vector encDataRef = new Vector();

        

        String modifier = encPart.getEncModifier();

        

        boolean content = modifier.equals("Content") ? true : false;

        String xencEncryptedDataId = wssConfig.getIdAllocator().createId("EncDataId-", element);

        encPart.setEncId(xencEncryptedDataId);



        boolean cloneKeyInfo = true;

        

        if (keyInfo == null) {

            keyInfo = new KeyInfo(document);

            SecurityTokenReference secToken = new SecurityTokenReference(document);

            Reference ref = new Reference(document);

            if (encKeyIdDirectId) {

                ref.setURI(encKeyId);

            } else {

                ref.setURI("#" + encKeyId);                    

            }

            if (encKeyValueType != null) {

                ref.setValueType(encKeyValueType);

            }

            secToken.setReference(ref);

            keyInfo.addUnknownElement(secToken.getElement());

            Element keyInfoElement = keyInfo.getElement();

            keyInfoElement.setAttributeNS(

                WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS

            );

        }

        //

        // Fourth step: encrypt data, and set necessary attributes in

        // xenc:EncryptedData

        //

        try {

            if (modifier.equals("Header")) {

                

                Element elem = 

                    doc.createElementNS(

                        WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER

                    );

                WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);

                String wsuPrefix = 

                    WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);

                elem.setAttributeNS(

                    WSConstants.WSU_NS, wsuPrefix + ":Id", 

                    wssConfig.getIdAllocator().createId("EncHeader-", element)

                );

                

                NamedNodeMap map = element.getAttributes();

                

                for (int i = 0 ; i < map.getLength() ; i++) {

                    Attr attr = (Attr)map.item(i);

                    if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)

                        || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {                         

                        String soapEnvPrefix = 

                            WSSecurityUtil.setNamespace(

                                elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX

                            );

                        elem.setAttributeNS(

                            attr.getNamespaceURI(), 

                            soapEnvPrefix + ":" + attr.getLocalName(), 

                            attr.getValue()

                        );

                    }

                }

                

                xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);

                EncryptedData encData = xmlCipher.getEncryptedData();

                encData.setId(xencEncryptedDataId);

                encData.setKeyInfo(keyInfo);

                xmlCipher.doFinal(doc, element, content);

                

                Element encDataElem = 

                    WSSecurityUtil.findElementById(

                        document.getDocumentElement(), xencEncryptedDataId, null

                    );

                Node clone = encDataElem.cloneNode(true);

                elem.appendChild(clone);

                encDataElem.getParentNode().appendChild(elem);

                encDataElem.getParentNode().removeChild(encDataElem); 

            } else {

                xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);

                EncryptedData encData = xmlCipher.getEncryptedData();

                encData.setId(xencEncryptedDataId);

                encData.setKeyInfo(keyInfo);

                xmlCipher.doFinal(doc, element, content);          

            }

            if (cloneKeyInfo) {

                keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true), null);

            }

        } catch (Exception e2) {

            throw new WSSecurityException(

                WSSecurityException.FAILED_ENCRYPTION, null, null, e2

            );

        }

        return xencEncryptedDataId;

        

    }

---





I've just extraced the part of the old method responsible for the encryption/marking of one Element and I call it for all found parts.

Perheadps you can discuss this modification and biuld it in one of the next version - should it be approved.



And there is one more suggestion - the class "WSEncryptionPart"... Since wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The lookup is done only by the namespaceURI and local name. Perheaps it will be used in one of the future versions. But - what if the namespace/local name does not correspond to the XPath? And if we have the XPath then we can use only it, and forget the namespace/local name. 

So it would be nice, if the class WSEncryptionPart would have all the currently used constructors, and beside this  new one with the XPath.

 Something like this:

---

//old ones:

WSEncryptionPart(String id)

WSEncryptionPart(String id, String encMod) 

WSEncryptionPart(String id, String encMod,int type)

WSEncryptionPart(String nm, String nmspace, String encMod)

WSEncryptionPart(String nm, String nmspace, String encMod, int type)



//new ones:

WSEncryptionPart(String xPath, String encMod)

WSEncryptionPart(String xPath, String encMod, int type)

---

and the newly added methods for setting and getting the xpath can be deleted. 

The search for the given element in the document can be then done by xpath _or_ the old way, depending on the parameter set.







Greetings,



Marcin Markiewicz







---------------------------------------------------------------------------------------------------------------------------------------------- 



Fiducia IT AG 

Fiduciastraße 20 

76227 Karlsruhe 



Sitz der Gesellschaft: Karlsruhe 

AG Mannheim HRB 100059 



Vorsitzender des Aufsichtsrats: Gregor Scheller

Vorsitzender des Vorstands: Michael Krings 

Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns

Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger



Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de 

---------------------------------------------------------------------------------------------------------------------------------------------- 
 		 	   		  

RE: Antwort: Fwd: possible bug in the class "WSSecEncrypt"

Posted by Martin Gainty <mg...@hotmail.com>.
danke marcin

Martin 
______________________________________________ 
Verzicht und Vertraulichkeitanmerkung/Note de déni et de confidentialité

Diese Nachricht ist vertraulich. Sollten Sie nicht der vorgesehene Empfaenger sein, so bitten wir hoeflich um eine Mitteilung. Jede unbefugte Weiterleitung oder Fertigung einer Kopie ist unzulaessig. Diese Nachricht dient lediglich dem Austausch von Informationen und entfaltet keine rechtliche Bindungswirkung. Aufgrund der leichten Manipulierbarkeit von E-Mails koennen wir keine Haftung fuer den Inhalt uebernehmen.
Ce message est confidentiel et peut être privilégié. Si vous n'êtes pas le destinataire prévu, nous te demandons avec bonté que pour satisfaire informez l'expéditeur. N'importe quelle diffusion non autorisée ou la copie de ceci est interdite. Ce message sert à l'information seulement et n'aura pas n'importe quel effet légalement obligatoire. Étant donné que les email peuvent facilement être sujets à la manipulation, nous ne pouvons accepter aucune responsabilité pour le contenu fourni.



 



Subject: Antwort: Fwd: possible bug in the class "WSSecEncrypt"
To: coheigea@apache.org
CC: dev@ws.apache.org; marcin.markiewicz@gmx.de
From: Marcin.Markiewicz@fiducia.de
Date: Thu, 25 Nov 2010 13:23:15 +0100


Hello,

I created a JIRA (WSS-254) for this problem. My solution is attached and commented there too.

Colm O hEigeartaigh ---24.11.2010 15:18:46---(In case you are not subscribe to dev@ws.apache.org - please direct all future WSS4J queries to this

Von: Colm O hEigeartaigh <co...@apache.org>
An: Marcin.Markiewicz@fiducia.de
Datum: 24.11.2010 15:18
Betreff: Fwd: possible bug in the class "WSSecEncrypt"





(In case you are not subscribe to dev@ws.apache.org - please direct
all future WSS4J queries to this list).

Colm.


---------- Forwarded message ----------
From: Colm O hEigeartaigh <co...@apache.org>
Date: Wed, Nov 24, 2010 at 2:16 PM
Subject: Re: possible bug in the class "WSSecEncrypt"
To: dev@ws.apache.org


Hi Marcin,

1) Yes that looks like a bug. Please create a JIRA
(https://issues.apache.org/jira/browse/WSS) and attach a patch for
this issue. Please note that NodeLists are not thread-safe, and are to
be avoided in WSS4J.

2) XPath is only used on the inbound side to refer to an element that
has been processed. I agree that it would be useful to support this
feature on the outbound side. The current API's used in
WSEncryptionPart cannot be changed for backwards compatibility
reasons. Another constructor could be added to support setting the
XPath. Some functionality would then have to be added to
WSSecurityUtil to
find a set of elements matching the XPath expression. You could add a
new JIRA for this as well if you want.

Thanks,

Colm.

On Wed, Nov 24, 2010 at 12:39 PM,  <Ma...@fiducia.de> wrote:
> Hallo team,
>
> it's my first post for this project, and the first one for an open source
> project as well. Thus i kindly pleas to excuse my mistakes, should i have
> done some.
>
> I'm currently developing an web service framework for the Fiducia, germany
> (huge Java banking project). My current task is to encrypt some parts of the
> SOAP-Headers, containing attachments.
>
> The structure of the SOAP-Message is like this:
> ---
> <xml...>
> <soapenv:Envelope>
> <soapenv:Header>
> <myNS:Header1>
> <!-- XML data-->
> </myNS:Header1>
> <myNS:Header2>
> <!-- XML data-->
> </myNS:Header2>
> ...
> <myNS:Attachments>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> ...
> </myNS:Attachments>
> ...
> <myNS:HeaderX>
> <!-- XML data-->
> </myNS:HeaderX>
> </soapenv:Header>
> <soapenv:Body>
> <!-- XML data-->
> </soapenv:Body>
> </soapenv:Envelope>
> ---
>
> The attachments will be extracted later in their own MIME multipart parts,
> using MTOM.
> My problem is now, that i cannot encrypt the attachments separately from
> each other. I can encrypt the whole Attachments-header using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> But if I want to encrypt the attachment-elements separately using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> then only the firs one will be encrypted. The others will not.
>
> I have quickly analysed the class
> org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495 and
> following, especially the one with:
> ---
> body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
> ---
> Well, this line finds only one (the first one) element with the given name,
> and not all of them. Then I implemented some work aound - not pretty, but
> working - and now this class canencrypt all the elements with the given
> name.
> here is the modified method:
> ---
> private Vector doEncryption(
> Document doc,
> SecretKey secretKey,
> KeyInfo keyInfo,
> Vector references
> ) throws WSSecurityException {
>
> XMLCipher xmlCipher = null;
> try {
> xmlCipher = XMLCipher.getInstance(symEncAlgo);
> } catch (XMLEncryptionException e3) {
> throw new WSSecurityException(
> WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
> );
> }
>
> Vector encDataRef = new Vector();
>
> boolean cloneKeyInfo = false;
> for (int part = 0; part < references.size(); part++) {
> WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
>
> String idToEnc = encPart.getId();
> String elemName = encPart.getName();
> String nmSpace = encPart.getNamespace();
> String modifier = encPart.getEncModifier();
> //
> // Third step: get the data to encrypt.
> //
> //Element body = null;
> if (idToEnc != null) {
> Element element =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), idToEnc, WSConstants.WSU_NS
> );
> if (element == null) {
> element =
> WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc,
> null);
> }
> if (element == null) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> } else {
> NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);
> if(elements == null || elements.getLength() <= 0) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> for(int i = 0; i < elements.getLength(); i++) {
> Element element = (Element)elements.item(i);
> String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> }
> }
> }
> return encDataRef;
> }
> ---
>
> and here is the ne private method used by the modified one:
> ---
> private String encryptPart(Document doc, WSEncryptionPart encPart, Element
> element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey ) throws
> WSSecurityException
> {
> Vector encDataRef = new Vector();
>
> String modifier = encPart.getEncModifier();
>
> boolean content = modifier.equals("Content") ? true : false;
> String xencEncryptedDataId =
> wssConfig.getIdAllocator().createId("EncDataId-", element);
> encPart.setEncId(xencEncryptedDataId);
>
> boolean cloneKeyInfo = true;
>
> if (keyInfo == null) {
> keyInfo = new KeyInfo(document);
> SecurityTokenReference secToken = new SecurityTokenReference(document);
> Reference ref = new Reference(document);
> if (encKeyIdDirectId) {
> ref.setURI(encKeyId);
> } else {
> ref.setURI("#" + encKeyId);
> }
> if (encKeyValueType != null) {
> ref.setValueType(encKeyValueType);
> }
> secToken.setReference(ref);
> keyInfo.addUnknownElement(secToken.getElement());
> Element keyInfoElement = keyInfo.getElement();
> keyInfoElement.setAttributeNS(
> WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
> );
> }
> //
> // Fourth step: encrypt data, and set necessary attributes in
> // xenc:EncryptedData
> //
> try {
> if (modifier.equals("Header")) {
>
> Element elem =
> doc.createElementNS(
> WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
> );
> WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
> WSConstants.WSSE11_PREFIX);
> String wsuPrefix =
> WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
> WSConstants.WSU_PREFIX);
> elem.setAttributeNS(
> WSConstants.WSU_NS, wsuPrefix + ":Id",
> wssConfig.getIdAllocator().createId("EncHeader-", element)
> );
>
> NamedNodeMap map = element.getAttributes();
>
> for (int i = 0 ; i < map.getLength() ; i++) {
> Attr attr = (Attr)map.item(i);
> if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
> || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {
> String soapEnvPrefix =
> WSSecurityUtil.setNamespace(
> elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
> );
> elem.setAttributeNS(
> attr.getNamespaceURI(),
> soapEnvPrefix + ":" + attr.getLocalName(),
> attr.getValue()
> );
> }
> }
>
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
>
> Element encDataElem =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), xencEncryptedDataId, null
> );
> Node clone = encDataElem.cloneNode(true);
> elem.appendChild(clone);
> encDataElem.getParentNode().appendChild(elem);
> encDataElem.getParentNode().removeChild(encDataElem);
> } else {
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> }
> if (cloneKeyInfo) {
> keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true), null);
> }
> } catch (Exception e2) {
> throw new WSSecurityException(
> WSSecurityException.FAILED_ENCRYPTION, null, null, e2
> );
> }
> return xencEncryptedDataId;
>
> }
> ---
>
>
> I've just extraced the part of the old method responsible for the
> encryption/marking of one Element and I call it for all found parts.
> Perheadps you can discuss this modification and biuld it in one of the next
> version - should it be approved.
>
> And there is one more suggestion - the class "WSEncryptionPart"... Since
> wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The lookup
> is done only by the namespaceURI and local name. Perheaps it will be used in
> one of the future versions. But - what if the namespace/local name does not
> correspond to the XPath? And if we have the XPath then we can use only it,
> and forget the namespace/local name.
> So it would be nice, if the class WSEncryptionPart would have all the
> currently used constructors, and beside this new one with the XPath.
> Something like this:
> ---
> //old ones:
> WSEncryptionPart(String id)
> WSEncryptionPart(String id, String encMod)
> WSEncryptionPart(String id, String encMod,int type)
> WSEncryptionPart(String nm, String nmspace, String encMod)
> WSEncryptionPart(String nm, String nmspace, String encMod, int type)
>
> //new ones:
> WSEncryptionPart(String xPath, String encMod)
> WSEncryptionPart(String xPath, String encMod, int type)
> ---
> and the newly added methods for setting and getting the xpath can be
> deleted.
> The search for the given element in the document can be then done by xpath
> _or_ the old way, depending on the parameter set.
>
>
>
> Greetings,
>
> Marcin Markiewicz
>
>
>
> ----------------------------------------------------------------------------------------------------------------------------------------------
>
> Fiducia IT AG
> Fiduciastraße 20
> 76227 Karlsruhe
>
> Sitz der Gesellschaft: Karlsruhe
> AG Mannheim HRB 100059
>
> Vorsitzender des Aufsichtsrats: Gregor Scheller
> Vorsitzender des Vorstands: Michael Krings
> Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
> Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger
>
> Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
> ----------------------------------------------------------------------------------------------------------------------------------------------
>





---------------------------------------------------------------------------------------------------------------------------------------------- 

Fiducia IT AG 
Fiduciastraße 20 
76227 Karlsruhe 

Sitz der Gesellschaft: Karlsruhe 
AG Mannheim HRB 100059 

Vorsitzender des Aufsichtsrats: Gregor Scheller
Vorsitzender des Vorstands: Michael Krings 
Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger

Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de 
---------------------------------------------------------------------------------------------------------------------------------------------- 
 		 	   		  

Antwort: Fwd: possible bug in the class "WSSecEncrypt"

Posted by Ma...@fiducia.de.
Hallo,

I attached a new possible solution to the Jira WSS 254 for this problem. It
is intended to work with wss4j 1.6. The code changes are quite huge...
Perheaps you can look at it and give me some feedback about it. It is not
tested yet...
This solution is based on a new interface IWSEncryptionPart with its
implementations WSEncryptionPartId, ...Name, ...XPath, ...StrTransform, and
an abstract class AbstractWSEncryptionPart containing just two methods that
are common for all the implementation classes. The ...StrTransform class is
used for this one special case to describe an element by name, if the name
is "STRTransform" (or so), and it is identical to the ...Name class. But
now the check in the code is not done by the "if ( name.equals
("STRTransform")"...case but by "if (IWSEncrpytionPart
instanceof ...StrTransform)" case.
All of the EncryptionPart implementation can describe multiple elements,
thus a list of encIds has to be manged instead of just one.
And there are changes across the code to use this new interface.

Greetings,
Marcin.



Von:	Marcin.Markiewicz@fiducia.de
An:	coheigea@apache.org
Kopie:	dev@ws.apache.org, marcin.markiewicz@gmx.de
Datum:	25.11.2010 14:04
Betreff:	Antwort: Fwd: possible bug in the class "WSSecEncrypt"



Hello,

I created a JIRA (WSS-254) for this problem. My solution is attached and
commented there too.

Inaktiv: Details verbergen für Colm O hEigeartaigh ---24.11.2010
15:18:46---(In case you are not subscribe to dev@ws.apache.orgColm O
hEigeartaigh ---24.11.2010 15:18:46---(In case you are not subscribe to
dev@ws.apache.org - please direct all future WSS4J queries to this

Von: Colm O hEigeartaigh <co...@apache.org>
An: Marcin.Markiewicz@fiducia.de
Datum: 24.11.2010 15:18
Betreff: Fwd: possible bug in the class "WSSecEncrypt"



(In case you are not subscribe to dev@ws.apache.org - please direct
all future WSS4J queries to this list).

Colm.


---------- Forwarded message ----------
From: Colm O hEigeartaigh <co...@apache.org>
Date: Wed, Nov 24, 2010 at 2:16 PM
Subject: Re: possible bug in the class "WSSecEncrypt"
To: dev@ws.apache.org


Hi Marcin,

1) Yes that looks like a bug. Please create a JIRA
(https://issues.apache.org/jira/browse/WSS) and attach a patch for
this issue. Please note that NodeLists are not thread-safe, and are to
be avoided in WSS4J.

2) XPath is only used on the inbound side to refer to an element that
has been processed. I agree that it would be useful to support this
feature on the outbound side. The current API's used in
WSEncryptionPart cannot be changed for backwards compatibility
reasons. Another constructor could be added to support setting the
XPath. Some functionality would then have to be added to
WSSecurityUtil to
find a set of elements matching the XPath expression. You could add a
new JIRA for this as well if you want.

Thanks,

Colm.

On Wed, Nov 24, 2010 at 12:39 PM,  <Ma...@fiducia.de> wrote:
> Hallo team,
>
> it's my first post for this project, and the first one for an open source
> project as well. Thus i kindly pleas to excuse my mistakes, should i have
> done some.
>
> I'm currently developing an web service framework for the Fiducia,
germany
> (huge Java banking project). My current task is to encrypt some parts of
the
> SOAP-Headers, containing attachments.
>
> The structure of the SOAP-Message is like this:
> ---
> <xml...>
> <soapenv:Envelope>
> <soapenv:Header>
> <myNS:Header1>
> <!-- XML data-->
> </myNS:Header1>
> <myNS:Header2>
> <!-- XML data-->
> </myNS:Header2>
> ...
> <myNS:Attachments>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> ...
> </myNS:Attachments>
> ...
> <myNS:HeaderX>
> <!-- XML data-->
> </myNS:HeaderX>
> </soapenv:Header>
> <soapenv:Body>
> <!-- XML data-->
> </soapenv:Body>
> </soapenv:Envelope>
> ---
>
> The attachments will be extracted later in their own MIME multipart
parts,
> using MTOM.
> My problem is now, that i cannot encrypt the attachments separately from
> each other. I can encrypt the whole Attachments-header using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> But if I want to encrypt the attachment-elements separately using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> then only the firs one will be encrypted. The others will not.
>
> I have quickly analysed the class
> org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495
and
> following, especially the one with:
> ---
> body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
> ---
> Well, this line finds only one (the first one) element with the given
name,
> and not all of them. Then I implemented some work aound - not pretty, but
> working - and now this class canencrypt all the elements with the given
> name.
> here is the modified method:
> ---
> private Vector doEncryption(
> Document doc,
> SecretKey secretKey,
> KeyInfo keyInfo,
> Vector references
> ) throws WSSecurityException {
>
> XMLCipher xmlCipher = null;
> try {
> xmlCipher = XMLCipher.getInstance(symEncAlgo);
> } catch (XMLEncryptionException e3) {
> throw new WSSecurityException(
> WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
> );
> }
>
> Vector encDataRef = new Vector();
>
> boolean cloneKeyInfo = false;
> for (int part = 0; part < references.size(); part++) {
> WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
>
> String idToEnc = encPart.getId();
> String elemName = encPart.getName();
> String nmSpace = encPart.getNamespace();
> String modifier = encPart.getEncModifier();
> //
> // Third step: get the data to encrypt.
> //
> //Element body = null;
> if (idToEnc != null) {
> Element element =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), idToEnc, WSConstants.WSU_NS
> );
> if (element == null) {
> element =
> WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc,
> null);
> }
> if (element == null) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> String encRef = encryptPart(document, encPart, element, keyInfo,
xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> } else {
> NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);
> if(elements == null || elements.getLength() <= 0) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> for(int i = 0; i < elements.getLength(); i++) {
> Element element = (Element)elements.item(i);
> String encRef = encryptPart(document, encPart, element, keyInfo,
xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> }
> }
> }
> return encDataRef;
> }
> ---
>
> and here is the ne private method used by the modified one:
> ---
> private String encryptPart(Document doc, WSEncryptionPart encPart,
Element
> element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey )
throws
> WSSecurityException
> {
> Vector encDataRef = new Vector();
>
> String modifier = encPart.getEncModifier();
>
> boolean content = modifier.equals("Content") ? true : false;
> String xencEncryptedDataId =
> wssConfig.getIdAllocator().createId("EncDataId-", element);
> encPart.setEncId(xencEncryptedDataId);
>
> boolean cloneKeyInfo = true;
>
> if (keyInfo == null) {
> keyInfo = new KeyInfo(document);
> SecurityTokenReference secToken = new SecurityTokenReference(document);
> Reference ref = new Reference(document);
> if (encKeyIdDirectId) {
> ref.setURI(encKeyId);
> } else {
> ref.setURI("#" + encKeyId);
> }
> if (encKeyValueType != null) {
> ref.setValueType(encKeyValueType);
> }
> secToken.setReference(ref);
> keyInfo.addUnknownElement(secToken.getElement());
> Element keyInfoElement = keyInfo.getElement();
> keyInfoElement.setAttributeNS(
> WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX,
WSConstants.SIG_NS
> );
> }
> //
> // Fourth step: encrypt data, and set necessary attributes in
> // xenc:EncryptedData
> //
> try {
> if (modifier.equals("Header")) {
>
> Element elem =
> doc.createElementNS(
> WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
> );
> WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
> WSConstants.WSSE11_PREFIX);
> String wsuPrefix =
> WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
> WSConstants.WSU_PREFIX);
> elem.setAttributeNS(
> WSConstants.WSU_NS, wsuPrefix + ":Id",
> wssConfig.getIdAllocator().createId("EncHeader-", element)
> );
>
> NamedNodeMap map = element.getAttributes();
>
> for (int i = 0 ; i < map.getLength() ; i++) {
> Attr attr = (Attr)map.item(i);
> if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
> || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {
> String soapEnvPrefix =
> WSSecurityUtil.setNamespace(
> elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
> );
> elem.setAttributeNS(
> attr.getNamespaceURI(),
> soapEnvPrefix + ":" + attr.getLocalName(),
> attr.getValue()
> );
> }
> }
>
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
>
> Element encDataElem =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), xencEncryptedDataId, null
> );
> Node clone = encDataElem.cloneNode(true);
> elem.appendChild(clone);
> encDataElem.getParentNode().appendChild(elem);
> encDataElem.getParentNode().removeChild(encDataElem);
> } else {
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> }
> if (cloneKeyInfo) {
> keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true),
null);
> }
> } catch (Exception e2) {
> throw new WSSecurityException(
> WSSecurityException.FAILED_ENCRYPTION, null, null, e2
> );
> }
> return xencEncryptedDataId;
>
> }
> ---
>
>
> I've just extraced the part of the old method responsible for the
> encryption/marking of one Element and I call it for all found parts.
> Perheadps you can discuss this modification and biuld it in one of the
next
> version - should it be approved.
>
> And there is one more suggestion - the class "WSEncryptionPart"... Since
> wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The
lookup
> is done only by the namespaceURI and local name. Perheaps it will be used
in
> one of the future versions. But - what if the namespace/local name does
not
> correspond to the XPath? And if we have the XPath then we can use only
it,
> and forget the namespace/local name.
> So it would be nice, if the class WSEncryptionPart would have all the
> currently used constructors, and beside this new one with the XPath.
> Something like this:
> ---
> //old ones:
> WSEncryptionPart(String id)
> WSEncryptionPart(String id, String encMod)
> WSEncryptionPart(String id, String encMod,int type)
> WSEncryptionPart(String nm, String nmspace, String encMod)
> WSEncryptionPart(String nm, String nmspace, String encMod, int type)
>
> //new ones:
> WSEncryptionPart(String xPath, String encMod)
> WSEncryptionPart(String xPath, String encMod, int type)
> ---
> and the newly added methods for setting and getting the xpath can be
> deleted.
> The search for the given element in the document can be then done by
xpath
> _or_ the old way, depending on the parameter set.
>
>
>
> Greetings,
>
> Marcin Markiewicz
>
>
>
>
----------------------------------------------------------------------------------------------------------------------------------------------

>
> Fiducia IT AG
> Fiduciastraße 20
> 76227 Karlsruhe
>
> Sitz der Gesellschaft: Karlsruhe
> AG Mannheim HRB 100059
>
> Vorsitzender des Aufsichtsrats: Gregor Scheller
> Vorsitzender des Vorstands: Michael Krings
> Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
> Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger
>
> Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
>
----------------------------------------------------------------------------------------------------------------------------------------------

>





----------------------------------------------------------------------------------------------------------------------------------------------


Fiducia IT AG
Fiduciastraße 20
76227 Karlsruhe

Sitz der Gesellschaft: Karlsruhe
AG Mannheim HRB 100059

Vorsitzender des Aufsichtsrats: Gregor Scheller
Vorsitzender des Vorstands: Michael Krings
Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger

Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
----------------------------------------------------------------------------------------------------------------------------------------------





----------------------------------------------------------------------------------------------------------------------------------------------


Fiducia IT AG
Fiduciastraße 20
76227 Karlsruhe

Sitz der Gesellschaft: Karlsruhe
AG Mannheim HRB 100059

Vorsitzender des Aufsichtsrats: Gregor Scheller
Vorsitzender des Vorstands: Michael Krings
Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger

Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
----------------------------------------------------------------------------------------------------------------------------------------------

Antwort: Fwd: possible bug in the class "WSSecEncrypt"

Posted by Ma...@fiducia.de.
Hello,

I created a JIRA (WSS-254) for this problem. My solution is attached and
commented there too.



Von:	Colm O hEigeartaigh <co...@apache.org>
An:	Marcin.Markiewicz@fiducia.de
Datum:	24.11.2010 15:18
Betreff:	Fwd: possible bug in the class "WSSecEncrypt"



(In case you are not subscribe to dev@ws.apache.org - please direct
all future WSS4J queries to this list).

Colm.


---------- Forwarded message ----------
From: Colm O hEigeartaigh <co...@apache.org>
Date: Wed, Nov 24, 2010 at 2:16 PM
Subject: Re: possible bug in the class "WSSecEncrypt"
To: dev@ws.apache.org


Hi Marcin,

1) Yes that looks like a bug. Please create a JIRA
(https://issues.apache.org/jira/browse/WSS) and attach a patch for
this issue. Please note that NodeLists are not thread-safe, and are to
be avoided in WSS4J.

2) XPath is only used on the inbound side to refer to an element that
has been processed. I agree that it would be useful to support this
feature on the outbound side. The current API's used in
WSEncryptionPart cannot be changed for backwards compatibility
reasons. Another constructor could be added to support setting the
XPath. Some functionality would then have to be added to
WSSecurityUtil to
find a set of elements matching the XPath expression. You could add a
new JIRA for this as well if you want.

Thanks,

Colm.

On Wed, Nov 24, 2010 at 12:39 PM,  <Ma...@fiducia.de> wrote:
> Hallo team,
>
> it's my first post for this project, and the first one for an open source
> project as well. Thus i kindly pleas to excuse my mistakes, should i have
> done some.
>
> I'm currently developing an web service framework for the Fiducia,
germany
> (huge Java banking project). My current task is to encrypt some parts of
the
> SOAP-Headers, containing attachments.
>
> The structure of the SOAP-Message is like this:
> ---
> <xml...>
> <soapenv:Envelope>
> <soapenv:Header>
> <myNS:Header1>
> <!-- XML data-->
> </myNS:Header1>
> <myNS:Header2>
> <!-- XML data-->
> </myNS:Header2>
> ...
> <myNS:Attachments>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> ...
> </myNS:Attachments>
> ...
> <myNS:HeaderX>
> <!-- XML data-->
> </myNS:HeaderX>
> </soapenv:Header>
> <soapenv:Body>
> <!-- XML data-->
> </soapenv:Body>
> </soapenv:Envelope>
> ---
>
> The attachments will be extracted later in their own MIME multipart
parts,
> using MTOM.
> My problem is now, that i cannot encrypt the attachments separately from
> each other. I can encrypt the whole Attachments-header using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> But if I want to encrypt the attachment-elements separately using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> then only the firs one will be encrypted. The others will not.
>
> I have quickly analysed the class
> org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495
and
> following, especially the one with:
> ---
> body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
> ---
> Well, this line finds only one (the first one) element with the given
name,
> and not all of them. Then I implemented some work aound - not pretty, but
> working - and now this class canencrypt all the elements with the given
> name.
> here is the modified method:
> ---
> private Vector doEncryption(
> Document doc,
> SecretKey secretKey,
> KeyInfo keyInfo,
> Vector references
> ) throws WSSecurityException {
>
> XMLCipher xmlCipher = null;
> try {
> xmlCipher = XMLCipher.getInstance(symEncAlgo);
> } catch (XMLEncryptionException e3) {
> throw new WSSecurityException(
> WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
> );
> }
>
> Vector encDataRef = new Vector();
>
> boolean cloneKeyInfo = false;
> for (int part = 0; part < references.size(); part++) {
> WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
>
> String idToEnc = encPart.getId();
> String elemName = encPart.getName();
> String nmSpace = encPart.getNamespace();
> String modifier = encPart.getEncModifier();
> //
> // Third step: get the data to encrypt.
> //
> //Element body = null;
> if (idToEnc != null) {
> Element element =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), idToEnc, WSConstants.WSU_NS
> );
> if (element == null) {
> element =
> WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc,
> null);
> }
> if (element == null) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> String encRef = encryptPart(document, encPart, element, keyInfo,
xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> } else {
> NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);
> if(elements == null || elements.getLength() <= 0) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> for(int i = 0; i < elements.getLength(); i++) {
> Element element = (Element)elements.item(i);
> String encRef = encryptPart(document, encPart, element, keyInfo,
xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> }
> }
> }
> return encDataRef;
> }
> ---
>
> and here is the ne private method used by the modified one:
> ---
> private String encryptPart(Document doc, WSEncryptionPart encPart,
Element
> element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey )
throws
> WSSecurityException
> {
> Vector encDataRef = new Vector();
>
> String modifier = encPart.getEncModifier();
>
> boolean content = modifier.equals("Content") ? true : false;
> String xencEncryptedDataId =
> wssConfig.getIdAllocator().createId("EncDataId-", element);
> encPart.setEncId(xencEncryptedDataId);
>
> boolean cloneKeyInfo = true;
>
> if (keyInfo == null) {
> keyInfo = new KeyInfo(document);
> SecurityTokenReference secToken = new SecurityTokenReference(document);
> Reference ref = new Reference(document);
> if (encKeyIdDirectId) {
> ref.setURI(encKeyId);
> } else {
> ref.setURI("#" + encKeyId);
> }
> if (encKeyValueType != null) {
> ref.setValueType(encKeyValueType);
> }
> secToken.setReference(ref);
> keyInfo.addUnknownElement(secToken.getElement());
> Element keyInfoElement = keyInfo.getElement();
> keyInfoElement.setAttributeNS(
> WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX,
WSConstants.SIG_NS
> );
> }
> //
> // Fourth step: encrypt data, and set necessary attributes in
> // xenc:EncryptedData
> //
> try {
> if (modifier.equals("Header")) {
>
> Element elem =
> doc.createElementNS(
> WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
> );
> WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
> WSConstants.WSSE11_PREFIX);
> String wsuPrefix =
> WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
> WSConstants.WSU_PREFIX);
> elem.setAttributeNS(
> WSConstants.WSU_NS, wsuPrefix + ":Id",
> wssConfig.getIdAllocator().createId("EncHeader-", element)
> );
>
> NamedNodeMap map = element.getAttributes();
>
> for (int i = 0 ; i < map.getLength() ; i++) {
> Attr attr = (Attr)map.item(i);
> if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
> || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {
> String soapEnvPrefix =
> WSSecurityUtil.setNamespace(
> elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
> );
> elem.setAttributeNS(
> attr.getNamespaceURI(),
> soapEnvPrefix + ":" + attr.getLocalName(),
> attr.getValue()
> );
> }
> }
>
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
>
> Element encDataElem =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), xencEncryptedDataId, null
> );
> Node clone = encDataElem.cloneNode(true);
> elem.appendChild(clone);
> encDataElem.getParentNode().appendChild(elem);
> encDataElem.getParentNode().removeChild(encDataElem);
> } else {
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> }
> if (cloneKeyInfo) {
> keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true),
null);
> }
> } catch (Exception e2) {
> throw new WSSecurityException(
> WSSecurityException.FAILED_ENCRYPTION, null, null, e2
> );
> }
> return xencEncryptedDataId;
>
> }
> ---
>
>
> I've just extraced the part of the old method responsible for the
> encryption/marking of one Element and I call it for all found parts.
> Perheadps you can discuss this modification and biuld it in one of the
next
> version - should it be approved.
>
> And there is one more suggestion - the class "WSEncryptionPart"... Since
> wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The
lookup
> is done only by the namespaceURI and local name. Perheaps it will be used
in
> one of the future versions. But - what if the namespace/local name does
not
> correspond to the XPath? And if we have the XPath then we can use only
it,
> and forget the namespace/local name.
> So it would be nice, if the class WSEncryptionPart would have all the
> currently used constructors, and beside this new one with the XPath.
> Something like this:
> ---
> //old ones:
> WSEncryptionPart(String id)
> WSEncryptionPart(String id, String encMod)
> WSEncryptionPart(String id, String encMod,int type)
> WSEncryptionPart(String nm, String nmspace, String encMod)
> WSEncryptionPart(String nm, String nmspace, String encMod, int type)
>
> //new ones:
> WSEncryptionPart(String xPath, String encMod)
> WSEncryptionPart(String xPath, String encMod, int type)
> ---
> and the newly added methods for setting and getting the xpath can be
> deleted.
> The search for the given element in the document can be then done by
xpath
> _or_ the old way, depending on the parameter set.
>
>
>
> Greetings,
>
> Marcin Markiewicz
>
>
>
>
----------------------------------------------------------------------------------------------------------------------------------------------

>
> Fiducia IT AG
> Fiduciastraße 20
> 76227 Karlsruhe
>
> Sitz der Gesellschaft: Karlsruhe
> AG Mannheim HRB 100059
>
> Vorsitzender des Aufsichtsrats: Gregor Scheller
> Vorsitzender des Vorstands: Michael Krings
> Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
> Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger
>
> Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
>
----------------------------------------------------------------------------------------------------------------------------------------------

>





----------------------------------------------------------------------------------------------------------------------------------------------


Fiducia IT AG
Fiduciastraße 20
76227 Karlsruhe

Sitz der Gesellschaft: Karlsruhe
AG Mannheim HRB 100059

Vorsitzender des Aufsichtsrats: Gregor Scheller
Vorsitzender des Vorstands: Michael Krings
Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger

Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
----------------------------------------------------------------------------------------------------------------------------------------------

Antwort: Fwd: possible bug in the class "WSSecEncrypt"

Posted by Ma...@fiducia.de.
Hi,

in pleased that you see this as a bug too. I will create this two (or maybe
four - i haven't looked at the signature parts yet but I think there ist
the same problem present) JIRA issues.
I have thought about the solusion and found two candidates:
1) just as described in your mail - new constructor an changest in the
Util-class. It is a minimal, backward compatible solution and should work.
2) kid of tricky. No we constructors for the WSEncryptionPart, but a new
one class - WSEncryptionPartXPath and a new Interface - IWSEncyrpytionPart
defining just one method - boolean processNode(Node node)...
  Both classes (WSEncryptionPart and WSEncryptionPartXPath ) will implement
this new interface. The Util class will then use this new method for
searching for the described elements (here I thing about a recursive
algorithm not using the NodeList). The advantage of this solution is, that
we can add another WSEncryptioPartXYZ classes describing the elements in
their way, but do not have to change the inmplementation of the util class
anymore.

What do you think abut it? I prefer the second solution.

Greetings
Marcin Markiewicz



Von:	Colm O hEigeartaigh <co...@apache.org>
An:	Marcin.Markiewicz@fiducia.de
Datum:	24.11.2010 15:18
Betreff:	Fwd: possible bug in the class "WSSecEncrypt"



(In case you are not subscribe to dev@ws.apache.org - please direct
all future WSS4J queries to this list).

Colm.


---------- Forwarded message ----------
From: Colm O hEigeartaigh <co...@apache.org>
Date: Wed, Nov 24, 2010 at 2:16 PM
Subject: Re: possible bug in the class "WSSecEncrypt"
To: dev@ws.apache.org


Hi Marcin,

1) Yes that looks like a bug. Please create a JIRA
(https://issues.apache.org/jira/browse/WSS) and attach a patch for
this issue. Please note that NodeLists are not thread-safe, and are to
be avoided in WSS4J.

2) XPath is only used on the inbound side to refer to an element that
has been processed. I agree that it would be useful to support this
feature on the outbound side. The current API's used in
WSEncryptionPart cannot be changed for backwards compatibility
reasons. Another constructor could be added to support setting the
XPath. Some functionality would then have to be added to
WSSecurityUtil to
find a set of elements matching the XPath expression. You could add a
new JIRA for this as well if you want.

Thanks,

Colm.

On Wed, Nov 24, 2010 at 12:39 PM,  <Ma...@fiducia.de> wrote:
> Hallo team,
>
> it's my first post for this project, and the first one for an open source
> project as well. Thus i kindly pleas to excuse my mistakes, should i have
> done some.
>
> I'm currently developing an web service framework for the Fiducia,
germany
> (huge Java banking project). My current task is to encrypt some parts of
the
> SOAP-Headers, containing attachments.
>
> The structure of the SOAP-Message is like this:
> ---
> <xml...>
> <soapenv:Envelope>
> <soapenv:Header>
> <myNS:Header1>
> <!-- XML data-->
> </myNS:Header1>
> <myNS:Header2>
> <!-- XML data-->
> </myNS:Header2>
> ...
> <myNS:Attachments>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> ...
> </myNS:Attachments>
> ...
> <myNS:HeaderX>
> <!-- XML data-->
> </myNS:HeaderX>
> </soapenv:Header>
> <soapenv:Body>
> <!-- XML data-->
> </soapenv:Body>
> </soapenv:Envelope>
> ---
>
> The attachments will be extracted later in their own MIME multipart
parts,
> using MTOM.
> My problem is now, that i cannot encrypt the attachments separately from
> each other. I can encrypt the whole Attachments-header using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> But if I want to encrypt the attachment-elements separately using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> then only the firs one will be encrypted. The others will not.
>
> I have quickly analysed the class
> org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495
and
> following, especially the one with:
> ---
> body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
> ---
> Well, this line finds only one (the first one) element with the given
name,
> and not all of them. Then I implemented some work aound - not pretty, but
> working - and now this class canencrypt all the elements with the given
> name.
> here is the modified method:
> ---
> private Vector doEncryption(
> Document doc,
> SecretKey secretKey,
> KeyInfo keyInfo,
> Vector references
> ) throws WSSecurityException {
>
> XMLCipher xmlCipher = null;
> try {
> xmlCipher = XMLCipher.getInstance(symEncAlgo);
> } catch (XMLEncryptionException e3) {
> throw new WSSecurityException(
> WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
> );
> }
>
> Vector encDataRef = new Vector();
>
> boolean cloneKeyInfo = false;
> for (int part = 0; part < references.size(); part++) {
> WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
>
> String idToEnc = encPart.getId();
> String elemName = encPart.getName();
> String nmSpace = encPart.getNamespace();
> String modifier = encPart.getEncModifier();
> //
> // Third step: get the data to encrypt.
> //
> //Element body = null;
> if (idToEnc != null) {
> Element element =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), idToEnc, WSConstants.WSU_NS
> );
> if (element == null) {
> element =
> WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc,
> null);
> }
> if (element == null) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> String encRef = encryptPart(document, encPart, element, keyInfo,
xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> } else {
> NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);
> if(elements == null || elements.getLength() <= 0) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> for(int i = 0; i < elements.getLength(); i++) {
> Element element = (Element)elements.item(i);
> String encRef = encryptPart(document, encPart, element, keyInfo,
xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> }
> }
> }
> return encDataRef;
> }
> ---
>
> and here is the ne private method used by the modified one:
> ---
> private String encryptPart(Document doc, WSEncryptionPart encPart,
Element
> element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey )
throws
> WSSecurityException
> {
> Vector encDataRef = new Vector();
>
> String modifier = encPart.getEncModifier();
>
> boolean content = modifier.equals("Content") ? true : false;
> String xencEncryptedDataId =
> wssConfig.getIdAllocator().createId("EncDataId-", element);
> encPart.setEncId(xencEncryptedDataId);
>
> boolean cloneKeyInfo = true;
>
> if (keyInfo == null) {
> keyInfo = new KeyInfo(document);
> SecurityTokenReference secToken = new SecurityTokenReference(document);
> Reference ref = new Reference(document);
> if (encKeyIdDirectId) {
> ref.setURI(encKeyId);
> } else {
> ref.setURI("#" + encKeyId);
> }
> if (encKeyValueType != null) {
> ref.setValueType(encKeyValueType);
> }
> secToken.setReference(ref);
> keyInfo.addUnknownElement(secToken.getElement());
> Element keyInfoElement = keyInfo.getElement();
> keyInfoElement.setAttributeNS(
> WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX,
WSConstants.SIG_NS
> );
> }
> //
> // Fourth step: encrypt data, and set necessary attributes in
> // xenc:EncryptedData
> //
> try {
> if (modifier.equals("Header")) {
>
> Element elem =
> doc.createElementNS(
> WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
> );
> WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
> WSConstants.WSSE11_PREFIX);
> String wsuPrefix =
> WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
> WSConstants.WSU_PREFIX);
> elem.setAttributeNS(
> WSConstants.WSU_NS, wsuPrefix + ":Id",
> wssConfig.getIdAllocator().createId("EncHeader-", element)
> );
>
> NamedNodeMap map = element.getAttributes();
>
> for (int i = 0 ; i < map.getLength() ; i++) {
> Attr attr = (Attr)map.item(i);
> if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
> || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {
> String soapEnvPrefix =
> WSSecurityUtil.setNamespace(
> elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
> );
> elem.setAttributeNS(
> attr.getNamespaceURI(),
> soapEnvPrefix + ":" + attr.getLocalName(),
> attr.getValue()
> );
> }
> }
>
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
>
> Element encDataElem =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), xencEncryptedDataId, null
> );
> Node clone = encDataElem.cloneNode(true);
> elem.appendChild(clone);
> encDataElem.getParentNode().appendChild(elem);
> encDataElem.getParentNode().removeChild(encDataElem);
> } else {
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> }
> if (cloneKeyInfo) {
> keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true),
null);
> }
> } catch (Exception e2) {
> throw new WSSecurityException(
> WSSecurityException.FAILED_ENCRYPTION, null, null, e2
> );
> }
> return xencEncryptedDataId;
>
> }
> ---
>
>
> I've just extraced the part of the old method responsible for the
> encryption/marking of one Element and I call it for all found parts.
> Perheadps you can discuss this modification and biuld it in one of the
next
> version - should it be approved.
>
> And there is one more suggestion - the class "WSEncryptionPart"... Since
> wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The
lookup
> is done only by the namespaceURI and local name. Perheaps it will be used
in
> one of the future versions. But - what if the namespace/local name does
not
> correspond to the XPath? And if we have the XPath then we can use only
it,
> and forget the namespace/local name.
> So it would be nice, if the class WSEncryptionPart would have all the
> currently used constructors, and beside this new one with the XPath.
> Something like this:
> ---
> //old ones:
> WSEncryptionPart(String id)
> WSEncryptionPart(String id, String encMod)
> WSEncryptionPart(String id, String encMod,int type)
> WSEncryptionPart(String nm, String nmspace, String encMod)
> WSEncryptionPart(String nm, String nmspace, String encMod, int type)
>
> //new ones:
> WSEncryptionPart(String xPath, String encMod)
> WSEncryptionPart(String xPath, String encMod, int type)
> ---
> and the newly added methods for setting and getting the xpath can be
> deleted.
> The search for the given element in the document can be then done by
xpath
> _or_ the old way, depending on the parameter set.
>
>
>
> Greetings,
>
> Marcin Markiewicz
>
>
>
>
----------------------------------------------------------------------------------------------------------------------------------------------

>
> Fiducia IT AG
> Fiduciastraße 20
> 76227 Karlsruhe
>
> Sitz der Gesellschaft: Karlsruhe
> AG Mannheim HRB 100059
>
> Vorsitzender des Aufsichtsrats: Gregor Scheller
> Vorsitzender des Vorstands: Michael Krings
> Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
> Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger
>
> Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
>
----------------------------------------------------------------------------------------------------------------------------------------------

>





----------------------------------------------------------------------------------------------------------------------------------------------


Fiducia IT AG
Fiduciastraße 20
76227 Karlsruhe

Sitz der Gesellschaft: Karlsruhe
AG Mannheim HRB 100059

Vorsitzender des Aufsichtsrats: Gregor Scheller
Vorsitzender des Vorstands: Michael Krings
Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger

Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
----------------------------------------------------------------------------------------------------------------------------------------------

Re: possible bug in the class "WSSecEncrypt"

Posted by Colm O hEigeartaigh <co...@apache.org>.
Hi Marcin,

1) Yes that looks like a bug. Please create a JIRA
(https://issues.apache.org/jira/browse/WSS) and attach a patch for
this issue. Please note that NodeLists are not thread-safe, and are to
be avoided in WSS4J.

2) XPath is only used on the inbound side to refer to an element that
has been processed. I agree that it would be useful to support this
feature on the outbound side. The current API's used in
WSEncryptionPart cannot be changed for backwards compatibility
reasons. Another constructor could be added to support setting the
XPath. Some functionality would then have to be added to
WSSecurityUtil to
find a set of elements matching the XPath expression. You could add a
new JIRA for this as well if you want.

Thanks,

Colm.

On Wed, Nov 24, 2010 at 12:39 PM,  <Ma...@fiducia.de> wrote:
> Hallo team,
>
> it's my first post for this project, and the first one for an open source
> project as well. Thus i kindly pleas to excuse my mistakes, should i have
> done some.
>
> I'm currently developing an web service framework for the Fiducia, germany
> (huge Java banking project). My current task is to encrypt some parts of the
> SOAP-Headers, containing attachments.
>
> The structure of the SOAP-Message is like this:
> ---
> <xml...>
> <soapenv:Envelope>
> <soapenv:Header>
> <myNS:Header1>
> <!-- XML data-->
> </myNS:Header1>
> <myNS:Header2>
> <!-- XML data-->
> </myNS:Header2>
> ...
> <myNS:Attachments>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> <myNS:attachment>
> <!-- binary data base64 encoded -->
> </myNS:attachment>
> ...
> </myNS:Attachments>
> ...
> <myNS:HeaderX>
> <!-- XML data-->
> </myNS:HeaderX>
> </soapenv:Header>
> <soapenv:Body>
> <!-- XML data-->
> </soapenv:Body>
> </soapenv:Envelope>
> ---
>
> The attachments will be extracted later in their own MIME multipart parts,
> using MTOM.
> My problem is now, that i cannot encrypt the attachments separately from
> each other. I can encrypt the whole Attachments-header using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("Attachments",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> But if I want to encrypt the attachment-elements separately using:
> ---
> WSEncryptionPartencryptionPart = new WSEncryptionPart("attachment",
> "myNS-URI", "Content");
> encryptionParts.add(encryptionPart);
> ---
> then only the firs one will be encrypted. The others will not.
>
> I have quickly analysed the class
> org.apache.ws.security.message.WSSecEncrypt, an found the code lines 495 and
> following, especially the one with:
> ---
> body = (Element) WSSecurityUtil.findElement(document, elemName, nmSpace);
> ---
> Well, this line finds only one (the first one) element with the given name,
> and not all of them. Then I implemented some work aound - not pretty, but
> working - and now this class canencrypt all the elements with the given
> name.
> here is the modified method:
> ---
> private Vector doEncryption(
> Document doc,
> SecretKey secretKey,
> KeyInfo keyInfo,
> Vector references
> ) throws WSSecurityException {
>
> XMLCipher xmlCipher = null;
> try {
> xmlCipher = XMLCipher.getInstance(symEncAlgo);
> } catch (XMLEncryptionException e3) {
> throw new WSSecurityException(
> WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3
> );
> }
>
> Vector encDataRef = new Vector();
>
> boolean cloneKeyInfo = false;
> for (int part = 0; part < references.size(); part++) {
> WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
>
> String idToEnc = encPart.getId();
> String elemName = encPart.getName();
> String nmSpace = encPart.getNamespace();
> String modifier = encPart.getEncModifier();
> //
> // Third step: get the data to encrypt.
> //
> //Element body = null;
> if (idToEnc != null) {
> Element element =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), idToEnc, WSConstants.WSU_NS
> );
> if (element == null) {
> element =
> WSSecurityUtil.findElementById(document.getDocumentElement(), idToEnc,
> null);
> }
> if (element == null) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> } else {
> NodeList elements = document.getElementsByTagNameNS(nmSpace, elemName);
> if(elements == null || elements.getLength() <= 0) {
> throw new WSSecurityException(
> WSSecurityException.FAILURE,
> "noEncElement",
> new Object[] {"{" + nmSpace + "}" + elemName}
> );
> }
> for(int i = 0; i < elements.getLength(); i++) {
> Element element = (Element)elements.item(i);
> String encRef = encryptPart(document, encPart, element, keyInfo, xmlCipher,
> secretKey);
> encDataRef.add(encRef);
> }
> }
> }
> return encDataRef;
> }
> ---
>
> and here is the ne private method used by the modified one:
> ---
> private String encryptPart(Document doc, WSEncryptionPart encPart, Element
> element, KeyInfo keyInfo, XMLCipher xmlCipher, SecretKey secretKey ) throws
> WSSecurityException
> {
> Vector encDataRef = new Vector();
>
> String modifier = encPart.getEncModifier();
>
> boolean content = modifier.equals("Content") ? true : false;
> String xencEncryptedDataId =
> wssConfig.getIdAllocator().createId("EncDataId-", element);
> encPart.setEncId(xencEncryptedDataId);
>
> boolean cloneKeyInfo = true;
>
> if (keyInfo == null) {
> keyInfo = new KeyInfo(document);
> SecurityTokenReference secToken = new SecurityTokenReference(document);
> Reference ref = new Reference(document);
> if (encKeyIdDirectId) {
> ref.setURI(encKeyId);
> } else {
> ref.setURI("#" + encKeyId);
> }
> if (encKeyValueType != null) {
> ref.setValueType(encKeyValueType);
> }
> secToken.setReference(ref);
> keyInfo.addUnknownElement(secToken.getElement());
> Element keyInfoElement = keyInfo.getElement();
> keyInfoElement.setAttributeNS(
> WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
> );
> }
> //
> // Fourth step: encrypt data, and set necessary attributes in
> // xenc:EncryptedData
> //
> try {
> if (modifier.equals("Header")) {
>
> Element elem =
> doc.createElementNS(
> WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER
> );
> WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS,
> WSConstants.WSSE11_PREFIX);
> String wsuPrefix =
> WSSecurityUtil.setNamespace(elem, WSConstants.WSU_NS,
> WSConstants.WSU_PREFIX);
> elem.setAttributeNS(
> WSConstants.WSU_NS, wsuPrefix + ":Id",
> wssConfig.getIdAllocator().createId("EncHeader-", element)
> );
>
> NamedNodeMap map = element.getAttributes();
>
> for (int i = 0 ; i < map.getLength() ; i++) {
> Attr attr = (Attr)map.item(i);
> if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
> || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {
> String soapEnvPrefix =
> WSSecurityUtil.setNamespace(
> elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX
> );
> elem.setAttributeNS(
> attr.getNamespaceURI(),
> soapEnvPrefix + ":" + attr.getLocalName(),
> attr.getValue()
> );
> }
> }
>
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
>
> Element encDataElem =
> WSSecurityUtil.findElementById(
> document.getDocumentElement(), xencEncryptedDataId, null
> );
> Node clone = encDataElem.cloneNode(true);
> elem.appendChild(clone);
> encDataElem.getParentNode().appendChild(elem);
> encDataElem.getParentNode().removeChild(encDataElem);
> } else {
> xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
> EncryptedData encData = xmlCipher.getEncryptedData();
> encData.setId(xencEncryptedDataId);
> encData.setKeyInfo(keyInfo);
> xmlCipher.doFinal(doc, element, content);
> }
> if (cloneKeyInfo) {
> keyInfo = new KeyInfo((Element) keyInfo.getElement().cloneNode(true), null);
> }
> } catch (Exception e2) {
> throw new WSSecurityException(
> WSSecurityException.FAILED_ENCRYPTION, null, null, e2
> );
> }
> return xencEncryptedDataId;
>
> }
> ---
>
>
> I've just extraced the part of the old method responsible for the
> encryption/marking of one Element and I call it for all found parts.
> Perheadps you can discuss this modification and biuld it in one of the next
> version - should it be approved.
>
> And there is one more suggestion - the class "WSEncryptionPart"... Since
> wss4j-1.5.8, or 1.5.9 you can set an XPath. But it is never used! The lookup
> is done only by the namespaceURI and local name. Perheaps it will be used in
> one of the future versions. But - what if the namespace/local name does not
> correspond to the XPath? And if we have the XPath then we can use only it,
> and forget the namespace/local name.
> So it would be nice, if the class WSEncryptionPart would have all the
> currently used constructors, and beside this new one with the XPath.
> Something like this:
> ---
> //old ones:
> WSEncryptionPart(String id)
> WSEncryptionPart(String id, String encMod)
> WSEncryptionPart(String id, String encMod,int type)
> WSEncryptionPart(String nm, String nmspace, String encMod)
> WSEncryptionPart(String nm, String nmspace, String encMod, int type)
>
> //new ones:
> WSEncryptionPart(String xPath, String encMod)
> WSEncryptionPart(String xPath, String encMod, int type)
> ---
> and the newly added methods for setting and getting the xpath can be
> deleted.
> The search for the given element in the document can be then done by xpath
> _or_ the old way, depending on the parameter set.
>
>
>
> Greetings,
>
> Marcin Markiewicz
>
>
>
> ----------------------------------------------------------------------------------------------------------------------------------------------
>
> Fiducia IT AG
> Fiduciastraße 20
> 76227 Karlsruhe
>
> Sitz der Gesellschaft: Karlsruhe
> AG Mannheim HRB 100059
>
> Vorsitzender des Aufsichtsrats: Gregor Scheller
> Vorsitzender des Vorstands: Michael Krings
> Stellv. Vorsitzender des Vorstands: Klaus-Peter Bruns
> Vorstand: Jens-Olaf Bartels, Hans-Peter Straberger
>
> Umsatzsteuer-ID.Nr. DE143582320, http://www.fiducia.de
> ----------------------------------------------------------------------------------------------------------------------------------------------
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ws.apache.org
For additional commands, e-mail: dev-help@ws.apache.org