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: [email protected]
CC: [email protected]
From: [email protected]
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 

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

Reply via email to