You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by we...@apache.org on 2006/03/06 18:05:23 UTC

svn commit: r383585 [2/2] - in /webservices/wss4j/trunk/src/org/apache/ws/security: ./ handler/ message/ processor/ util/

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java?rev=383585&r1=383584&r2=383585&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 Mon Mar  6 09:05:19 2006
@@ -46,7 +46,6 @@
 import javax.crypto.SecretKey;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
 import java.security.cert.X509Certificate;
 import java.util.Vector;
 
@@ -58,856 +57,814 @@
  * @author Werner Dittmann (Werner.Dittmann@apache.org).
  */
 public class WSSecEncrypt extends WSSecBase {
-	private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
+    private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
 
-	private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
 
-	protected String symEncAlgo = WSConstants.AES_128;
+    protected String symEncAlgo = WSConstants.AES_128;
 
-	protected String keyEncAlgo = WSConstants.KEYTRANSPORT_RSA15;
+    protected String keyEncAlgo = WSConstants.KEYTRANSPORT_RSA15;
 
-	protected String encCanonAlgo = null;
-
-	protected byte[] embeddedKey = null;
-
-	protected String embeddedKeyName = null;
-
-	protected X509Certificate useThisCert = null;
-
-	/**
-	 * Symmetric key used in the EncrytpedKey.
-	 */
-	protected SecretKey symmetricKey = null;
-
-	/**
-	 * Symmetric key that's actually used.
-	 */
-	protected SecretKey encryptionKey = null;
-
-	/**
-	 * Parent node to which the EncryptedKeyElement should be added.
-	 */
-	protected Element parentNode = null;
-
-	/**
-	 * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
-	 */
-	protected SecurityTokenReference securityTokenReference = null;
-
-	private BinarySecurity bstToken = null;
-
-	private Element xencEncryptedKey = null;
-
-	private Document document = null;
-
-	private Element envelope = null;
-
-	private String encKeyId = null;
-
-	private Vector encDataRefs = null;
-
-	/**
-	 * 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 user name to get the encryption certificate.
-	 * 
-	 * The public key of this certificate is used, thus no password necessary.
-	 * The user name is a keystore alias usually.
-	 * 
-	 * @param user
-	 */
-	public void setUserInfo(String user) {
-		this.user = user;
-	}
-
-	/**
-	 * Set the key name for EMBEDDED_KEYNAME
-	 * 
-	 * @param embeddedKeyName
-	 */
-	public void setEmbeddedKeyName(String embeddedKeyName) {
-		this.embeddedKeyName = embeddedKeyName;
-	}
-
-	/**
-	 * Set the X509 Certificate to use for encryption.
-	 * 
-	 * If this is set <b>and</b> the key identifier is set to
-	 * <code>DirectReference</code> then use this certificate to get the
-	 * public key for encryption.
-	 * 
-	 * @param cert
-	 *            is the X509 certificate to use for encryption
-	 */
-	public void setUseThisCert(X509Certificate cert) {
-		useThisCert = cert;
-	}
-
-	/**
-	 * Set the name of the symmetric encryption algorithm to use.
-	 * 
-	 * This encryption alogrithm 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 alogrithm 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 alogrithm 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;
-	}
-
-	/**
-	 * Get the id generated during <code>prepare()</code>.
-	 * 
-	 * Returns the the value of wsu:Id attribute of the EncryptedKey element.
-	 * 
-	 * @return Return the wsu:Id of this token or null if <code>prepare()</code>
-	 *         was not called before.
-	 */
-	public String getId() {
-		return encKeyId;
-	}
-
-	/**
-	 * Returns a Vector that contains the refernces to EncryptedData elements.
-	 * 
-	 * During encryption the encryption method generates one or more
-	 * EncryptedData elements. Each elements gets its unique id. The encryption
-	 * process stores these id in a vector that the caller may use to get the
-	 * generated unique ids.
-	 * 
-	 * <p/>
-	 * 
-	 * ATTENTION: Each call to <code>encryptForExternalRef</code> or
-	 * <code>encryptForInternalRef</code> overwrites the Vector that contains
-	 * the ids. Thus get the refernces immediatly after calling one of the named
-	 * methods.
-	 * 
-	 * 
-	 * @return Returns the encDataRefs.
-	 */
-	public Vector getEncDataRefs() {
-		return encDataRefs;
-	}
-
-	/**
-	 * Initialize a WSSec Encrypt.
-	 * 
-	 * The method prepares and initializes a WSSec Encrypt structure after the
-	 * relevant information was set. After preparartion 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 unsigned 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
-		 */
-
-		this.encryptionKey = this.symmetricKey;
-		if (encryptionKey == null) {
-			KeyGenerator keyGen = getKeyGenerator();
-			this.encryptionKey = keyGen.generateKey();
-		}
-
-		/*
-		 * Get the certificate that contains the public key for the public key
-		 * algorithm that will encrypt the generated symmetric (session) key.
-		 */
-		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];
-		}
-		String certUri = "EncCertId-" + remoteCert.hashCode();
-		Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo, wssConfig
-				.getJceProviderId());
-		try {
-			cipher.init(Cipher.ENCRYPT_MODE, remoteCert);
-		} catch (InvalidKeyException e) {
-			throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
-					null, null, e);
-		}
-		byte[] encKey = this.encryptionKey.getEncoded();
-		if (doDebug) {
-			log.debug("cipher blksize: " + cipher.getBlockSize()
-					+ ", symm key length: " + encKey.length);
-		}
-		if (cipher.getBlockSize() < encKey.length) {
-			throw new WSSecurityException(
-					WSSecurityException.FAILURE,
-					"unsupportedKeyTransp",
-					new Object[] { "public key algorithm too weak to encrypt symmetric key" });
-		}
-		byte[] encryptedKey = null;
-		try {
-			encryptedKey = cipher.doFinal(encKey);
-		} catch (IllegalStateException e1) {
-			throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
-					null, null, e1);
-		} catch (IllegalBlockSizeException e1) {
-			throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
-					null, null, e1);
-		} catch (BadPaddingException e1) {
-			throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
-					null, null, e1);
-		}
-		Text keyText = WSSecurityUtil.createBase64EncodedTextNode(doc,
-				encryptedKey);
-
-		/*
-		 * Now we need to setup the EncryptedKey header block 1) create a
-		 * EncryptedKey element and set a wsu:Id for it 2) Generate ds:KeyInfo
-		 * element, this wraps the wsse:SecurityTokenReference 3) Create and set
-		 * up the SecurityTokenReference according to the keyIdentifer parameter
-		 * 4) Create the CipherValue element structure and insert the encrypted
-		 * session key
-		 */
-		xencEncryptedKey = createEnrcyptedKey(doc, keyEncAlgo);
-		encKeyId = "EncKeyId-" + xencEncryptedKey.hashCode();
-		xencEncryptedKey.setAttributeNS(null, "Id", encKeyId);
-
-		KeyInfo keyInfo = new KeyInfo(doc);
-
-		SecurityTokenReference secToken = new SecurityTokenReference(doc);
-
-		switch (keyIdentifierType) {
-		case WSConstants.X509_KEY_IDENTIFIER:
-			secToken.setKeyIdentifier(remoteCert);
-			break;
-
-		case WSConstants.SKI_KEY_IDENTIFIER:
-			secToken.setKeyIdentifierSKI(remoteCert, crypto);
-			break;
-
-		case WSConstants.THUMBPRINT_IDENTIFIER:
-			secToken.setKeyIdentifierThumb(remoteCert);
-			break;
-
-		case WSConstants.ISSUER_SERIAL:
-			XMLX509IssuerSerial data = new XMLX509IssuerSerial(doc, remoteCert);
-			X509Data x509Data = new X509Data(doc);
-			x509Data.add(data);
-			secToken.setX509IssuerSerial(x509Data);
-			break;
-
-		case WSConstants.BST_DIRECT_REFERENCE:
-			Reference ref = new Reference(doc);
-			ref.setURI("#" + certUri);
-			bstToken = new X509Security(doc);
-			((X509Security) bstToken).setX509Certificate(remoteCert);
-			bstToken.setID(certUri);
-			ref.setValueType(bstToken.getValueType());
-			secToken.setReference(ref);
-			break;
-
-		default:
-			throw new WSSecurityException(WSSecurityException.FAILURE,
-					"unsupportedKeyId");
-		}
-		keyInfo.addUnknownElement(secToken.getElement());
-		WSSecurityUtil.appendChildElement(doc, xencEncryptedKey, keyInfo
-				.getElement());
-
-		Element xencCipherValue = createCipherValue(doc, xencEncryptedKey);
-		xencCipherValue.appendChild(keyText);
-
-		envelope = doc.getDocumentElement();
-		envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
-				+ WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
-
-	}
-
-	/**
-	 * Prepend the EncryptedKey element to the elements already in the Security
-	 * header.
-	 * 
-	 * The method can be called any time after <code>prepare()</code>. This
-	 * allows to insert the EncryptedKey element at any position in the Security
-	 * header.
-	 * 
-	 * @param secHeader
-	 *            The security header that holds the Signature element.
-	 */
-	public void prependToHeader(WSSecHeader secHeader) {
-		WSSecurityUtil.prependChildElement(document, secHeader
-				.getSecurityHeader(), xencEncryptedKey, false);
-	}
-
-	/**
-	 * Prepend the BinarySecurityToken to the elements already in the Security
-	 * header.
-	 * 
-	 * The method can be called any time after <code>prepare()</code>. This
-	 * allows to insert the BST element at any position in the Security header.
-	 * 
-	 * @param secHeader
-	 *            The security header that holds the BST element.
-	 */
-	public void prependBSTElementToHeader(WSSecHeader secHeader) {
-		if (bstToken != null) {
-			WSSecurityUtil.prependChildElement(document, secHeader
-					.getSecurityHeader(), bstToken.getElement(), false);
-		}
-		bstToken = null;
-	}
-
-	/**
-	 * 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 plaintext
-	 *            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 {
-		encDataRefs = doEncryption(document, this.encryptionKey, 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 {
-
-		KeyInfo keyInfo = new KeyInfo(document);
-		SecurityTokenReference secToken = new SecurityTokenReference(document);
-		Reference ref = new Reference(document);
-		ref.setURI("#" + encKeyId);
-		secToken.setReference(ref);
-
-		keyInfo.addUnknownElement(secToken.getElement());
-
-		encDataRefs = doEncryption(document, this.encryptionKey, keyInfo,
-				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 refernce element <i>must</i> be created by the
-	 * <code>encryptForInternalRef()</code> method. The refernce 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, xencEncryptedKey, dataRef);
-	}
-
-	/**
-	 * Adds (prepends) the external Reference element to the Security header.
-	 * 
-	 * The refernce 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 {
-		return doEncryption(doc, secretKey, null, references);
-	}
-
-	private Vector doEncryption(Document doc, SecretKey secretKey,
-			KeyInfo keyInfo, Vector references) throws WSSecurityException {
-
-		XMLCipher xmlCipher = null;
-		try {
-			String provider = wssConfig.getJceProviderId();
-			if (provider == null) {
-				xmlCipher = XMLCipher.getInstance(symEncAlgo);
-			} else {
-				xmlCipher = XMLCipher.getProviderInstance(symEncAlgo, provider);
-			}
-		} catch (XMLEncryptionException e3) {
-			throw new WSSecurityException(
-					WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
-		}
-
-		Vector encDataRef = new Vector();
-
-		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 neccessary attributes in
-			 * xenc:EncryptedData
-			 */
-			try {
-				xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
-				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);
-			}
-			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 alogrithm, and set the cipher into encryption
-		 * mode.
-		 */
-		this.encryptionKey = this.symmetricKey;
-		if (this.encryptionKey == null) {
-			if (embeddedKey == null) {
-				throw new WSSecurityException(WSSecurityException.FAILURE,
-						"noKeySupplied");
-			}
-			this.encryptionKey = 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.encryptionKey, 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;
-		String id = wssConfig.getJceProviderId();
-		try {
-			/*
-			 * Assume AES as default, so initialize it
-			 */
-			if (id == null) {
-				keyGen = KeyGenerator.getInstance("AES");
-			} else {
-				keyGen = KeyGenerator.getInstance("AES", id);
-			}
-			if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
-				if (id == null) {
-					keyGen = KeyGenerator.getInstance("DESede");
-				} else {
-					keyGen = KeyGenerator.getInstance("DESede", id);
-				}
-			} 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);
-		} catch (NoSuchProviderException e) {
-			throw new WSSecurityException(
-					WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
-		}
-		return keyGen;
-	}
-
-	/**
-	 * Create DOM subtree for <code>xenc:EncryptedKey</code>
-	 * 
-	 * @param doc
-	 *            the SOAP enevelope parent document
-	 * @param keyTransportAlgo
-	 *            specifies which alogrithm to use to encrypt the symmetric key
-	 * @return an <code>xenc:EncryptedKey</code> element
-	 */
-	public static Element createEnrcyptedKey(Document doc,
-			String keyTransportAlgo) {
-		Element encryptedKey = doc.createElementNS(WSConstants.ENC_NS,
-				WSConstants.ENC_PREFIX + ":EncryptedKey");
-
-		WSSecurityUtil.setNamespace(encryptedKey, WSConstants.ENC_NS,
-				WSConstants.ENC_PREFIX);
-		Element encryptionMethod = doc.createElementNS(WSConstants.ENC_NS,
-				WSConstants.ENC_PREFIX + ":EncryptionMethod");
-		encryptionMethod.setAttributeNS(null, "Algorithm", keyTransportAlgo);
-		WSSecurityUtil.appendChildElement(doc, encryptedKey, encryptionMethod);
-		return encryptedKey;
-	}
-
-	public static Element createCipherValue(Document doc, Element encryptedKey) {
-		Element cipherData = doc.createElementNS(WSConstants.ENC_NS,
-				WSConstants.ENC_PREFIX + ":CipherData");
-		Element cipherValue = doc.createElementNS(WSConstants.ENC_NS,
-				WSConstants.ENC_PREFIX + ":CipherValue");
-		cipherData.appendChild(cipherValue);
-		WSSecurityUtil.appendChildElement(doc, encryptedKey, cipherData);
-		return cipherValue;
-	}
-
-	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;
-	}
-
-	/**
-	 * Sets the parent node of the EncryptedKeyElement
-	 * 
-	 * @param element
-	 */
-	public void setParentNode(Element element) {
-		parentNode = element;
-	}
-
-	/**
-	 * @return TODO
-	 */
-	public SecretKey getSymmetricKey() {
-		return symmetricKey;
-	}
-
-	/**
-	 * Set the symmetric key to be used for encryption
-	 * 
-	 * @param key
-	 */
-	public void setSymmetricKey(SecretKey key) {
-		this.symmetricKey = key;
-	}
-
-	/**
-	 * Get the symmetric key used for encryption. This may be the same as the
-	 * symmetric key field.
-	 * 
-	 * @return The symmetric key
-	 */
-	public SecretKey getEncryptionKey() {
-		return this.encryptionKey;
-	}
-
-	/**
-	 * @return TODO
-	 */
-	public SecurityTokenReference getSecurityTokenReference() {
-		return securityTokenReference;
-	}
-
-	/**
-	 * @param reference
-	 */
-	public void setSecurityTokenReference(SecurityTokenReference reference) {
-		securityTokenReference = reference;
-	}
+    protected String encCanonAlgo = null;
+
+    protected byte[] embeddedKey = null;
+
+    protected String embeddedKeyName = null;
+
+    protected X509Certificate useThisCert = null;
+
+    /**
+     * Symmetric key used in the EncrytpedKey.
+     */
+    protected SecretKey symmetricKey = null;
+
+    /**
+     * Symmetric key that's actually used.
+     */
+    protected SecretKey encryptionKey = null;
+
+    /**
+     * Parent node to which the EncryptedKeyElement should be added.
+     */
+    protected Element parentNode = null;
+
+    /**
+     * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
+     */
+    protected SecurityTokenReference securityTokenReference = null;
+
+    private BinarySecurity bstToken = null;
+
+    private Element xencEncryptedKey = null;
+
+    private Document document = null;
+
+    private Element envelope = null;
+
+    private String encKeyId = null;
+
+    /**
+     * 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 user name to get the encryption certificate.
+     * 
+     * The public key of this certificate is used, thus no password necessary.
+     * The user name is a keystore alias usually.
+     * 
+     * @param user
+     */
+    public void setUserInfo(String user) {
+        this.user = user;
+    }
+
+    /**
+     * Set the key name for EMBEDDED_KEYNAME
+     * 
+     * @param embeddedKeyName
+     */
+    public void setEmbeddedKeyName(String embeddedKeyName) {
+        this.embeddedKeyName = embeddedKeyName;
+    }
+
+    /**
+     * Set the X509 Certificate to use for encryption.
+     * 
+     * If this is set <b>and</b> the key identifier is set to
+     * <code>DirectReference</code> then use this certificate to get the
+     * public key for encryption.
+     * 
+     * @param cert
+     *            is the X509 certificate to use for encryption
+     */
+    public void setUseThisCert(X509Certificate cert) {
+        useThisCert = cert;
+    }
+
+    /**
+     * Set the name of the symmetric encryption algorithm to use.
+     * 
+     * This encryption alogrithm 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 alogrithm 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 alogrithm 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;
+    }
+
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of the EncryptedKey element.
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepare()</code>
+     *         was not called before.
+     */
+    public String getId() {
+        return encKeyId;
+    }
+
+    /**
+     * Initialize a WSSec Encrypt.
+     * 
+     * The method prepares and initializes a WSSec Encrypt structure after the
+     * relevant information was set. After preparartion 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 unsigned 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
+         */
+
+        this.encryptionKey = this.symmetricKey;
+        if (encryptionKey == null) {
+            KeyGenerator keyGen = getKeyGenerator();
+            this.encryptionKey = keyGen.generateKey();
+        }
+
+        /*
+         * Get the certificate that contains the public key for the public key
+         * algorithm that will encrypt the generated symmetric (session) key.
+         */
+        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];
+        }
+        String certUri = "EncCertId-" + remoteCert.hashCode();
+        Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo);
+        try {
+            cipher.init(Cipher.ENCRYPT_MODE, remoteCert);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
+                    null, null, e);
+        }
+        byte[] encKey = this.encryptionKey.getEncoded();
+        if (doDebug) {
+            log.debug("cipher blksize: " + cipher.getBlockSize()
+                    + ", symm key length: " + encKey.length);
+        }
+        if (cipher.getBlockSize() < encKey.length) {
+            throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "unsupportedKeyTransp",
+                    new Object[] { "public key algorithm too weak to encrypt symmetric key" });
+        }
+        byte[] encryptedKey = null;
+        try {
+            encryptedKey = cipher.doFinal(encKey);
+        } catch (IllegalStateException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
+                    null, null, e1);
+        } catch (IllegalBlockSizeException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
+                    null, null, e1);
+        } catch (BadPaddingException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
+                    null, null, e1);
+        }
+        Text keyText = WSSecurityUtil.createBase64EncodedTextNode(doc,
+                encryptedKey);
+
+        /*
+         * Now we need to setup the EncryptedKey header block 1) create a
+         * EncryptedKey element and set a wsu:Id for it 2) Generate ds:KeyInfo
+         * element, this wraps the wsse:SecurityTokenReference 3) Create and set
+         * up the SecurityTokenReference according to the keyIdentifer parameter
+         * 4) Create the CipherValue element structure and insert the encrypted
+         * session key
+         */
+        xencEncryptedKey = createEnrcyptedKey(doc, keyEncAlgo);
+        encKeyId = "EncKeyId-" + xencEncryptedKey.hashCode();
+        xencEncryptedKey.setAttributeNS(null, "Id", encKeyId);
+
+        KeyInfo keyInfo = new KeyInfo(doc);
+
+        SecurityTokenReference secToken = new SecurityTokenReference(doc);
+
+        switch (keyIdentifierType) {
+        case WSConstants.X509_KEY_IDENTIFIER:
+            secToken.setKeyIdentifier(remoteCert);
+            break;
+
+        case WSConstants.SKI_KEY_IDENTIFIER:
+            secToken.setKeyIdentifierSKI(remoteCert, crypto);
+            break;
+
+        case WSConstants.THUMBPRINT_IDENTIFIER:
+            secToken.setKeyIdentifierThumb(remoteCert);
+            break;
+
+        case WSConstants.ISSUER_SERIAL:
+            XMLX509IssuerSerial data = new XMLX509IssuerSerial(doc, remoteCert);
+            X509Data x509Data = new X509Data(doc);
+            x509Data.add(data);
+            secToken.setX509IssuerSerial(x509Data);
+            break;
+
+        case WSConstants.BST_DIRECT_REFERENCE:
+            Reference ref = new Reference(doc);
+            ref.setURI("#" + certUri);
+            bstToken = new X509Security(doc);
+            ((X509Security) bstToken).setX509Certificate(remoteCert);
+            bstToken.setID(certUri);
+            ref.setValueType(bstToken.getValueType());
+            secToken.setReference(ref);
+            break;
+
+        default:
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyId");
+        }
+        keyInfo.addUnknownElement(secToken.getElement());
+        WSSecurityUtil.appendChildElement(doc, xencEncryptedKey, keyInfo
+                .getElement());
+
+        Element xencCipherValue = createCipherValue(doc, xencEncryptedKey);
+        xencCipherValue.appendChild(keyText);
+
+        envelope = doc.getDocumentElement();
+        envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
+
+    }
+
+    /**
+     * Prepend the EncryptedKey element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the EncryptedKey element at any position in the Security
+     * header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), xencEncryptedKey, false);
+    }
+
+    /**
+     * Prepend the BinarySecurityToken to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the BST element at any position in the Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the BST element.
+     */
+    public void prependBSTElementToHeader(WSSecHeader secHeader) {
+        if (bstToken != null) {
+            WSSecurityUtil.prependChildElement(document, secHeader
+                    .getSecurityHeader(), bstToken.getElement(), false);
+        }
+        bstToken = null;
+    }
+
+    /**
+     * 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 plaintext
+     *            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.encryptionKey,
+                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 {
+
+        KeyInfo keyInfo = new KeyInfo(document);
+        SecurityTokenReference secToken = new SecurityTokenReference(document);
+        Reference ref = new Reference(document);
+        ref.setURI("#" + encKeyId);
+        secToken.setReference(ref);
+
+        keyInfo.addUnknownElement(secToken.getElement());
+
+        Vector encDataRefs = doEncryption(document, this.encryptionKey,
+                keyInfo, 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 refernce element <i>must</i> be created by the
+     * <code>encryptForInternalRef()</code> method. The refernce 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, xencEncryptedKey, dataRef);
+    }
+
+    /**
+     * Adds (prepends) the external Reference element to the Security header.
+     * 
+     * The refernce 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 {
+        return doEncryption(doc, secretKey, null, 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();
+
+        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 neccessary attributes in
+             * xenc:EncryptedData
+             */
+            try {
+                xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+                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);
+            }
+            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 alogrithm, and set the cipher into encryption
+         * mode.
+         */
+        this.encryptionKey = this.symmetricKey;
+        if (this.encryptionKey == null) {
+            if (embeddedKey == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noKeySupplied");
+            }
+            this.encryptionKey = 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.encryptionKey, 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;
+        String id = wssConfig.getJceProviderId();
+        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 enevelope parent document
+     * @param keyTransportAlgo
+     *            specifies which alogrithm to use to encrypt the symmetric key
+     * @return an <code>xenc:EncryptedKey</code> element
+     */
+    public static Element createEnrcyptedKey(Document doc,
+            String keyTransportAlgo) {
+        Element encryptedKey = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":EncryptedKey");
+
+        WSSecurityUtil.setNamespace(encryptedKey, WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX);
+        Element encryptionMethod = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":EncryptionMethod");
+        encryptionMethod.setAttributeNS(null, "Algorithm", keyTransportAlgo);
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, encryptionMethod);
+        return encryptedKey;
+    }
+
+    public static Element createCipherValue(Document doc, Element encryptedKey) {
+        Element cipherData = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":CipherData");
+        Element cipherValue = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":CipherValue");
+        cipherData.appendChild(cipherValue);
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, cipherData);
+        return cipherValue;
+    }
+
+    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;
+    }
+
+    /**
+     * Sets the parent node of the EncryptedKeyElement
+     * 
+     * @param element
+     */
+    public void setParentNode(Element element) {
+        parentNode = element;
+    }
+
+    /**
+     * @return TODO
+     */
+    public SecretKey getSymmetricKey() {
+        return symmetricKey;
+    }
+
+    /**
+     * Set the symmetric key to be used for encryption
+     * 
+     * @param key
+     */
+    public void setSymmetricKey(SecretKey key) {
+        this.symmetricKey = key;
+    }
+
+    /**
+     * Get the symmetric key used for encryption. This may be the same as the
+     * symmetric key field.
+     * 
+     * @return The symmetric key
+     */
+    public SecretKey getEncryptionKey() {
+        return this.encryptionKey;
+    }
+
+    /**
+     * @return TODO
+     */
+    public SecurityTokenReference getSecurityTokenReference() {
+        return securityTokenReference;
+    }
+
+    /**
+     * @param reference
+     */
+    public void setSecurityTokenReference(SecurityTokenReference reference) {
+        securityTokenReference = reference;
+    }
 
 }

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecHeader.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecHeader.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecHeader.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecHeader.java Mon Mar  6 09:05:19 2006
@@ -21,13 +21,9 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.security.SOAPConstants;
 import org.apache.ws.security.WSConstants;
