Author: anil.saldhana(a)jboss.com
Date: 2009-03-26 11:55:38 -0400 (Thu, 26 Mar 2009)
New Revision: 402
Removed:
identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java
Log:
move xml encryption util
Deleted:
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-03-26
15:55:17 UTC (rev 401)
+++
identity-federation/trunk/identity-fed-api/src/main/java/org/jboss/identity/federation/api/util/XMLEncryptionUtil.java 2009-03-26
15:55:38 UTC (rev 402)
@@ -1,396 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.jboss.identity.federation.api.util;
-
-import java.security.Key;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import javax.crypto.SecretKey;
-import javax.xml.namespace.QName;
-
-import org.apache.xml.security.encryption.EncryptedData;
-import org.apache.xml.security.encryption.EncryptedKey;
-import org.apache.xml.security.encryption.XMLCipher;
-import org.jboss.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * XML Encryption Util
- * <b>Note: </b> This utility is currently using Apache XML Security
- * library API. JSR-106 is not yet final. Until that happens,we
- * rely on the non-standard API.
- *
- * @author Anil.Saldhana(a)redhat.com
- * @since Feb 4, 2009
- */
-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/";
- public static String XMLSIG_NS = JBossSAMLURIConstants.XMLDSIG_NSURI.get();
- public static String XMLENC_NS = JBossSAMLURIConstants.XMLENC_NSURI.get();
-
- static
- {
- //Initialize the Apache XML Security Library
- org.apache.xml.security.Init.init();
- }
-
- /**
- * <p>
- * Encrypt the Key to be transported
- * </p>
- * <p>
- * Data is encrypted with a SecretKey. Then the key needs to be
- * transported to the other end where it is needed for decryption.
- * For the Key transport, the SecretKey is encrypted with the
- * recipient's public key. At the receiving end, the receiver
- * can decrypt the Secret Key using his private key.s
- * </p>
- * @param document
- * @param keyToBeEncrypted Symmetric Key (SecretKey)
- * @param keyUsedToEncryptSecretKey Asymmetric Key (Public Key)
- * @param keySize Length of the key
- * @return
- * @throws Exception
- */
- public static EncryptedKey encryptKey(Document document,
- SecretKey keyToBeEncrypted, PublicKey keyUsedToEncryptSecretKey,
- int keySize) throws Exception
- {
- XMLCipher keyCipher = null;
- String pubKeyAlg = keyUsedToEncryptSecretKey.getAlgorithm();
-
- String keyWrapAlgo = getXMLEncryptionURLForKeyUnwrap(pubKeyAlg, keySize);
- keyCipher = XMLCipher.getInstance(keyWrapAlgo);
-
- keyCipher.init(XMLCipher.WRAP_MODE, keyUsedToEncryptSecretKey);
- return keyCipher.encryptKey(document, keyToBeEncrypted);
- }
-
- /**
- * 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
- * @param keySize Length of key
- * @param wrappingElementQName QName of the element to be used to wrap around
- * the cipher data.
- * @param addEncryptedKeyInKeyInfo Should the encrypted key be inside a KeyInfo
- * or added as a peer of Cipher Data
- * @return An element that has the wrappingElementQName
- * @throws Exception
- */
- 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);
-
- String encryptionAlgorithm = getXMLEncryptionURL(secretKey.getAlgorithm(),
keySize);
- //Encrypt the Document
- cipher = XMLCipher.getInstance(encryptionAlgorithm);
- cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
-
- Document encryptedDoc = cipher.doFinal(document, document.getDocumentElement());
-
- // 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());
-
- Element encryptedDocRootElement = encryptedDoc.getDocumentElement();
- //Bring in the encrypted wrapping element to wrap the root node
- encryptedDoc.replaceChild(wrappingElement, encryptedDocRootElement);
-
- wrappingElement.appendChild(encryptedDocRootElement);
-
- 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 = 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);
- encryptedDocRootElement.insertBefore(sigElement, cipherDataElement);
- }
- else
- {
- //Add the encrypted key as a child of the wrapping element
- wrappingElement.appendChild(encryptedKeyElement);
- }
-
- return encryptedDoc.getDocumentElement();
- }
-
- /**
- * Decrypt an encrypted element inside a document
- * @param documentWithEncryptedElement
- * @param privateKey key need to unwrap the encryption key
- * @return the document with the encrypted element replaced by the data element
- * @throws Exception
- */
- public static Element decryptElementInDocument(Document documentWithEncryptedElement,
- PrivateKey privateKey) throws Exception
- {
- if(documentWithEncryptedElement == null)
- throw new IllegalArgumentException("Input document is null");
-
- //Look for encrypted data element
- Element documentRoot = documentWithEncryptedElement.getDocumentElement();
- Element encDataElement = getNextElementNode(documentRoot.getFirstChild());
- if(encDataElement == null)
- throw new IllegalStateException("No element representing the encrypted data
found");
-
- //Look at siblings for the key
- Element encKeyElement = getNextElementNode(encDataElement.getNextSibling());
- if(encKeyElement == null)
- {
- //Search the enc data element for enc key
- 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");
-
- encKeyElement = (Element) nodeList.item(0);
- }
-
- XMLCipher cipher = XMLCipher.getInstance();
- cipher.init(XMLCipher.DECRYPT_MODE, null);
- EncryptedData encryptedData =
cipher.loadEncryptedData(documentWithEncryptedElement, encDataElement);
- EncryptedKey encryptedKey = cipher.loadEncryptedKey(documentWithEncryptedElement,
encKeyElement);
-
- Document decryptedDoc = null;
-
- if (encryptedData != null && encryptedKey != null)
- {
- String encAlgoURL = encryptedData.getEncryptionMethod().getAlgorithm();
- XMLCipher keyCipher = XMLCipher.getInstance();
- keyCipher.init(XMLCipher.UNWRAP_MODE, privateKey);
- Key encryptionKey = keyCipher.decryptKey( encryptedKey, encAlgoURL );
- cipher = XMLCipher.getInstance();
- cipher.init(XMLCipher.DECRYPT_MODE, encryptionKey);
- decryptedDoc = cipher.doFinal(documentWithEncryptedElement, encDataElement);
- }
-
- Element decryptedRoot = decryptedDoc.getDocumentElement();
- Element dataElement = getNextElementNode(decryptedRoot.getFirstChild());
- if (dataElement == null)
- throw new IllegalStateException("Data Element after encryption is
null");
-
- decryptedRoot.removeChild(dataElement);
- decryptedDoc.replaceChild(dataElement, decryptedRoot);
-
- return decryptedDoc.getDocumentElement();
- }
-
- /**
- * From the secret key, get the W3C XML Encryption URL
- * @param publicKeyAlgo
- * @param keySize
- * @return
- */
- private static String getXMLEncryptionURLForKeyUnwrap(String publicKeyAlgo, int
keySize)
- {
- if("AES".equals(publicKeyAlgo))
- {
- switch(keySize)
- {
- case 192: return XMLCipher.AES_192_KeyWrap;
- case 256: return XMLCipher.AES_256_KeyWrap;
- default:
- return XMLCipher.AES_128_KeyWrap;
- }
- }
- if(publicKeyAlgo.contains("RSA"))
- return XMLCipher.RSA_v1dot5;
- if(publicKeyAlgo.contains("DES"))
- return XMLCipher.TRIPLEDES_KeyWrap;
- throw new IllegalArgumentException("unsupported publicKey Algo:" +
publicKeyAlgo);
- }
-
- /**
- * From the secret key, get the W3C XML Encryption URL
- * @param secretKey
- * @param keySize
- * @return
- */
- private static String getXMLEncryptionURL(String algo, int keySize)
- {
- if("AES".equals(algo))
- {
- switch(keySize)
- {
- case 192: return XMLCipher.AES_192;
- case 256: return XMLCipher.AES_256;
- default:
- return XMLCipher.AES_128;
- }
- }
- if(algo.contains("RSA"))
- return XMLCipher.RSA_v1dot5;
- if(algo.contains("DES"))
- return XMLCipher.TRIPLEDES_KeyWrap;
- throw new IllegalArgumentException("Secret Key with unsupported algo:" +
algo);
- }
-
- /**
- * Returns the next Element node.
- */
- private static Element getNextElementNode(Node node)
- {
- while(node != null)
- {
- if(Node.ELEMENT_NODE == node.getNodeType())
- return (Element) node;
- node = node.getNextSibling();
- }
- return null;
- }
-}
\ No newline at end of file