You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wss4j-dev@ws.apache.org by fa...@apache.org on 2008/04/11 19:28:46 UTC
svn commit: r647232 [1/4] - in /webservices/wss4j/trunk:
src/org/apache/ws/security/ src/org/apache/ws/security/message/
src/org/apache/ws/security/processor/ test/wssec/
Author: fadushin
Date: Fri Apr 11 10:28:39 2008
New Revision: 647232
URL: http://svn.apache.org/viewvc?rev=647232&view=rev
Log:
WSS-109 Error Handling improvements
* Applied Colm's error handling fixes
Note: In order to get this patch to work, I had to change a lot
of the files that were affected to use UNIX line ending conventions
(I am developing on a UNIX machine). Many files seem to have been
committed with Windows (CRLF) line endings, perhaps using a UNIX
subversion client.
Added:
webservices/wss4j/trunk/test/wssec/TestWSSecurityFaultCodes.java (with props)
Modified:
webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java
webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncryptedKey.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedDataProcessor.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/TimestampProcessor.java
webservices/wss4j/trunk/test/wssec/PackageTests.java
webservices/wss4j/trunk/test/wssec/TestWSSecurityNew14.java
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java Fri Apr 11 10:28:39 2008
@@ -428,7 +428,9 @@
public final static String WSC_SCT = "http://schemas.xmlsoap.org/ws/2005/02/sc/sct";
- // Fault codes defined in the WSS 1.0 spec under section 6, Error handling
+ //
+ // Fault codes defined in the WSS 1.1 spec under section 12, Error handling
+ //
/**
* An unsupported token was provided
@@ -464,6 +466,11 @@
* Referenced security token could not be retrieved
*/
public static final QName SECURITY_TOKEN_UNAVAILABLE = new QName (WSSE_NS, "SecurityTokenUnavailable");
+
+ /**
+ * The message has expired
+ */
+ public static final QName MESSAGE_EXPIRED = new QName (WSSE_NS, "MessageExpired");
/**
* Header type in <code>org.apache.ws.security.WSEncryptionPart</code>
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityException.java Fri Apr 11 10:28:39 2008
@@ -37,9 +37,18 @@
public static final int FAILED_AUTHENTICATION = 5;
public static final int FAILED_CHECK = 6;
public static final int SECURITY_TOKEN_UNAVAILABLE = 7;
- public static final int FAILED_ENC_DEC = 8;
- public static final int FAILED_SIGNATURE = 9;
+ public static final int MESSAGE_EXPIRED = 8;
+ public static final int FAILED_ENCRYPTION = 9;
+ public static final int FAILED_SIGNATURE = 10;
private static ResourceBundle resources;
+ /*
+ * This is an Integer -> QName map. Its function is to map the integer error codes
+ * given above to the QName fault codes as defined in the SOAP Message Security 1.1
+ * specification. A client application can simply call getFaultCode rather than do
+ * any parsing of the error code. Note that there are no mappings for "FAILURE",
+ * "FAILED_ENCRYPTION" and "FAILED_SIGNATURE" as these are not standard error messages.
+ */
+ private static final java.util.Map FAULT_CODE_MAP = new java.util.HashMap();
static {
try {
@@ -47,6 +56,39 @@
} catch (MissingResourceException e) {
throw new RuntimeException(e.getMessage());
}
+
+ FAULT_CODE_MAP.put(
+ new Integer(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN),
+ WSConstants.UNSUPPORTED_SECURITY_TOKEN
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(UNSUPPORTED_ALGORITHM),
+ WSConstants.UNSUPPORTED_ALGORITHM
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(INVALID_SECURITY),
+ WSConstants.INVALID_SECURITY
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(INVALID_SECURITY_TOKEN),
+ WSConstants.INVALID_SECURITY_TOKEN
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(FAILED_AUTHENTICATION),
+ WSConstants.FAILED_AUTHENTICATION
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(FAILED_CHECK),
+ WSConstants.FAILED_CHECK
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(SECURITY_TOKEN_UNAVAILABLE),
+ WSConstants.SECURITY_TOKEN_UNAVAILABLE
+ );
+ FAULT_CODE_MAP.put(
+ new Integer(MESSAGE_EXPIRED),
+ WSConstants.MESSAGE_EXPIRED
+ );
}
private int errorCode;
@@ -127,6 +169,20 @@
*/
public int getErrorCode() {
return this.errorCode;
+ }
+
+ /**
+ * Get the fault code QName for this associated error code.
+ * <p/>
+ *
+ * @return the fault code QName of this exception
+ */
+ public javax.xml.namespace.QName getFaultCode() {
+ Object ret = FAULT_CODE_MAP.get(new Integer(this.errorCode));
+ if (ret != null) {
+ return (javax.xml.namespace.QName)ret;
+ }
+ return null;
}
/**
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/errors.properties Fri Apr 11 10:28:39 2008
@@ -2,13 +2,14 @@
0 = General security error
1 = An unsupported token was provided
2 = An unsupported signature or encryption algorithm was used
-3 = An error was discovered processing the <wsse:Security> header.
+3 = An error was discovered processing the <wsse:Security> header
4 = An invalid security token was provided
5 = The security token could not be authenticated or authorized
-6 = The signature verification failed
-7 = Referenced security token could not be retrieved.
-8 = Cannot encrypt/decrypt data
-9 = Signature creation failed
+6 = The signature or decryption was invalid
+7 = Referenced security token could not be retrieved
+8 = The message has expired
+9 = Cannot encrypt data
+10 = Signature creation failed
## detailed error msgs
noToken = Reference \"{0}\"
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java Fri Apr 11 10:28:39 2008
@@ -353,7 +353,7 @@
try {
cipher.init(Cipher.ENCRYPT_MODE, remoteCert);
} catch (InvalidKeyException e) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e);
+ throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e);
}
byte[] encKey = this.encryptionKey.getEncoded();
if (doDebug) {
@@ -371,11 +371,11 @@
try {
encryptedKey = cipher.doFinal(encKey);
} catch (IllegalStateException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e1);
+ throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
} catch (IllegalBlockSizeException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e1);
+ throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
} catch (BadPaddingException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e1);
+ throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
}
Text keyText =
WSSecurityUtil.createBase64EncodedTextNode(doc, encryptedKey);
@@ -542,7 +542,7 @@
encData.setKeyInfo(keyInfo);
xmlCipher.doFinal(doc, body, content);
} catch (Exception e2) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC, null, null, e2);
+ throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
}
encDataRefs.add(new String("#" + xencEncryptedDataId));
}
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java Fri Apr 11 10:28:39 2008
@@ -1,248 +1,248 @@
-/*
- * Copyright 2003-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.ws.security.message;
-
-import org.apache.ws.security.SOAPConstants;
-import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSEncryptionPart;
-import org.apache.ws.security.WSSecurityException;
-import org.apache.ws.security.conversation.ConversationException;
-import org.apache.ws.security.message.token.Reference;
-import org.apache.ws.security.message.token.SecurityTokenReference;
-import org.apache.ws.security.util.WSSecurityUtil;
-import org.apache.xml.security.encryption.EncryptedData;
-import org.apache.xml.security.encryption.XMLCipher;
-import org.apache.xml.security.encryption.XMLEncryptionException;
-import org.apache.xml.security.keys.KeyInfo;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import javax.crypto.SecretKey;
-
-import java.util.Vector;
-
-/**
- * Encrypts and signs parts of a message with derived keys derived from a
- * symmetric key. This symmetric key will be included as an EncryptedKey
- *
- * @author Ruchith Fernando (ruchith.fernando@gmail.com)
- */
-public class WSSecDKEncrypt extends WSSecDerivedKeyBase {
-
- protected String symEncAlgo = WSConstants.AES_128;
-
- public Document build(Document doc, WSSecHeader secHeader)
- throws WSSecurityException, ConversationException {
-
- /*
- * Setup the encrypted key
- */
- prepare(doc);
-
- this.envelope = doc.getDocumentElement();
- /*
- * prepend elements in the right order to the security header
- */
- prependDKElementToHeader(secHeader);
-
- SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
- if (parts == null) {
- parts = new Vector();
- WSEncryptionPart encP = new WSEncryptionPart(soapConstants
- .getBodyQName().getLocalPart(), soapConstants
- .getEnvelopeURI(), "Content");
- parts.add(encP);
- }
- Element externRefList = encryptForExternalRef(null, parts);
- addExternalRefElement(externRefList, secHeader);
-
- return doc;
- }
-
- private Vector doEncryption(Document doc, byte[] secretKey, Vector references) throws WSSecurityException {
-
- SecretKey key = WSSecurityUtil.prepareSecretKey(this.symEncAlgo, secretKey);
-
-
- XMLCipher xmlCipher = null;
- try {
- xmlCipher = XMLCipher.getInstance(symEncAlgo);
- } catch (XMLEncryptionException e3) {
- throw new WSSecurityException(
- WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
- }
-
- Vector encDataRefs = new Vector();
-
- if(envelope == null) {
- envelope = doc.getDocumentElement();
- }
-
- 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) {
- body = WSSecurityUtil.findElementById(document
- .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
- if (body == null) {
- body = WSSecurityUtil.findElementById(document
- .getDocumentElement(), idToEnc, null);
- }
- } else {
- body = (Element) WSSecurityUtil.findElement(envelope, elemName,
- nmSpace);
- }
- if (body == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "noEncElement", new Object[] { "{" + nmSpace + "}"
- + elemName });
- }
-
- boolean content = modifier.equals("Content") ? true : false;
- String xencEncryptedDataId = "EncDataId-" + body.hashCode();
-
- /*
- * Forth step: encrypt data, and set necessary attributes in
- * xenc:EncryptedData
- */
- try {
- //Create the SecurityTokenRef to the DKT
- KeyInfo keyInfo = new KeyInfo(document);
- SecurityTokenReference secToken = new SecurityTokenReference(document);
- Reference ref = new Reference(document);
- ref.setURI("#" + dktId);
- secToken.setReference(ref);
-
- keyInfo.addUnknownElement(secToken.getElement());
-
- xmlCipher.init(XMLCipher.ENCRYPT_MODE, key);
- EncryptedData encData = xmlCipher.getEncryptedData();
- encData.setId(xencEncryptedDataId);
- encData.setKeyInfo(keyInfo);
- xmlCipher.doFinal(doc, body, content);
- } catch (Exception e2) {
- throw new WSSecurityException(
- WSSecurityException.FAILED_ENC_DEC, null, null, e2);
- }
- encDataRefs.add(new String("#" + xencEncryptedDataId));
- }
- return encDataRefs;
- }
-
- /**
- * Encrypt one or more parts or elements of the message (external).
- *
- * This method takes a vector of <code>WSEncryptionPart</code> object that
- * contain information about the elements to encrypt. The method call the
- * encryption method, takes the reference information generated during
- * encryption and add this to the <code>xenc:Reference</code> element.
- * This method can be called after <code>prepare()</code> and can be
- * called multiple times to encrypt a number of parts or elements.
- *
- * </p>
- *
- * The method generates a <code>xenc:Reference</code> element that <i>must</i>
- * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
- *
- * </p>
- *
- * If the <code>dataRef</code> parameter is <code>null</code> the method
- * creates and initializes a new Reference element.
- *
- * @param dataRef
- * A <code>xenc:Reference</code> element or <code>null</code>
- * @param references
- * A vector containing WSEncryptionPart objects
- * @return Returns the updated <code>xenc:Reference</code> element
- * @throws WSSecurityException
- */
- public Element encryptForExternalRef(Element dataRef, Vector references)
- throws WSSecurityException {
-
-
- Vector encDataRefs = doEncryption(document, derivedKeyBytes,
- references);
- Element referenceList = dataRef;
- if (referenceList == null) {
- referenceList = document.createElementNS(WSConstants.ENC_NS,
- WSConstants.ENC_PREFIX + ":ReferenceList");
- }
- createDataRefList(document, referenceList, encDataRefs);
- return referenceList;
- }
-
- /**
- * Adds (prepends) the external Reference element to the Security header.
- *
- * The reference element <i>must</i> be created by the
- * <code>encryptForExternalRef() </code> method. The method adds the
- * reference element in the SecurityHeader.
- *
- * @param dataRef
- * The external <code>enc:Reference</code> element
- * @param secHeader
- * The security header.
- */
- public void addExternalRefElement(Element referenceList, WSSecHeader secHeader) {
- Node node = dkt.getElement().getNextSibling();
- if(node == null || (node != null && !(node instanceof Element))) {
- //If (at this moment) DerivedKeyToken is the LAST element of
- //the security header
- secHeader.getSecurityHeader().appendChild(referenceList);
- } else {
- secHeader.getSecurityHeader().insertBefore(referenceList, node);
- }
-
- }
-
- public static Element createDataRefList(Document doc,
- Element referenceList, Vector encDataRefs) {
- for (int i = 0; i < encDataRefs.size(); i++) {
- String dataReferenceUri = (String) encDataRefs.get(i);
- Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
- WSConstants.ENC_PREFIX + ":DataReference");
- dataReference.setAttributeNS(null, "URI", dataReferenceUri);
- referenceList.appendChild(dataReference);
- }
- return referenceList;
- }
-
-
- public void setSymmetricEncAlgorithm(String algo) {
- symEncAlgo = algo;
- }
-
- /**
- * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
- */
- protected int getDerivedKeyLength() throws WSSecurityException{
- return (this.derivedKeyLength > 0) ? this.derivedKeyLength :
- WSSecurityUtil.getKeyLength(this.symEncAlgo);
- }
-
-}
+/*
+ * Copyright 2003-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.ws.security.message;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.crypto.SecretKey;
+
+import java.util.Vector;
+
+/**
+ * Encrypts and signs parts of a message with derived keys derived from a
+ * symmetric key. This symmetric key will be included as an EncryptedKey
+ *
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class WSSecDKEncrypt extends WSSecDerivedKeyBase {
+
+ protected String symEncAlgo = WSConstants.AES_128;
+
+ public Document build(Document doc, WSSecHeader secHeader)
+ throws WSSecurityException, ConversationException {
+
+ /*
+ * Setup the encrypted key
+ */
+ prepare(doc);
+
+ this.envelope = doc.getDocumentElement();
+ /*
+ * prepend elements in the right order to the security header
+ */
+ prependDKElementToHeader(secHeader);
+
+ SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+ if (parts == null) {
+ parts = new Vector();
+ WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+ .getBodyQName().getLocalPart(), soapConstants
+ .getEnvelopeURI(), "Content");
+ parts.add(encP);
+ }
+ Element externRefList = encryptForExternalRef(null, parts);
+ addExternalRefElement(externRefList, secHeader);
+
+ return doc;
+ }
+
+ private Vector doEncryption(Document doc, byte[] secretKey, Vector references) throws WSSecurityException {
+
+ SecretKey key = WSSecurityUtil.prepareSecretKey(this.symEncAlgo, secretKey);
+
+
+ XMLCipher xmlCipher = null;
+ try {
+ xmlCipher = XMLCipher.getInstance(symEncAlgo);
+ } catch (XMLEncryptionException e3) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
+ }
+
+ Vector encDataRefs = new Vector();
+
+ if(envelope == null) {
+ envelope = doc.getDocumentElement();
+ }
+
+ 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) {
+ body = WSSecurityUtil.findElementById(document
+ .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
+ if (body == null) {
+ body = WSSecurityUtil.findElementById(document
+ .getDocumentElement(), idToEnc, null);
+ }
+ } else {
+ body = (Element) WSSecurityUtil.findElement(envelope, elemName,
+ nmSpace);
+ }
+ if (body == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "noEncElement", new Object[] { "{" + nmSpace + "}"
+ + elemName });
+ }
+
+ boolean content = modifier.equals("Content") ? true : false;
+ String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+
+ /*
+ * Forth step: encrypt data, and set necessary attributes in
+ * xenc:EncryptedData
+ */
+ try {
+ //Create the SecurityTokenRef to the DKT
+ KeyInfo keyInfo = new KeyInfo(document);
+ SecurityTokenReference secToken = new SecurityTokenReference(document);
+ Reference ref = new Reference(document);
+ ref.setURI("#" + dktId);
+ secToken.setReference(ref);
+
+ keyInfo.addUnknownElement(secToken.getElement());
+
+ xmlCipher.init(XMLCipher.ENCRYPT_MODE, key);
+ EncryptedData encData = xmlCipher.getEncryptedData();
+ encData.setId(xencEncryptedDataId);
+ encData.setKeyInfo(keyInfo);
+ xmlCipher.doFinal(doc, body, content);
+ } catch (Exception e2) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+ }
+ encDataRefs.add(new String("#" + xencEncryptedDataId));
+ }
+ return encDataRefs;
+ }
+
+ /**
+ * Encrypt one or more parts or elements of the message (external).
+ *
+ * This method takes a vector of <code>WSEncryptionPart</code> object that
+ * contain information about the elements to encrypt. The method call the
+ * encryption method, takes the reference information generated during
+ * encryption and add this to the <code>xenc:Reference</code> element.
+ * This method can be called after <code>prepare()</code> and can be
+ * called multiple times to encrypt a number of parts or elements.
+ *
+ * </p>
+ *
+ * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+ * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
+ *
+ * </p>
+ *
+ * If the <code>dataRef</code> parameter is <code>null</code> the method
+ * creates and initializes a new Reference element.
+ *
+ * @param dataRef
+ * A <code>xenc:Reference</code> element or <code>null</code>
+ * @param references
+ * A vector containing WSEncryptionPart objects
+ * @return Returns the updated <code>xenc:Reference</code> element
+ * @throws WSSecurityException
+ */
+ public Element encryptForExternalRef(Element dataRef, Vector references)
+ throws WSSecurityException {
+
+
+ Vector encDataRefs = doEncryption(document, derivedKeyBytes,
+ references);
+ Element referenceList = dataRef;
+ if (referenceList == null) {
+ referenceList = document.createElementNS(WSConstants.ENC_NS,
+ WSConstants.ENC_PREFIX + ":ReferenceList");
+ }
+ createDataRefList(document, referenceList, encDataRefs);
+ return referenceList;
+ }
+
+ /**
+ * Adds (prepends) the external Reference element to the Security header.
+ *
+ * The reference element <i>must</i> be created by the
+ * <code>encryptForExternalRef() </code> method. The method adds the
+ * reference element in the SecurityHeader.
+ *
+ * @param dataRef
+ * The external <code>enc:Reference</code> element
+ * @param secHeader
+ * The security header.
+ */
+ public void addExternalRefElement(Element referenceList, WSSecHeader secHeader) {
+ Node node = dkt.getElement().getNextSibling();
+ if(node == null || (node != null && !(node instanceof Element))) {
+ //If (at this moment) DerivedKeyToken is the LAST element of
+ //the security header
+ secHeader.getSecurityHeader().appendChild(referenceList);
+ } else {
+ secHeader.getSecurityHeader().insertBefore(referenceList, node);
+ }
+
+ }
+
+ public static Element createDataRefList(Document doc,
+ Element referenceList, Vector encDataRefs) {
+ for (int i = 0; i < encDataRefs.size(); i++) {
+ String dataReferenceUri = (String) encDataRefs.get(i);
+ Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
+ WSConstants.ENC_PREFIX + ":DataReference");
+ dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+ referenceList.appendChild(dataReference);
+ }
+ return referenceList;
+ }
+
+
+ public void setSymmetricEncAlgorithm(String algo) {
+ symEncAlgo = algo;
+ }
+
+ /**
+ * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
+ */
+ protected int getDerivedKeyLength() throws WSSecurityException{
+ return (this.derivedKeyLength > 0) ? this.derivedKeyLength :
+ WSSecurityUtil.getKeyLength(this.symEncAlgo);
+ }
+
+}
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java?rev=647232&r1=647231&r2=647232&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java Fri Apr 11 10:28:39 2008
@@ -1,743 +1,743 @@
-/*
- * Copyright 2003-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.ws.security.message;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.ws.security.SOAPConstants;
-import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSEncryptionPart;
-import org.apache.ws.security.WSSecurityException;
-import org.apache.ws.security.components.crypto.Crypto;
-import org.apache.ws.security.message.token.Reference;
-import org.apache.ws.security.message.token.SecurityTokenReference;
-import org.apache.ws.security.util.Base64;
-import org.apache.ws.security.util.WSSecurityUtil;
-import org.apache.xml.security.encryption.EncryptedData;
-import org.apache.xml.security.encryption.XMLCipher;
-import org.apache.xml.security.encryption.XMLEncryptionException;
-import org.apache.xml.security.keys.KeyInfo;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.X509Certificate;
-import java.util.Vector;
-
-/**
- * Encrypts a parts of a message according to WS Specification, X509 profile,
- * and adds the encryption data.
- *
- * @author Davanum Srinivas (dims@yahoo.com).
- * @author Werner Dittmann (Werner.Dittmann@apache.org).
- */
-public class WSSecEncrypt extends WSSecEncryptedKey {
- private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
-
- private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
-
- protected String symEncAlgo = WSConstants.AES_128;
-
- protected String encCanonAlgo = null;
-
- protected byte[] embeddedKey = null;
-
- protected String embeddedKeyName = null;
-
- /**
- * Symmetric key used in the EncrytpedKey.
- */
- protected SecretKey symmetricKey = null;
-
- /**
- * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
- */
- protected SecurityTokenReference securityTokenReference = null;
-
- /**
- * Indicates whether to encrypt the symmetric key into an EncryptedKey
- * or not.
- */
- private boolean encryptSymmKey = true;
-
- /**
- * Custom reference value
- */
- private String customReferenceValue;
-
- /**
- * Constructor.
- */
- public WSSecEncrypt() {
- }
-
- /**
- * Sets the key to use during embedded encryption.
- *
- * <p/>
- *
- * @param key
- * to use during encryption. The key must fit the selected
- * symmetrical encryption algorithm
- */
- public void setKey(byte[] key) {
- this.embeddedKey = key;
- }
-
- /**
- * Sets the algorithm to encode the symmetric key.
- *
- * Default is the <code>WSConstants.KEYTRANSPORT_RSA15</code> algorithm.
- *
- * @param keyEnc
- * specifies the key encoding algorithm.
- * @see WSConstants#KEYTRANSPORT_RSA15
- * @see WSConstants#KEYTRANSPORT_RSAOEP
- */
- public void setKeyEnc(String keyEnc) {
- keyEncAlgo = keyEnc;
- }
-
- /**
- * Set the key name for EMBEDDED_KEYNAME
- *
- * @param embeddedKeyName
- */
- public void setEmbeddedKeyName(String embeddedKeyName) {
- this.embeddedKeyName = embeddedKeyName;
- }
-
- /**
- * Set the name of the symmetric encryption algorithm to use.
- *
- * This encryption algorithm is used to encrypt the data. If the algorithm
- * is not set then AES128 is used. Refer to WSConstants which algorithms are
- * supported.
- *
- * @param algo
- * Is the name of the encryption algorithm
- * @see WSConstants#TRIPLE_DES
- * @see WSConstants#AES_128
- * @see WSConstants#AES_192
- * @see WSConstants#AES_256
- */
- public void setSymmetricEncAlgorithm(String algo) {
- symEncAlgo = algo;
- }
-
- /**
- * Set the name of an optional canonicalization algorithm to use before
- * encryption.
- *
- * This c14n algorithm is used to serialize the data before encryption. If
- * the algorithm is not set then a standard serialization is used (provided
- * by XMLCipher, usually a XMLSerializer according to DOM 3 specification).
- *
- * @param algo
- * Is the name of the canonicalization algorithm
- */
- public void setEncCanonicalization(String algo) {
- encCanonAlgo = algo;
- }
-
- /**
- * Get the name of symmetric encryption algorithm to use.
- *
- * The name of the encryption algorithm to encrypt the data, i.e. the SOAP
- * Body. Refer to WSConstants which algorithms are supported.
- *
- * @return the name of the currently selected symmetric encryption algorithm
- * @see WSConstants#TRIPLE_DES
- * @see WSConstants#AES_128
- * @see WSConstants#AES_192
- * @see WSConstants#AES_256
- */
- public String getSymmetricEncAlgorithm() {
- return symEncAlgo;
- }
-
- /**
- * Initialize a WSSec Encrypt.
- *
- * The method prepares and initializes a WSSec Encrypt structure after the
- * relevant information was set. After preparation of the token references
- * can be added and encrypted.
- *
- * </p>
- *
- * This method does not add any element to the security header. This must be
- * done explicitly.
- *
- * @param doc
- * The SOAP envelope as <code>Document</code>
- * @param crypto
- * An instance of the Crypto API to handle keystore and
- * certificates
- * @throws WSSecurityException
- */
- public void prepare(Document doc, Crypto crypto) throws WSSecurityException {
-
- document = doc;
-
- /*
- * If no external key (symmetricalKey) was set generate an encryption
- * key (session key) for this Encrypt element. This key will be
- * encrypted using the public key of the receiver
- */
-
-
- if(this.ephemeralKey == null) {
- if (symmetricKey == null) {
- KeyGenerator keyGen = getKeyGenerator();
- this.symmetricKey = keyGen.generateKey();
- }
- this.ephemeralKey = this.symmetricKey.getEncoded();
- }
-
- if (this.symmetricKey == null) {
-
- this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
- this.ephemeralKey);
- }
-
- /*
- * Get the certificate that contains the public key for the public key
- * algorithm that will encrypt the generated symmetric (session) key.
- */
- if(this.encryptSymmKey) {
- X509Certificate remoteCert = null;
- if (useThisCert != null) {
- remoteCert = useThisCert;
- } else {
- X509Certificate[] certs = crypto.getCertificates(user);
- if (certs == null || certs.length <= 0) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidX509Data", new Object[] { "for Encryption" });
- }
- remoteCert = certs[0];
- }
- prepareInternal(this.ephemeralKey, remoteCert, crypto);
- }
- }
-
- /**
- * Builds the SOAP envelope with encrypted Body and adds encrypted key.
- *
- * This is a convenience method and for backward compatibility. The method
- * calls the single function methods in order to perform a <i>one shot
- * encryption</i>. This method is compatible with the build method of the
- * previous version with the exception of the additional WSSecHeader
- * parameter.
- *
- * @param doc
- * the SOAP envelope as <code>Document</code> with plain text
- * Body
- * @param crypto
- * an instance of the Crypto API to handle keystore and
- * Certificates
- * @param secHeader
- * the security header element to hold the encrypted key element.
- * @return the SOAP envelope with encrypted Body as <code>Document
- * </code>
- * @throws WSSecurityException
- */
- public Document build(Document doc, Crypto crypto, WSSecHeader secHeader)
- throws WSSecurityException {
- doDebug = log.isDebugEnabled();
-
- if (keyIdentifierType == WSConstants.EMBEDDED_KEYNAME
- || keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
- return buildEmbedded(doc, crypto, secHeader);
- }
-
- if (doDebug) {
- log.debug("Beginning Encryption...");
- }
-
- prepare(doc, crypto);
-
- SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
- if (parts == null) {
- parts = new Vector();
- WSEncryptionPart encP = new WSEncryptionPart(soapConstants
- .getBodyQName().getLocalPart(), soapConstants
- .getEnvelopeURI(), "Content");
- parts.add(encP);
- }
-
- Element refs = encryptForInternalRef(null, parts);
- addInternalRefElement(refs);
-
- prependToHeader(secHeader);
-
- if (bstToken != null) {
- prependBSTElementToHeader(secHeader);
- }
-
- log.debug("Encryption complete.");
- return doc;
- }
-
- /**
- * Encrypt one or more parts or elements of the message (internal).
- *
- * This method takes a vector of <code>WSEncryptionPart</code> object that
- * contain information about the elements to encrypt. The method call the
- * encryption method, takes the reference information generated during
- * encryption and add this to the <code>xenc:Reference</code> element.
- * This method can be called after <code>prepare()</code> and can be
- * called multiple times to encrypt a number of parts or elements.
- *
- * </p>
- *
- * The method generates a <code>xenc:Reference</code> element that <i>must</i>
- * be added to this token. See <code>addInternalRefElement()</code>.
- *
- * </p>
- *
- * If the <code>dataRef</code> parameter is <code>null</code> the method
- * creates and initializes a new Reference element.
- *
- * @param dataRef
- * A <code>xenc:Reference</code> element or <code>null</code>
- * @param references
- * A vector containing WSEncryptionPart objects
- * @return Returns the updated <code>xenc:Reference</code> element
- * @throws WSSecurityException
- */
- public Element encryptForInternalRef(Element dataRef, Vector references)
- throws WSSecurityException {
- Vector encDataRefs = doEncryption(document, this.symmetricKey,
- references);
- Element referenceList = dataRef;
- if (referenceList == null) {
- referenceList = document.createElementNS(WSConstants.ENC_NS,
- WSConstants.ENC_PREFIX + ":ReferenceList");
- }
- createDataRefList(document, referenceList, encDataRefs);
- return referenceList;
- }
-
- /**
- * Encrypt one or more parts or elements of the message (external).
- *
- * This method takes a vector of <code>WSEncryptionPart</code> object that
- * contain information about the elements to encrypt. The method call the
- * encryption method, takes the reference information generated during
- * encryption and add this to the <code>xenc:Reference</code> element.
- * This method can be called after <code>prepare()</code> and can be
- * called multiple times to encrypt a number of parts or elements.
- *
- * </p>
- *
- * The method generates a <code>xenc:Reference</code> element that <i>must</i>
- * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
- *
- * </p>
- *
- * If the <code>dataRef</code> parameter is <code>null</code> the method
- * creates and initializes a new Reference element.
- *
- * @param dataRef
- * A <code>xenc:Reference</code> element or <code>null</code>
- * @param references
- * A vector containing WSEncryptionPart objects
- * @return Returns the updated <code>xenc:Reference</code> element
- * @throws WSSecurityException
- */
- public Element encryptForExternalRef(Element dataRef, Vector references)
- throws WSSecurityException {
-
- Vector encDataRefs = doEncryption(document, this.symmetricKey,
- references);
- Element referenceList = dataRef;
- if (referenceList == null) {
- referenceList = document.createElementNS(WSConstants.ENC_NS,
- WSConstants.ENC_PREFIX + ":ReferenceList");
- }
- createDataRefList(document, referenceList, encDataRefs);
- return referenceList;
- }
-
- /**
- * Adds the internal Reference element to this Encrypt data.
- *
- * The reference element <i>must</i> be created by the
- * <code>encryptForInternalRef()</code> method. The reference element is
- * added to the <code>EncryptedKey</code> element of this encrypt block.
- *
- * @param dataRef
- * The internal <code>enc:Reference</code> element
- */
- public void addInternalRefElement(Element dataRef) {
- WSSecurityUtil.appendChildElement(document, encryptedKeyElement, dataRef);
- }
-
- /**
- * Adds (prepends) the external Reference element to the Security header.
- *
- * The reference element <i>must</i> be created by the
- * <code>encryptForExternalRef() </code> method. The method prepends the
- * reference element in the SecurityHeader.
- *
- * @param dataRef
- * The external <code>enc:Reference</code> element
- * @param secHeader
- * The security header.
- */
- public void addExternalRefElement(Element dataRef, WSSecHeader secHeader) {
- WSSecurityUtil.prependChildElement(document, secHeader
- .getSecurityHeader(), dataRef, false);
- }
-
- private Vector doEncryption(Document doc, SecretKey secretKey,
- Vector references) throws WSSecurityException {
-
- KeyInfo keyInfo = null;
-
- // Prepare KeyInfo if useKeyIdentifier is set
- if (keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
- keyInfo = new KeyInfo(document);
- SecurityTokenReference secToken = new SecurityTokenReference(document);
- if(this.customReferenceValue != null) {
- secToken.setKeyIdentifierEncKeySHA1(this.customReferenceValue);
- } else {
- secToken.setKeyIdentifierEncKeySHA1(getSHA1(encryptedEphemeralKey));
- }
-
-
- keyInfo.addUnknownElement(secToken.getElement());
- }
-
- return doEncryption(doc, secretKey, keyInfo, references);
- }
-
- 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) {
- body = WSSecurityUtil.findElementById(document
- .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
- if (body == null) {
- body = WSSecurityUtil.findElementById(document
- .getDocumentElement(), idToEnc, null);
- }
- } else {
- body = (Element) WSSecurityUtil.findElement(document, elemName,
- nmSpace);
- }
- if (body == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "noEncElement", new Object[] { "{" + nmSpace + "}"
- + elemName });
- }
-
- boolean content = modifier.equals("Content") ? true : false;
- String xencEncryptedDataId = "EncDataId-" + body.hashCode();
- encPart.setEncId(xencEncryptedDataId);
-
- cloneKeyInfo = true;
-
- if(keyInfo == null) {
- keyInfo = new KeyInfo(document);
- SecurityTokenReference secToken = new SecurityTokenReference(document);
- Reference ref = new Reference(document);
- ref.setURI("#" + encKeyId);
- secToken.setReference(ref);
- keyInfo.addUnknownElement(secToken.getElement());
- }
- /*
- * Forth 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", "EncHeader-" + body.hashCode());
-
-
- NamedNodeMap map = body.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(), "soapevn");
- 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, body, 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, body, content);
- }
- if(cloneKeyInfo) {
- keyInfo = new KeyInfo((Element) keyInfo.getElement()
- .cloneNode(true), null);
- }
- } catch (Exception e2) {
- throw new WSSecurityException(
- WSSecurityException.FAILED_ENC_DEC, null, null, e2);
- }
- encDataRef.add(new String("#" + xencEncryptedDataId));
- }
- return encDataRef;
- }
-
- private Document buildEmbedded(Document doc, Crypto crypto,
- WSSecHeader secHeader) throws WSSecurityException {
- doDebug = log.isDebugEnabled();
-
- if (doDebug) {
- log.debug("Beginning Encryption embedded...");
- }
- envelope = doc.getDocumentElement();
- envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
- + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
-
- /*
- * Second step: generate a symmetric key from the specified key
- * (password) for this algorithm, and set the cipher into encryption
- * mode.
- */
- if (this.symmetricKey == null) {
- if (embeddedKey == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "noKeySupplied");
- }
- this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
- embeddedKey);
- }
-
- KeyInfo keyInfo = null;
- if (this.keyIdentifierType == WSConstants.EMBEDDED_KEYNAME) {
- keyInfo = new KeyInfo(doc);
- keyInfo
- .addKeyName(embeddedKeyName == null ? user
- : embeddedKeyName);
- } else if (this.keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
- /*
- * This means that we want to embed a <wsse:SecurityTokenReference>
- * into keyInfo element. If we need this functionality, this.secRef
- * MUST be set before calling the build(doc, crypto) method. So if
- * secRef is null then throw an exception.
- */
- if (this.securityTokenReference == null) {
- throw new WSSecurityException(
- WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
- "You must set keyInfo element, if the keyIdentifier "
- + "== EMBED_SECURITY_TOKEN_REF");
- } else {
- keyInfo = new KeyInfo(doc);
- Element tmpE = securityTokenReference.getElement();
- tmpE.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
- + tmpE.getPrefix(), tmpE.getNamespaceURI());
- keyInfo.addUnknownElement(securityTokenReference.getElement());
- }
- }
-
- SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
- if (parts == null) {
- parts = new Vector();
- WSEncryptionPart encP = new WSEncryptionPart(soapConstants
- .getBodyQName().getLocalPart(), soapConstants
- .getEnvelopeURI(), "Content");
- parts.add(encP);
- }
- Vector encDataRefs = doEncryption(doc, this.symmetricKey, keyInfo,
- parts);
-
- /*
- * At this point data is encrypted with the symmetric key and can be
- * referenced via the above Id
- */
-
- /*
- * Now we need to setup the wsse:Security header block 1) get (or
- * create) the wsse:Security header block 2) The last step sets up the
- * reference list that pints to the encrypted data
- */
- Element wsseSecurity = secHeader.getSecurityHeader();
-
- Element referenceList = doc.createElementNS(WSConstants.ENC_NS,
- WSConstants.ENC_PREFIX + ":ReferenceList");
- referenceList = createDataRefList(doc, referenceList, encDataRefs);
- WSSecurityUtil.prependChildElement(doc, wsseSecurity, referenceList,
- true);
-
- return doc;
- }
-
- private KeyGenerator getKeyGenerator() throws WSSecurityException {
- KeyGenerator keyGen = null;
- try {
- /*
- * Assume AES as default, so initialize it
- */
- keyGen = KeyGenerator.getInstance("AES");
- if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
- keyGen = KeyGenerator.getInstance("DESede");
- } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
- keyGen.init(128);
- } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
- keyGen.init(192);
- } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
- keyGen.init(256);
- } else {
- return null;
- }
- } catch (NoSuchAlgorithmException e) {
- throw new WSSecurityException(
- WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
- }
- return keyGen;
- }
-
- /**
- * Create DOM subtree for <code>xenc:EncryptedKey</code>
- *
- * @param doc
- * the SOAP envelope parent document
- * @param keyTransportAlgo
- * specifies which algorithm to use to encrypt the symmetric key
- * @return an <code>xenc:EncryptedKey</code> element
- */
-
- public static Element createDataRefList(Document doc,
- Element referenceList, Vector encDataRefs) {
- for (int i = 0; i < encDataRefs.size(); i++) {
- String dataReferenceUri = (String) encDataRefs.get(i);
- Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
- WSConstants.ENC_PREFIX + ":DataReference");
- dataReference.setAttributeNS(null, "URI", dataReferenceUri);
- referenceList.appendChild(dataReference);
- }
- return referenceList;
- }
-
- /**
- * @return The symmetric key
- */
- public SecretKey getSymmetricKey() {
- return symmetricKey;
- }
-
- /**
- * Set the symmetric key to be used for encryption
- *
- * @param key
- */
- public void setSymmetricKey(SecretKey key) {
- this.symmetricKey = key;
- }
-
- /**
- * @return Return the SecurityTokenRefernce
- */
- public SecurityTokenReference getSecurityTokenReference() {
- return securityTokenReference;
- }
-
- /**
- * @param reference
- */
- public void setSecurityTokenReference(SecurityTokenReference reference) {
- securityTokenReference = reference;
- }
-
- public boolean isEncryptSymmKey() {
- return encryptSymmKey;
- }
-
- public void setEncryptSymmKey(boolean encryptSymmKey) {
- this.encryptSymmKey = encryptSymmKey;
- }
-
- private String getSHA1(byte[] input) throws WSSecurityException {
- try {
- MessageDigest sha = null;
- sha = MessageDigest.getInstance("SHA-1");
- sha.reset();
- sha.update(input);
- byte[] data = sha.digest();
-
- return Base64.encode(data);
- } catch (NoSuchAlgorithmException e) {
- throw new WSSecurityException(
- WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
- }
- }
-
- public void setCustomReferenceValue(String customReferenceValue) {
- this.customReferenceValue = customReferenceValue;
- }
-
-}
+/*
+ * Copyright 2003-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Vector;
+
+/**
+ * Encrypts a parts of a message according to WS Specification, X509 profile,
+ * and adds the encryption data.
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@apache.org).
+ */
+public class WSSecEncrypt extends WSSecEncryptedKey {
+ private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
+
+ private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+
+ protected String symEncAlgo = WSConstants.AES_128;
+
+ protected String encCanonAlgo = null;
+
+ protected byte[] embeddedKey = null;
+
+ protected String embeddedKeyName = null;
+
+ /**
+ * Symmetric key used in the EncrytpedKey.
+ */
+ protected SecretKey symmetricKey = null;
+
+ /**
+ * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
+ */
+ protected SecurityTokenReference securityTokenReference = null;
+
+ /**
+ * Indicates whether to encrypt the symmetric key into an EncryptedKey
+ * or not.
+ */
+ private boolean encryptSymmKey = true;
+
+ /**
+ * Custom reference value
+ */
+ private String customReferenceValue;
+
+ /**
+ * Constructor.
+ */
+ public WSSecEncrypt() {
+ }
+
+ /**
+ * Sets the key to use during embedded encryption.
+ *
+ * <p/>
+ *
+ * @param key
+ * to use during encryption. The key must fit the selected
+ * symmetrical encryption algorithm
+ */
+ public void setKey(byte[] key) {
+ this.embeddedKey = key;
+ }
+
+ /**
+ * Sets the algorithm to encode the symmetric key.
+ *
+ * Default is the <code>WSConstants.KEYTRANSPORT_RSA15</code> algorithm.
+ *
+ * @param keyEnc
+ * specifies the key encoding algorithm.
+ * @see WSConstants#KEYTRANSPORT_RSA15
+ * @see WSConstants#KEYTRANSPORT_RSAOEP
+ */
+ public void setKeyEnc(String keyEnc) {
+ keyEncAlgo = keyEnc;
+ }
+
+ /**
+ * Set the key name for EMBEDDED_KEYNAME
+ *
+ * @param embeddedKeyName
+ */
+ public void setEmbeddedKeyName(String embeddedKeyName) {
+ this.embeddedKeyName = embeddedKeyName;
+ }
+
+ /**
+ * Set the name of the symmetric encryption algorithm to use.
+ *
+ * This encryption algorithm is used to encrypt the data. If the algorithm
+ * is not set then AES128 is used. Refer to WSConstants which algorithms are
+ * supported.
+ *
+ * @param algo
+ * Is the name of the encryption algorithm
+ * @see WSConstants#TRIPLE_DES
+ * @see WSConstants#AES_128
+ * @see WSConstants#AES_192
+ * @see WSConstants#AES_256
+ */
+ public void setSymmetricEncAlgorithm(String algo) {
+ symEncAlgo = algo;
+ }
+
+ /**
+ * Set the name of an optional canonicalization algorithm to use before
+ * encryption.
+ *
+ * This c14n algorithm is used to serialize the data before encryption. If
+ * the algorithm is not set then a standard serialization is used (provided
+ * by XMLCipher, usually a XMLSerializer according to DOM 3 specification).
+ *
+ * @param algo
+ * Is the name of the canonicalization algorithm
+ */
+ public void setEncCanonicalization(String algo) {
+ encCanonAlgo = algo;
+ }
+
+ /**
+ * Get the name of symmetric encryption algorithm to use.
+ *
+ * The name of the encryption algorithm to encrypt the data, i.e. the SOAP
+ * Body. Refer to WSConstants which algorithms are supported.
+ *
+ * @return the name of the currently selected symmetric encryption algorithm
+ * @see WSConstants#TRIPLE_DES
+ * @see WSConstants#AES_128
+ * @see WSConstants#AES_192
+ * @see WSConstants#AES_256
+ */
+ public String getSymmetricEncAlgorithm() {
+ return symEncAlgo;
+ }
+
+ /**
+ * Initialize a WSSec Encrypt.
+ *
+ * The method prepares and initializes a WSSec Encrypt structure after the
+ * relevant information was set. After preparation of the token references
+ * can be added and encrypted.
+ *
+ * </p>
+ *
+ * This method does not add any element to the security header. This must be
+ * done explicitly.
+ *
+ * @param doc
+ * The SOAP envelope as <code>Document</code>
+ * @param crypto
+ * An instance of the Crypto API to handle keystore and
+ * certificates
+ * @throws WSSecurityException
+ */
+ public void prepare(Document doc, Crypto crypto) throws WSSecurityException {
+
+ document = doc;
+
+ /*
+ * If no external key (symmetricalKey) was set generate an encryption
+ * key (session key) for this Encrypt element. This key will be
+ * encrypted using the public key of the receiver
+ */
+
+
+ if(this.ephemeralKey == null) {
+ if (symmetricKey == null) {
+ KeyGenerator keyGen = getKeyGenerator();
+ this.symmetricKey = keyGen.generateKey();
+ }
+ this.ephemeralKey = this.symmetricKey.getEncoded();
+ }
+
+ if (this.symmetricKey == null) {
+
+ this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
+ this.ephemeralKey);
+ }
+
+ /*
+ * Get the certificate that contains the public key for the public key
+ * algorithm that will encrypt the generated symmetric (session) key.
+ */
+ if(this.encryptSymmKey) {
+ X509Certificate remoteCert = null;
+ if (useThisCert != null) {
+ remoteCert = useThisCert;
+ } else {
+ X509Certificate[] certs = crypto.getCertificates(user);
+ if (certs == null || certs.length <= 0) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidX509Data", new Object[] { "for Encryption" });
+ }
+ remoteCert = certs[0];
+ }
+ prepareInternal(this.ephemeralKey, remoteCert, crypto);
+ }
+ }
+
+ /**
+ * Builds the SOAP envelope with encrypted Body and adds encrypted key.
+ *
+ * This is a convenience method and for backward compatibility. The method
+ * calls the single function methods in order to perform a <i>one shot
+ * encryption</i>. This method is compatible with the build method of the
+ * previous version with the exception of the additional WSSecHeader
+ * parameter.
+ *
+ * @param doc
+ * the SOAP envelope as <code>Document</code> with plain text
+ * Body
+ * @param crypto
+ * an instance of the Crypto API to handle keystore and
+ * Certificates
+ * @param secHeader
+ * the security header element to hold the encrypted key element.
+ * @return the SOAP envelope with encrypted Body as <code>Document
+ * </code>
+ * @throws WSSecurityException
+ */
+ public Document build(Document doc, Crypto crypto, WSSecHeader secHeader)
+ throws WSSecurityException {
+ doDebug = log.isDebugEnabled();
+
+ if (keyIdentifierType == WSConstants.EMBEDDED_KEYNAME
+ || keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+ return buildEmbedded(doc, crypto, secHeader);
+ }
+
+ if (doDebug) {
+ log.debug("Beginning Encryption...");
+ }
+
+ prepare(doc, crypto);
+
+ SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+ if (parts == null) {
+ parts = new Vector();
+ WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+ .getBodyQName().getLocalPart(), soapConstants
+ .getEnvelopeURI(), "Content");
+ parts.add(encP);
+ }
+
+ Element refs = encryptForInternalRef(null, parts);
+ addInternalRefElement(refs);
+
+ prependToHeader(secHeader);
+
+ if (bstToken != null) {
+ prependBSTElementToHeader(secHeader);
+ }
+
+ log.debug("Encryption complete.");
+ return doc;
+ }
+
+ /**
+ * Encrypt one or more parts or elements of the message (internal).
+ *
+ * This method takes a vector of <code>WSEncryptionPart</code> object that
+ * contain information about the elements to encrypt. The method call the
+ * encryption method, takes the reference information generated during
+ * encryption and add this to the <code>xenc:Reference</code> element.
+ * This method can be called after <code>prepare()</code> and can be
+ * called multiple times to encrypt a number of parts or elements.
+ *
+ * </p>
+ *
+ * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+ * be added to this token. See <code>addInternalRefElement()</code>.
+ *
+ * </p>
+ *
+ * If the <code>dataRef</code> parameter is <code>null</code> the method
+ * creates and initializes a new Reference element.
+ *
+ * @param dataRef
+ * A <code>xenc:Reference</code> element or <code>null</code>
+ * @param references
+ * A vector containing WSEncryptionPart objects
+ * @return Returns the updated <code>xenc:Reference</code> element
+ * @throws WSSecurityException
+ */
+ public Element encryptForInternalRef(Element dataRef, Vector references)
+ throws WSSecurityException {
+ Vector encDataRefs = doEncryption(document, this.symmetricKey,
+ references);
+ Element referenceList = dataRef;
+ if (referenceList == null) {
+ referenceList = document.createElementNS(WSConstants.ENC_NS,
+ WSConstants.ENC_PREFIX + ":ReferenceList");
+ }
+ createDataRefList(document, referenceList, encDataRefs);
+ return referenceList;
+ }
+
+ /**
+ * Encrypt one or more parts or elements of the message (external).
+ *
+ * This method takes a vector of <code>WSEncryptionPart</code> object that
+ * contain information about the elements to encrypt. The method call the
+ * encryption method, takes the reference information generated during
+ * encryption and add this to the <code>xenc:Reference</code> element.
+ * This method can be called after <code>prepare()</code> and can be
+ * called multiple times to encrypt a number of parts or elements.
+ *
+ * </p>
+ *
+ * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+ * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
+ *
+ * </p>
+ *
+ * If the <code>dataRef</code> parameter is <code>null</code> the method
+ * creates and initializes a new Reference element.
+ *
+ * @param dataRef
+ * A <code>xenc:Reference</code> element or <code>null</code>
+ * @param references
+ * A vector containing WSEncryptionPart objects
+ * @return Returns the updated <code>xenc:Reference</code> element
+ * @throws WSSecurityException
+ */
+ public Element encryptForExternalRef(Element dataRef, Vector references)
+ throws WSSecurityException {
+
+ Vector encDataRefs = doEncryption(document, this.symmetricKey,
+ references);
+ Element referenceList = dataRef;
+ if (referenceList == null) {
+ referenceList = document.createElementNS(WSConstants.ENC_NS,
+ WSConstants.ENC_PREFIX + ":ReferenceList");
+ }
+ createDataRefList(document, referenceList, encDataRefs);
+ return referenceList;
+ }
+
+ /**
+ * Adds the internal Reference element to this Encrypt data.
+ *
+ * The reference element <i>must</i> be created by the
+ * <code>encryptForInternalRef()</code> method. The reference element is
+ * added to the <code>EncryptedKey</code> element of this encrypt block.
+ *
+ * @param dataRef
+ * The internal <code>enc:Reference</code> element
+ */
+ public void addInternalRefElement(Element dataRef) {
+ WSSecurityUtil.appendChildElement(document, encryptedKeyElement, dataRef);
+ }
+
+ /**
+ * Adds (prepends) the external Reference element to the Security header.
+ *
+ * The reference element <i>must</i> be created by the
+ * <code>encryptForExternalRef() </code> method. The method prepends the
+ * reference element in the SecurityHeader.
+ *
+ * @param dataRef
+ * The external <code>enc:Reference</code> element
+ * @param secHeader
+ * The security header.
+ */
+ public void addExternalRefElement(Element dataRef, WSSecHeader secHeader) {
+ WSSecurityUtil.prependChildElement(document, secHeader
+ .getSecurityHeader(), dataRef, false);
+ }
+
+ private Vector doEncryption(Document doc, SecretKey secretKey,
+ Vector references) throws WSSecurityException {
+
+ KeyInfo keyInfo = null;
+
+ // Prepare KeyInfo if useKeyIdentifier is set
+ if (keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
+ keyInfo = new KeyInfo(document);
+ SecurityTokenReference secToken = new SecurityTokenReference(document);
+ if(this.customReferenceValue != null) {
+ secToken.setKeyIdentifierEncKeySHA1(this.customReferenceValue);
+ } else {
+ secToken.setKeyIdentifierEncKeySHA1(getSHA1(encryptedEphemeralKey));
+ }
+
+
+ keyInfo.addUnknownElement(secToken.getElement());
+ }
+
+ return doEncryption(doc, secretKey, keyInfo, references);
+ }
+
+ 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) {
+ body = WSSecurityUtil.findElementById(document
+ .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
+ if (body == null) {
+ body = WSSecurityUtil.findElementById(document
+ .getDocumentElement(), idToEnc, null);
+ }
+ } else {
+ body = (Element) WSSecurityUtil.findElement(document, elemName,
+ nmSpace);
+ }
+ if (body == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "noEncElement", new Object[] { "{" + nmSpace + "}"
+ + elemName });
+ }
+
+ boolean content = modifier.equals("Content") ? true : false;
+ String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+ encPart.setEncId(xencEncryptedDataId);
+
+ cloneKeyInfo = true;
+
+ if(keyInfo == null) {
+ keyInfo = new KeyInfo(document);
+ SecurityTokenReference secToken = new SecurityTokenReference(document);
+ Reference ref = new Reference(document);
+ ref.setURI("#" + encKeyId);
+ secToken.setReference(ref);
+ keyInfo.addUnknownElement(secToken.getElement());
+ }
+ /*
+ * Forth 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", "EncHeader-" + body.hashCode());
+
+
+ NamedNodeMap map = body.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(), "soapevn");
+ 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, body, 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, body, content);
+ }
+ if(cloneKeyInfo) {
+ keyInfo = new KeyInfo((Element) keyInfo.getElement()
+ .cloneNode(true), null);
+ }
+ } catch (Exception e2) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+ }
+ encDataRef.add(new String("#" + xencEncryptedDataId));
+ }
+ return encDataRef;
+ }
+
+ private Document buildEmbedded(Document doc, Crypto crypto,
+ WSSecHeader secHeader) throws WSSecurityException {
+ doDebug = log.isDebugEnabled();
+
+ if (doDebug) {
+ log.debug("Beginning Encryption embedded...");
+ }
+ envelope = doc.getDocumentElement();
+ envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+ + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
+
+ /*
+ * Second step: generate a symmetric key from the specified key
+ * (password) for this algorithm, and set the cipher into encryption
+ * mode.
+ */
+ if (this.symmetricKey == null) {
+ if (embeddedKey == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "noKeySupplied");
+ }
+ this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
+ embeddedKey);
+ }
+
+ KeyInfo keyInfo = null;
+ if (this.keyIdentifierType == WSConstants.EMBEDDED_KEYNAME) {
+ keyInfo = new KeyInfo(doc);
+ keyInfo
+ .addKeyName(embeddedKeyName == null ? user
+ : embeddedKeyName);
+ } else if (this.keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+ /*
+ * This means that we want to embed a <wsse:SecurityTokenReference>
+ * into keyInfo element. If we need this functionality, this.secRef
+ * MUST be set before calling the build(doc, crypto) method. So if
+ * secRef is null then throw an exception.
+ */
+ if (this.securityTokenReference == null) {
+ throw new WSSecurityException(
+ WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+ "You must set keyInfo element, if the keyIdentifier "
+ + "== EMBED_SECURITY_TOKEN_REF");
+ } else {
+ keyInfo = new KeyInfo(doc);
+ Element tmpE = securityTokenReference.getElement();
+ tmpE.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+ + tmpE.getPrefix(), tmpE.getNamespaceURI());
+ keyInfo.addUnknownElement(securityTokenReference.getElement());
+ }
+ }
+
+ SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+ if (parts == null) {
+ parts = new Vector();
+ WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+ .getBodyQName().getLocalPart(), soapConstants
+ .getEnvelopeURI(), "Content");
+ parts.add(encP);
+ }
+ Vector encDataRefs = doEncryption(doc, this.symmetricKey, keyInfo,
+ parts);
+
+ /*
+ * At this point data is encrypted with the symmetric key and can be
+ * referenced via the above Id
+ */
+
+ /*
+ * Now we need to setup the wsse:Security header block 1) get (or
+ * create) the wsse:Security header block 2) The last step sets up the
+ * reference list that pints to the encrypted data
+ */
+ Element wsseSecurity = secHeader.getSecurityHeader();
+
+ Element referenceList = doc.createElementNS(WSConstants.ENC_NS,
+ WSConstants.ENC_PREFIX + ":ReferenceList");
+ referenceList = createDataRefList(doc, referenceList, encDataRefs);
+ WSSecurityUtil.prependChildElement(doc, wsseSecurity, referenceList,
+ true);
+
+ return doc;
+ }
+
+ private KeyGenerator getKeyGenerator() throws WSSecurityException {
+ KeyGenerator keyGen = null;
+ try {
+ /*
+ * Assume AES as default, so initialize it
+ */
+ keyGen = KeyGenerator.getInstance("AES");
+ if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
+ keyGen = KeyGenerator.getInstance("DESede");
+ } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
+ keyGen.init(128);
+ } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
+ keyGen.init(192);
+ } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
+ keyGen.init(256);
+ } else {
+ return null;
+ }
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+ }
+ return keyGen;
+ }
+
+ /**
+ * Create DOM subtree for <code>xenc:EncryptedKey</code>
+ *
+ * @param doc
+ * the SOAP envelope parent document
+ * @param keyTransportAlgo
+ * specifies which algorithm to use to encrypt the symmetric key
+ * @return an <code>xenc:EncryptedKey</code> element
+ */
+
+ public static Element createDataRefList(Document doc,
+ Element referenceList, Vector encDataRefs) {
+ for (int i = 0; i < encDataRefs.size(); i++) {
+ String dataReferenceUri = (String) encDataRefs.get(i);
+ Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
+ WSConstants.ENC_PREFIX + ":DataReference");
+ dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+ referenceList.appendChild(dataReference);
+ }
+ return referenceList;
+ }
+
+ /**
+ * @return The symmetric key
+ */
+ public SecretKey getSymmetricKey() {
+ return symmetricKey;
+ }
+
+ /**
+ * Set the symmetric key to be used for encryption
+ *
+ * @param key
+ */
+ public void setSymmetricKey(SecretKey key) {
+ this.symmetricKey = key;
+ }
+
+ /**
+ * @return Return the SecurityTokenRefernce
+ */
+ public SecurityTokenReference getSecurityTokenReference() {
+ return securityTokenReference;
+ }
+
+ /**
+ * @param reference
+ */
+ public void setSecurityTokenReference(SecurityTokenReference reference) {
+ securityTokenReference = reference;
+ }
+
+ public boolean isEncryptSymmKey() {
+ return encryptSymmKey;
+ }
+
+ public void setEncryptSymmKey(boolean encryptSymmKey) {
+ this.encryptSymmKey = encryptSymmKey;
+ }
+
+ private String getSHA1(byte[] input) throws WSSecurityException {
+ try {
+ MessageDigest sha = null;
+ sha = MessageDigest.getInstance("SHA-1");
+ sha.reset();
+ sha.update(input);
+ byte[] data = sha.digest();
+
+ return Base64.encode(data);
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(
+ WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+ }
+ }
+
+ public void setCustomReferenceValue(String customReferenceValue) {
+ this.customReferenceValue = customReferenceValue;
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org