-import org.apache.ws.security.WSSConfig;
-import org.apache.ws.security.components.crypto.Crypto;
 import org.apache.ws.security.util.WSSecurityUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-
-import java.util.Vector;
 
 /**
  * This class implements WS Security header.

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java Mon Mar  6 09:05:19 2006
@@ -18,7 +18,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.ws.security.message.token.UsernameToken;
 import org.apache.ws.security.util.WSSecurityUtil;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLException;

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java Mon Mar  6 09:05:19 2006
@@ -20,10 +20,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ws.security.message.token.SignatureConfirmation;
-import org.apache.ws.security.message.token.Timestamp;
 import org.apache.ws.security.util.WSSecurityUtil;
 import org.w3c.dom.Document;
-import org.w3c.dom.Element;
 
 /**
  * Builds a WS SignatureConfirmation and inserts it into the SOAP Envelope.

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java Mon Mar  6 09:05:19 2006
@@ -82,7 +82,7 @@
 
     /**
      * Constructor.
-     * @deprecated replaced by {@link WSSecSignature#constructor()}
+     * @deprecated replaced by {@link WSSecSignature#WSSecSignature()}
      */
     public WSSignEnvelope() {
     }
@@ -92,7 +92,7 @@
      *
      * @param actor The actor name of the <code>wsse:Security</code> header
      * 
