keycloak-aplcache
Merge pull request #3491 from hmlnarik/KEYCLOAK-3087-XmlEncryptionUtil KEYCLOAK-3087 …
            11/16/2016 9:17:26 AM
        
        
        
            
        Changes
Details
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLEncryptionUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLEncryptionUtil.java
index 245cff9..f81ea03 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLEncryptionUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLEncryptionUtil.java
@@ -20,6 +20,7 @@ import org.apache.xml.security.encryption.EncryptedData;
 import org.apache.xml.security.encryption.EncryptedKey;
 import org.apache.xml.security.encryption.XMLCipher;
 import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.utils.EncryptionConstants;
 
 import org.keycloak.saml.common.PicketLinkLogger;
 import org.keycloak.saml.common.PicketLinkLoggerFactory;
@@ -38,8 +39,9 @@ import javax.xml.namespace.QName;
 import java.security.Key;
 import java.security.PrivateKey;
 import java.security.PublicKey;
-import java.util.HashMap;
 import java.util.Objects;
+import javax.xml.XMLConstants;
+import javax.xml.crypto.dsig.XMLSignature;
 
 /**
  * Utility for XML Encryption <b>Note: </b> This utility is currently using Apache XML Security library API. JSR-106 is
@@ -58,77 +60,12 @@ public class XMLEncryptionUtil {
         org.apache.xml.security.Init.init();
     }
 
-    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 final String XMLSIG_NS = "http://www.w3.org/2000/09/xmldsig#";
-
-    public static final String XMLENC_NS = "http://www.w3.org/2001/04/xmlenc#";
-
-    private static HashMap<String, EncryptionAlgorithm> algorithms = new HashMap<String, EncryptionAlgorithm>(4);
-
     private static final String RSA_ENCRYPTION_SCHEME = Objects.equals(System.getProperty("keycloak.saml.key_trans.rsa_v1.5"), "true")
       ? XMLCipher.RSA_v1dot5
       : XMLCipher.RSA_OAEP;
 
-    private static class EncryptionAlgorithm {
-
-        EncryptionAlgorithm(String jceName, String xmlSecName, int size) {
-            this.jceName = jceName;
-            this.xmlSecName = xmlSecName;
-            this.size = size;
-        }
-
-        @SuppressWarnings("unused")
-        public String jceName;
-
-        public String xmlSecName;
-
-        public int size;
-    }
-
-    static {
-        algorithms.put("aes-128", new EncryptionAlgorithm("AES", XMLCipher.AES_128, 128));
-        algorithms.put("aes-192", new EncryptionAlgorithm("AES", XMLCipher.AES_192, 192));
-        algorithms.put("aes-256", new EncryptionAlgorithm("AES", XMLCipher.AES_256, 256));
-        algorithms.put("aes", new EncryptionAlgorithm("AES", XMLCipher.AES_256, 256));
-
-        algorithms.put("tripledes", new EncryptionAlgorithm("TripleDes", XMLCipher.TRIPLEDES, 168));
-    }
-
-    /**
-     * Given the JCE algorithm, get the XML Encryption URL
-     *
-     * @param certAlgo
-     *
-     * @return
-     */
-    public static String getEncryptionURL(String certAlgo) {
-        EncryptionAlgorithm ea = algorithms.get(certAlgo);
-        if (ea == null)
-            throw logger.encryptUnknownAlgoError(certAlgo);
-        return ea.xmlSecName;
-    }
-
-    /**
-     * Given the JCE algorithm, get the XML Encryption KeySize
-     *
-     * @param certAlgo
-     *
-     * @return
-     */
-    public static int getEncryptionKeySize(String certAlgo) {
-        EncryptionAlgorithm ea = algorithms.get(certAlgo);
-        if (ea == null)
-            throw logger.encryptUnknownAlgoError(certAlgo);
-        return ea.size;
-    }
-
     /**
      * <p>
      * Encrypt the Key to be transported
@@ -151,7 +88,7 @@ public class XMLEncryptionUtil {
      */
     public static EncryptedKey encryptKey(Document document, SecretKey keyToBeEncrypted, PublicKey keyUsedToEncryptSecretKey,
                                           int keySize) throws ProcessingException {
-        XMLCipher keyCipher = null;
+        XMLCipher keyCipher;
         String pubKeyAlg = keyUsedToEncryptSecretKey.getAlgorithm();
 
         try {
@@ -170,14 +107,13 @@ public class XMLEncryptionUtil {
      * data
      *
      * @param elementQName QName of the element that we like to encrypt
+     * @param document
      * @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 ProcessingException
      */
     public static void encryptElement(QName elementQName, Document document, PublicKey publicKey, SecretKey secretKey,
@@ -187,7 +123,7 @@ public class XMLEncryptionUtil {
         if (document == null)
             throw logger.nullArgumentError("document");
         String wrappingElementPrefix = wrappingElementQName.getPrefix();
-        if (wrappingElementPrefix == null || wrappingElementPrefix == "")
+        if (wrappingElementPrefix == null || "".equals(wrappingElementPrefix))
             throw logger.wrongTypeError("Wrapping element prefix invalid");
 
         Element documentElement = DocumentUtil.getElement(document, elementQName);
@@ -217,18 +153,22 @@ public class XMLEncryptionUtil {
         // The EncryptedKey element is added
         Element encryptedKeyElement = cipher.martial(document, encryptedKey);
 
-        String wrappingElementName = wrappingElementPrefix + ":" + wrappingElementQName.getLocalPart();
+        final String wrappingElementName;
 
+        if (StringUtil.isNullOrEmpty(wrappingElementPrefix)) {
+            wrappingElementName = wrappingElementQName.getLocalPart();
+        } else {
+            wrappingElementName = wrappingElementPrefix + ":" + wrappingElementQName.getLocalPart();
+        }
         // Create the wrapping element and set its attribute NS
         Element wrappingElement = encryptedDoc.createElementNS(wrappingElementQName.getNamespaceURI(), wrappingElementName);
 
-        if (StringUtil.isNullOrEmpty(wrappingElementPrefix)) {
-            wrappingElementName = wrappingElementQName.getLocalPart();
+        if (! StringUtil.isNullOrEmpty(wrappingElementPrefix)) {
+            wrappingElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:" + wrappingElementPrefix, wrappingElementQName.getNamespaceURI());
         }
-        wrappingElement.setAttributeNS(XMLNS, "xmlns:" + wrappingElementPrefix, wrappingElementQName.getNamespaceURI());
 
         // Get Hold of the Cipher Data
-        NodeList cipherElements = encryptedDoc.getElementsByTagNameNS(XMLENC_NS, "EncryptedData");
+        NodeList cipherElements = encryptedDoc.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_ENCRYPTEDDATA);
         if (cipherElements == null || cipherElements.getLength() == 0)
             throw logger.domMissingElementError("xenc:EncryptedData");
         Element encryptedDataElement = (Element) cipherElements.item(0);
@@ -240,12 +180,12 @@ public class XMLEncryptionUtil {
 
         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);
+            Element sigElement = encryptedDoc.createElementNS(XMLSignature.XMLNS, DS_KEY_INFO);
+            sigElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:ds", XMLSignature.XMLNS);
             sigElement.appendChild(encryptedKeyElement);
 
             // Insert the Encrypted key before the CipherData element
-            NodeList nodeList = encryptedDoc.getElementsByTagNameNS(XMLENC_NS, CIPHER_DATA_LOCALNAME);
+            NodeList nodeList = encryptedDoc.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA);
             if (nodeList == null || nodeList.getLength() == 0)
                 throw logger.domMissingElementError("xenc:CipherData");
             Element cipherDataElement = (Element) nodeList.item(0);
@@ -328,12 +268,12 @@ public class XMLEncryptionUtil {
         Element encryptedKeyElement = cipher.martial(document, encryptedKey);
 
         // Outer ds:KeyInfo Element to hold the EncryptionKey
-        Element sigElement = encryptedDoc.createElementNS(XMLSIG_NS, DS_KEY_INFO);
-        sigElement.setAttributeNS(XMLNS, "xmlns:ds", XMLSIG_NS);
+        Element sigElement = encryptedDoc.createElementNS(XMLSignature.XMLNS, DS_KEY_INFO);
+        sigElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:ds", XMLSignature.XMLNS);
         sigElement.appendChild(encryptedKeyElement);
 
         // Insert the Encrypted key before the CipherData element
-        NodeList nodeList = encryptedDoc.getElementsByTagNameNS(XMLENC_NS, CIPHER_DATA_LOCALNAME);
+        NodeList nodeList = encryptedDoc.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA);
         if (nodeList == null || nodeList.getLength() == 0)
             throw logger.domMissingElementError("xenc:CipherData");
         Element cipherDataElement = (Element) nodeList.item(0);
@@ -342,7 +282,7 @@ public class XMLEncryptionUtil {
     }
 
     /**
-     * Encrypt the root document element inside a Document. <b>NOTE:</> The document root element will be replaced by
+     * Encrypt the root document element inside a Document. <b>NOTE:</b> The document root element will be replaced by
      * the
      * wrapping element.
      *
@@ -361,7 +301,7 @@ public class XMLEncryptionUtil {
     public static Element encryptElementInDocument(Document document, PublicKey publicKey, SecretKey secretKey, int keySize,
                                                    QName wrappingElementQName, boolean addEncryptedKeyInKeyInfo) throws ProcessingException, ConfigurationException {
         String wrappingElementPrefix = wrappingElementQName.getPrefix();
-        if (wrappingElementPrefix == null || wrappingElementPrefix == "")
+        if (wrappingElementPrefix == null || "".equals(wrappingElementPrefix))
             throw logger.wrongTypeError("Wrapping element prefix invalid");
 
         XMLCipher cipher = null;
@@ -386,15 +326,19 @@ public class XMLEncryptionUtil {
         // The EncryptedKey element is added
         Element encryptedKeyElement = cipher.martial(document, encryptedKey);
 
-        String wrappingElementName = wrappingElementPrefix + ":" + wrappingElementQName.getLocalPart();
+        final String wrappingElementName;
 
+        if (StringUtil.isNullOrEmpty(wrappingElementPrefix)) {
+            wrappingElementName = wrappingElementQName.getLocalPart();
+        } else {
+            wrappingElementName = wrappingElementPrefix + ":" + wrappingElementQName.getLocalPart();
+        }
         // Create the wrapping element and set its attribute NS
         Element wrappingElement = encryptedDoc.createElementNS(wrappingElementQName.getNamespaceURI(), wrappingElementName);
 
-        if (StringUtil.isNullOrEmpty(wrappingElementPrefix)) {
-            wrappingElementName = wrappingElementQName.getLocalPart();
+        if (! StringUtil.isNullOrEmpty(wrappingElementPrefix)) {
+            wrappingElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:" + wrappingElementPrefix, wrappingElementQName.getNamespaceURI());
         }
-        wrappingElement.setAttributeNS(XMLNS, "xmlns:" + wrappingElementPrefix, wrappingElementQName.getNamespaceURI());
 
         Element encryptedDocRootElement = encryptedDoc.getDocumentElement();
         // Bring in the encrypted wrapping element to wrap the root node
@@ -404,12 +348,12 @@ public class XMLEncryptionUtil {
 
         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);
+            Element sigElement = encryptedDoc.createElementNS(XMLSignature.XMLNS, DS_KEY_INFO);
+            sigElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:ds", XMLSignature.XMLNS);
             sigElement.appendChild(encryptedKeyElement);
 
             // Insert the Encrypted key before the CipherData element
-            NodeList nodeList = encryptedDocRootElement.getElementsByTagNameNS(XMLENC_NS, CIPHER_DATA_LOCALNAME);
+            NodeList nodeList = encryptedDocRootElement.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA);
             if (nodeList == null || nodeList.getLength() == 0)
                 throw logger.domMissingElementError("xenc:CipherData");
 
@@ -430,9 +374,6 @@ public class XMLEncryptionUtil {
      * @param privateKey key need to unwrap the encryption key
      *
      * @return the document with the encrypted element replaced by the data element
-     *
-     * @throws XMLEncryptionException
-     * @throws ProcessingException
      */
     public static Element decryptElementInDocument(Document documentWithEncryptedElement, PrivateKey privateKey)
             throws ProcessingException {
@@ -449,7 +390,7 @@ public class XMLEncryptionUtil {
         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);
+            NodeList nodeList = encDataElement.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_ENCRYPTEDKEY);
 
             if (nodeList == null || nodeList.getLength() == 0)
                 throw logger.nullValueError("Encrypted Key not found in the enc data");
@@ -522,8 +463,6 @@ public class XMLEncryptionUtil {
         }
         if (publicKeyAlgo.contains("RSA"))
             return RSA_ENCRYPTION_SCHEME;
-        if (publicKeyAlgo.contains("DES"))
-            return XMLCipher.TRIPLEDES_KeyWrap;
         throw logger.unsupportedType("unsupported publicKey Algo:" + publicKeyAlgo);
     }
 
@@ -548,8 +487,6 @@ public class XMLEncryptionUtil {
         }
         if (algo.contains("RSA"))
             return XMLCipher.RSA_v1dot5;
-        if (algo.contains("DES"))
-            return XMLCipher.TRIPLEDES_KeyWrap;
         throw logger.unsupportedType("Secret Key with unsupported algo:" + algo);
     }