Author: anil.saldhana(a)jboss.com
Date: 2009-02-26 15:53:50 -0500 (Thu, 26 Feb 2009)
New Revision: 351
Modified:
identity-federation/trunk/identity-fed-api/.classpath
identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java
identity-federation/trunk/identity-fed-api/src/test/java/org/jboss/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java
Log:
XMLEnc updates
Modified: identity-federation/trunk/identity-fed-api/.classpath
===================================================================
--- identity-federation/trunk/identity-fed-api/.classpath 2009-02-26 20:53:23 UTC (rev
350)
+++ identity-federation/trunk/identity-fed-api/.classpath 2009-02-26 20:53:50 UTC (rev
351)
@@ -3,7 +3,7 @@
<classpathentry kind="src" path="src/main/java"/>
<classpathentry excluding="**/*.java" kind="src"
path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes"
path="src/test/java"/>
- <classpathentry excluding="**/*.java" kind="src"
output="target/test-classes" path="src/test/resources"/>
+ <classpathentry excluding="**/*.java|endorsed/*jar" kind="src"
output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var"
path="M2_REPO/sun-jaf/activation/1.1/activation-1.1.jar"/>
<classpathentry kind="var"
path="M2_REPO/apache-logging/commons-logging-api/1.0.3/commons-logging-api-1.0.3.jar"/>
@@ -19,5 +19,10 @@
<classpathentry combineaccessrules="false" kind="src"
path="/identity-fed-model"/>
<classpathentry combineaccessrules="false" kind="src"
path="/identity-xmlsecmodel"/>
<classpathentry kind="var"
path="M2_REPO/sun-jaxws/jaxws-api/2.1.1/jaxws-api-2.1.1.jar"/>
+ <classpathentry kind="lib"
path="src/test/resources/endorsed/resolver.jar"/>
+ <classpathentry kind="lib"
path="src/test/resources/endorsed/serializer.jar"/>
+ <classpathentry kind="lib"
path="src/test/resources/endorsed/xalan.jar"/>
+ <classpathentry kind="lib"
path="src/test/resources/endorsed/xercesImpl.jar"/>
+ <classpathentry kind="lib"
path="src/test/resources/endorsed/xml-apis.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Modified:
identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java
===================================================================
---
identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java 2009-02-26
20:53:23 UTC (rev 350)
+++
identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java 2009-02-26
20:53:50 UTC (rev 351)
@@ -48,9 +48,13 @@
*/
public class XMLEncryptionUtil
{
+ public static final String CIPHER_DATA_LOCALNAME = "CipherData";
+ public static final String ENCRYPTED_KEY_LOCALNAME = "EncryptedKey";
+ public static final String DS_KEY_INFO = "ds:KeyInfo";
+
public static final String XMLNS = "http://www.w3.org/2000/xmlns/";
- private static String XMLSIG_NS = JBossSAMLURIConstants.XMLDSIG_NSURI.get();
- private static String XMLENC_NS = JBossSAMLURIConstants.XMLENC_NSURI.get();
+ public static String XMLSIG_NS = JBossSAMLURIConstants.XMLDSIG_NSURI.get();
+ public static String XMLENC_NS = JBossSAMLURIConstants.XMLENC_NSURI.get();
static
{
@@ -91,7 +95,104 @@
}
/**
- * Encrypt an element inside a Document.
+ * Given an element in a Document, encrypt the element and replace
+ * the element in the document with the encrypted data
+ * @param elementQName QName of the element that we like to encrypt
+ * @param publicKey
+ * @param secretKey
+ * @param keySize
+ * @param wrappingElementQName A QName of an element that will wrap the encrypted
element
+ * @param addEncryptedKeyInKeyInfo Need for the EncryptedKey to be placed in
ds:KeyInfo
+ * @return
+ * @throws Exception
+ */
+ public static void encryptElement(QName elementQName,
+ Document document,
+ PublicKey publicKey,
+ SecretKey secretKey, int keySize, QName wrappingElementQName,
+ boolean addEncryptedKeyInKeyInfo) throws Exception
+ {
+ if(elementQName == null)
+ throw new IllegalArgumentException("elementQName is null");
+ if(document == null)
+ throw new IllegalArgumentException("document is null");
+ String wrappingElementPrefix = wrappingElementQName.getPrefix();
+ if(wrappingElementPrefix == null || wrappingElementPrefix == "")
+ throw new IllegalArgumentException("Wrapping element prefix
invalid");
+
+ NodeList elements = document.getElementsByTagName(elementQName.toString());
+ if(elements == null || elements.getLength() > 1)
+ throw new IllegalStateException("Element was either null or more than
one:"+elements);
+ Element documentElement = (Element) elements.item(0);
+
+ if(documentElement == null)
+ throw new IllegalStateException("Element could not be found in the
document:"+ elementQName.toString());
+
+ XMLCipher cipher = null;
+ EncryptedKey encryptedKey = encryptKey(document, secretKey, publicKey, keySize);
+
+ String encryptionAlgorithm = getXMLEncryptionURL(secretKey.getAlgorithm(),
keySize);
+ //Encrypt the Document
+ cipher = XMLCipher.getInstance(encryptionAlgorithm);
+ cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+
+ Document encryptedDoc = cipher.doFinal(document, documentElement);
+
+ // The EncryptedKey element is added
+ Element encryptedKeyElement = cipher.martial(document, encryptedKey);
+
+ String wrappingElementName = wrappingElementPrefix + ":" +
wrappingElementQName.getLocalPart();
+
+ //Create the wrapping element and set its attribute NS
+ Element wrappingElement =
encryptedDoc.createElementNS(wrappingElementQName.getNamespaceURI(),
+ wrappingElementName);
+
+ if(wrappingElementPrefix == null || wrappingElementPrefix == "")
+ {
+ wrappingElementName = wrappingElementQName.getLocalPart();
+ }
+ wrappingElement.setAttributeNS(XMLNS,
+ "xmlns:" + wrappingElementPrefix,
wrappingElementQName.getNamespaceURI());
+
+ //Get Hold of the Cipher Data
+ NodeList cipherElements = encryptedDoc.getElementsByTagNameNS(XMLENC_NS,
"EncryptedData");
+ if(cipherElements == null || cipherElements.getLength() == 0)
+ throw new IllegalStateException("xenc:EncryptedData Element
Missing");
+ Element encryptedDataElement = (Element) cipherElements.item(0);
+
+ Node parentOfEncNode = encryptedDataElement.getParentNode();
+ parentOfEncNode.replaceChild(wrappingElement, encryptedDataElement);
+
+ wrappingElement.appendChild(encryptedDataElement);
+
+ if (addEncryptedKeyInKeyInfo)
+ {
+ // Outer ds:KeyInfo Element to hold the EncryptionKey
+ Element sigElement = encryptedDoc.createElementNS(XMLSIG_NS, DS_KEY_INFO);
+ sigElement.setAttributeNS(XMLNS, "xmlns:ds", XMLSIG_NS);
+ sigElement.appendChild(encryptedKeyElement);
+
+ //Insert the Encrypted key before the CipherData element
+ NodeList nodeList = encryptedDoc.getElementsByTagNameNS(XMLENC_NS,
CIPHER_DATA_LOCALNAME);
+ if (nodeList == null || nodeList.getLength() == 0)
+ throw new IllegalStateException("xenc:CipherData Element Missing");
+ Element cipherDataElement = (Element) nodeList.item(0);
+ Node cipherParent = cipherDataElement.getParentNode();
+ cipherParent.insertBefore(sigElement, cipherDataElement);
+ }
+ else
+ {
+ //Add the encrypted key as a child of the wrapping element
+ wrappingElement.appendChild(encryptedKeyElement);
+ }
+ }
+
+
+ /**
+ * Encrypt the root document element inside a Document.
+ * <b>NOTE:</> The document root element will be replaced
+ * by the wrapping element.
+ *
* @param document Document that contains an element to encrypt
* @param publicKey The Public Key used to encrypt the secret encryption key
* @param secretKey The secret encryption key
@@ -103,10 +204,15 @@
* @return An element that has the wrappingElementQName
* @throws Exception
*/
- public static Element encryptElementInDocument(Document document, PublicKey
publicKey,
+ public static Element encryptElementInDocument(Document document,
+ PublicKey publicKey,
SecretKey secretKey, int keySize, QName wrappingElementQName,
boolean addEncryptedKeyInKeyInfo) throws Exception
{
+ String wrappingElementPrefix = wrappingElementQName.getPrefix();
+ if(wrappingElementPrefix == null || wrappingElementPrefix == "")
+ throw new IllegalArgumentException("Wrapping element prefix
invalid");
+
XMLCipher cipher = null;
EncryptedKey encryptedKey = encryptKey(document, secretKey, publicKey, keySize);
@@ -120,12 +226,18 @@
// The EncryptedKey element is added
Element encryptedKeyElement = cipher.martial(document, encryptedKey);
+ String wrappingElementName = wrappingElementPrefix + ":" +
wrappingElementQName.getLocalPart();
+
//Create the wrapping element and set its attribute NS
Element wrappingElement =
encryptedDoc.createElementNS(wrappingElementQName.getNamespaceURI(),
- wrappingElementQName.getPrefix() + ":" +
wrappingElementQName.getLocalPart());
+ wrappingElementName);
+ if(wrappingElementPrefix == null || wrappingElementPrefix == "")
+ {
+ wrappingElementName = wrappingElementQName.getLocalPart();
+ }
wrappingElement.setAttributeNS(XMLNS,
- "xmlns:" + wrappingElementQName.getPrefix(),
wrappingElementQName.getNamespaceURI());
+ "xmlns:" + wrappingElementPrefix,
wrappingElementQName.getNamespaceURI());
Element encryptedDocRootElement = encryptedDoc.getDocumentElement();
//Bring in the encrypted wrapping element to wrap the root node
@@ -136,13 +248,13 @@
if (addEncryptedKeyInKeyInfo)
{
// Outer ds:KeyInfo Element to hold the EncryptionKey
- Element sigElement = encryptedDoc.createElementNS(XMLSIG_NS,
"ds:KeyInfo");
+ Element sigElement = encryptedDoc.createElementNS(XMLSIG_NS, DS_KEY_INFO);
sigElement.setAttributeNS(XMLNS, "xmlns:ds", XMLSIG_NS);
sigElement.appendChild(encryptedKeyElement);
//Insert the Encrypted key before the CipherData element
- NodeList nodeList = encryptedDocRootElement.getElementsByTagNameNS(XMLENC_NS,
"CipherData");
- if ((nodeList == null) || (nodeList.getLength() == 0))
+ NodeList nodeList = encryptedDocRootElement.getElementsByTagNameNS(XMLENC_NS,
CIPHER_DATA_LOCALNAME);
+ if (nodeList == null || nodeList.getLength() == 0)
throw new IllegalStateException("xenc:CipherData Element Missing");
Element cipherDataElement = (Element) nodeList.item(0);
@@ -155,9 +267,8 @@
}
return encryptedDoc.getDocumentElement();
- }
+ }
-
/**
* Decrypt an encrypted element inside a document
* @param documentWithEncryptedElement
@@ -182,7 +293,7 @@
if(encKeyElement == null)
{
//Search the enc data element for enc key
- NodeList nodeList = encDataElement.getElementsByTagNameNS( XMLENC_NS,
"EncryptedKey");
+ NodeList nodeList = encDataElement.getElementsByTagNameNS( XMLENC_NS,
ENCRYPTED_KEY_LOCALNAME);
if(nodeList == null || nodeList.getLength() == 0)
throw new IllegalStateException("Encrypted Key not found in the enc
data");
Modified:
identity-federation/trunk/identity-fed-api/src/test/java/org/jboss/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java
===================================================================
---
identity-federation/trunk/identity-fed-api/src/test/java/org/jboss/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java 2009-02-26
20:53:23 UTC (rev 350)
+++
identity-federation/trunk/identity-fed-api/src/test/java/org/jboss/test/identity/federation/api/util/XMLEncryptionUnitTestCase.java 2009-02-26
20:53:50 UTC (rev 351)
@@ -25,6 +25,7 @@
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
@@ -48,6 +49,8 @@
import org.jboss.identity.federation.saml.v2.protocol.ResponseType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
@@ -126,6 +129,57 @@
assertEquals("http://identityurl", assertion.getIssuer().getValue());
}
+
+ public void testArbitraryXML() throws Exception
+ {
+ String myXML =
"<somexml><a><b></b></a></somexml>";
+
+ KeyPair kp = this.getKeyPair("RSA");
+ SecretKey sk = this.getSecretKey();
+
+ PublicKey publicKey = kp.getPublic();
+
+ Document doc = DocumentUtil.getDocument(myXML);
+ QName qname = new QName("urn:test", "encryptedA",
"someprefix");
+
+ QName elementAQname = new QName("a");
+
+ XMLEncryptionUtil.encryptElement(elementAQname, doc,
+ publicKey, sk, 256, qname, true);
+
+ //Let us verify the document: The original document that has been passed has been
updated
+ NodeList nl = doc.getElementsByTagNameNS(XMLEncryptionUtil.XMLENC_NS,
+ XMLEncryptionUtil.ENCRYPTED_KEY_LOCALNAME);
+ assertTrue(nl != null && nl.getLength() == 1);
+
+ Node wrappedNode = doc.getDocumentElement().getFirstChild();
+ assertEquals(wrappedNode.getLocalName(),qname.getLocalPart());
+ assertEquals(wrappedNode.getNamespaceURI(), qname.getNamespaceURI());
+ assertEquals(wrappedNode.getPrefix(), qname.getPrefix());
+ }
+
+ public void testArbitraryXMLWithOuterKeyInfo() throws Exception
+ {
+ String myXML =
"<somexml><a><b></b></a></somexml>";
+
+ KeyPair kp = this.getKeyPair("RSA");
+ SecretKey sk = this.getSecretKey();
+
+ PublicKey publicKey = kp.getPublic();
+
+ Document doc = DocumentUtil.getDocument(myXML);
+ QName qname = new QName("urn:test", "encryptedA",
"someprefix");
+
+ QName elementAQname = new QName("a");
+
+ XMLEncryptionUtil.encryptElement(elementAQname, doc,
+ publicKey, sk, 256, qname, false);
+
+ //Let us verify the document: The original document that has been passed has been
updated
+ NodeList nl = doc.getElementsByTagNameNS(XMLEncryptionUtil.XMLENC_NS,
+ XMLEncryptionUtil.ENCRYPTED_KEY_LOCALNAME);
+ assertTrue(nl != null && nl.getLength() == 1);
+ }
private ResponseType createResponse() throws Exception
{
List<String> roles = new ArrayList<String>();