-     * @deprecated replaced by {@link WSSecSignature#constructor()}
+     * @deprecated replaced by {@link WSSecSignature#WSSecSignature()}
      *             and {@link WSSecHeader} for actor specification.
      */
     public WSSignEnvelope(String actor) {
@@ -105,7 +105,7 @@
      * @param actor The actor name of the <code>wsse:Security</code> header
      * @param mu    Set <code>mustUnderstand</code> to true or false
      * 
-     * @deprecated replaced by {@link WSSecSignature#constructor()}
+     * @deprecated replaced by {@link WSSecSignature#WSSecSignature()}
      *             and {@link WSSecHeader} for actor and mustunderstand
      *             specification.
      */

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java Mon Mar  6 09:05:19 2006
@@ -135,8 +135,8 @@
      * Get the derived key bytes for a given length
      * @return Returns the keyBytes.
      */
-    public byte[] getKeyBytes(int length) throws WSSecurityException {
-        this.length = length;
+    public byte[] getKeyBytes(int len) throws WSSecurityException {
+        this.length = len;
         this.deriveKey();
         return keyBytes;
     } 

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java Mon Mar  6 09:05:19 2006
@@ -113,7 +113,7 @@
             throw new WSSecurityException
                     (WSSecurityException.UNSUPPORTED_ALGORITHM, "noEncAlgo");
         }
-        Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo, wssConfig.getJceProviderId());
+        Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo);
         /*
          * Well, we can decrypt the session (symmetric) key. Now lookup CipherValue, this is the value of the
          * encrypted session key (session key usually is a symmetrical key that encrypts

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java?rev=383585&r1=383584&r2=383585&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java Mon Mar  6 09:05:19 2006
@@ -678,23 +678,15 @@
         }
     }
 
-    public static Cipher getCipherInstance(String cipherAlgo, String jceId)
+    public static Cipher getCipherInstance(String cipherAlgo)
             throws WSSecurityException {
         Cipher cipher = null;
         try {
             if (cipherAlgo.equalsIgnoreCase(WSConstants.KEYTRANSPORT_RSA15)) {
-                if (jceId == null) {
-                    cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
-                } else {
-                    cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING", jceId);
-                }
+                cipher = Cipher.getInstance("RSA/NONE/PKCS1PADDING");
             } else if (cipherAlgo
                     .equalsIgnoreCase(WSConstants.KEYTRANSPORT_RSAOEP)) {
-                if (jceId == null) {
-                    cipher = Cipher.getInstance("RSA/NONE/OAEPPADDING");
-                } else {
-                    cipher = Cipher.getInstance("RSA/NONE/OAEPPADDING", jceId);
-                }
+                cipher = Cipher.getInstance("RSA/NONE/OAEPPADDING");
             } else {
                 throw new WSSecurityException(
                         WSSecurityException.UNSUPPORTED_ALGORITHM,
@@ -704,11 +696,6 @@
             throw new WSSecurityException(
                     WSSecurityException.UNSUPPORTED_ALGORITHM,
                     "unsupportedKeyTransp", new Object[] { "No such padding: "
-                            + cipherAlgo });
-        } catch (NoSuchProviderException ex) {
-            throw new WSSecurityException(
-                    WSSecurityException.UNSUPPORTED_ALGORITHM,
-                    "unsupportedKeyTransp", new Object[] { "no provider: "
                             + cipherAlgo });
         } catch (NoSuchAlgorithmException ex) {
             throw new WSSecurityException(



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