You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2015/06/24 11:39:01 UTC

svn commit: r1687219 - in /webservices/wss4j/trunk: ws-security-common/src/main/java/org/apache/wss4j/common/ ws-security-common/src/main/java/org/apache/wss4j/common/ext/ ws-security-dom/src/main/java/org/apache/wss4j/dom/action/ ws-security-dom/src/m...

Author: coheigea
Date: Wed Jun 24 09:39:00 2015
New Revision: 1687219

URL: http://svn.apache.org/r1687219
Log:
Allow the retrieval of a secret key for encryption from a CallbackHandler

Modified:
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/EncryptionActionToken.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ext/WSPasswordCallback.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionAction.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java Wed Jun 24 09:39:00 2015
@@ -532,6 +532,14 @@ public class ConfigurationConstants {
      */
     public static final String USE_2005_12_NAMESPACE = "use200512Namespace";
     
+    /**
+     * Whether to get a secret key from a CallbackHandler or not for encryption only. The default is
+     * false. If set to true WSS4J attempts to get the secret key from the CallbackHandler instead of
+     * generating a random key internally. This allows the user more control over the symmetric key
+     * if required.
+     */
+    public static final String GET_SECRET_KEY_FROM_CALLBACK_HANDLER = "getSecretKeyFromCallbackHandler";
+    
     //
     // (Non-boolean) Configuration parameters for the actions/processors
     //

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/EncryptionActionToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/EncryptionActionToken.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/EncryptionActionToken.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/EncryptionActionToken.java Wed Jun 24 09:39:00 2015
@@ -28,6 +28,7 @@ public class EncryptionActionToken exten
     private String mgfAlgorithm;
     private String symmetricAlgorithm;
     private String keyTransportAlgorithm;
+    private boolean getSymmetricKeyFromCallbackHandler;
     
     public boolean isEncSymmetricEncryptionKey() {
         return encSymmetricEncryptionKey;
@@ -53,6 +54,12 @@ public class EncryptionActionToken exten
     public void setKeyTransportAlgorithm(String keyTransportAlgorithm) {
         this.keyTransportAlgorithm = keyTransportAlgorithm;
     }
+    public boolean isGetSymmetricKeyFromCallbackHandler() {
+        return getSymmetricKeyFromCallbackHandler;
+    }
+    public void setGetSymmetricKeyFromCallbackHandler(boolean getSymmetricKeyFromCallbackHandler) {
+        this.getSymmetricKeyFromCallbackHandler = getSymmetricKeyFromCallbackHandler;
+    }
  
 }
 

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ext/WSPasswordCallback.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ext/WSPasswordCallback.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ext/WSPasswordCallback.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ext/WSPasswordCallback.java Wed Jun 24 09:39:00 2015
@@ -138,10 +138,12 @@ public class WSPasswordCallback implemen
     private String identifier;
     private String password;
     private byte[] secret;
+    private byte[] encryptedSecret;
     private Key key;
     private int usage;
     private String type;
     private Element customToken;
+    private String algorithm;
     
     /**
      * Constructor.
@@ -264,5 +266,43 @@ public class WSPasswordCallback implemen
     public void setCustomToken(Element customToken) {
         this.customToken = customToken;
     }
+
+    /**
+     * Get the Encrypted Secret. The CallbackHandler may return an encrypted version of the secret key
+     * to be used, instead of having WSS4J explicitly encrypt the key. Alternatively, the recipient can
+     * call this with the cipher content of the EncryptedKey, if a symmetric key wrap algorithm is used.
+     *
+     */
+    public byte[] getEncryptedSecret() {
+        return encryptedSecret;
+    }
+
+    /**
+     * Set the Encrypted Secret. The CallbackHandler may return an encrypted version of the secret key
+     * to be used, instead of having WSS4J explicitly encrypt the key. Alternatively, the recipient can
+     * call this with the cipher content of the EncryptedKey, if a symmetric key wrap algorithm is used.
+     *  
+     * @param encryptedSecret
+     */
+    public void setEncryptedSecret(byte[] encryptedSecret) {
+        this.encryptedSecret = encryptedSecret;
+    }
+    
+    /**
+     * Get the algorithm to be used. For example, a different secret key might be returned depending
+     * on the algorithm.
+     */
+    public String getAlgorithm() {
+        return algorithm;
+    }
+
+    /**
+     * Specify an algorithm to be used. For example, a different secret key might be returned depending
+     * on the algorithm.
+     */
+    public void setAlgorithm(String algorithm) {
+        this.algorithm = algorithm;
+    }
+
     
 }
\ No newline at end of file

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionAction.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionAction.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/action/EncryptionAction.java Wed Jun 24 09:39:00 2015
@@ -88,13 +88,17 @@ public class EncryptionAction implements
         }
         
         wsEncrypt.setEncryptSymmKey(encryptionToken.isEncSymmetricEncryptionKey());
+        
         byte[] ephemeralKey = encryptionToken.getKey();
-        if (!encryptionToken.isEncSymmetricEncryptionKey() && ephemeralKey == null) {
+        if (encryptionToken.isGetSymmetricKeyFromCallbackHandler()
+            || !encryptionToken.isEncSymmetricEncryptionKey() && ephemeralKey == null) {
             CallbackHandler callbackHandler = 
                 handler.getPasswordCallbackHandler(reqData);
             WSPasswordCallback passwordCallback = 
                 handler.getPasswordCB(encryptionToken.getUser(), WSConstants.ENCR, callbackHandler, reqData);
             ephemeralKey = passwordCallback.getKey();
+            byte[] encryptedKey = passwordCallback.getEncryptedSecret();
+            wsEncrypt.setEncryptedEphemeralKey(encryptedKey);
         }
         wsEncrypt.setEphemeralKey(ephemeralKey);
         

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java Wed Jun 24 09:39:00 2015
@@ -709,6 +709,10 @@ public abstract class WSHandler {
             decodeBooleanConfigValue(mc, WSHandlerConstants.USE_2005_12_NAMESPACE, true);
         reqData.setUse200512Namespace(use200512Namespace);
         
+        boolean getSecretKeyFromCallbackHandler = 
+            decodeBooleanConfigValue(mc, WSHandlerConstants.GET_SECRET_KEY_FROM_CALLBACK_HANDLER, false);
+        actionToken.setGetSymmetricKeyFromCallbackHandler(getSecretKeyFromCallbackHandler);
+        
         String digestAlgo = getString(WSHandlerConstants.ENC_DIGEST_ALGO, mc);
         actionToken.setDigestAlgorithm(digestAlgo);
 

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncrypt.java Wed Jun 24 09:39:00 2015
@@ -133,7 +133,7 @@ public class WSSecEncrypt extends WSSecE
         // Get the certificate that contains the public key for the public key
         // algorithm that will encrypt the generated symmetric (session) key.
         //
-        if (encryptSymmKey) {
+        if (encryptSymmKey && encryptedEphemeralKey == null) {
             X509Certificate remoteCert = getUseThisCert();
             if (remoteCert == null) {
                 CryptoType cryptoType = null;
@@ -154,6 +154,8 @@ public class WSSecEncrypt extends WSSecE
                 remoteCert = certs[0];
             }
             prepareInternal(symmetricKey, remoteCert, crypto);
+        } else if (encryptedEphemeralKey != null) {
+            prepareInternal(symmetricKey);
         } else {
             encryptedEphemeralKey = symmetricKey.getEncoded();
         }
@@ -197,6 +199,7 @@ public class WSSecEncrypt extends WSSecE
 
         prependBSTElementToHeader(secHeader);
 
+        clean();
         LOG.debug("Encryption complete.");
         return doc;
     }

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java?rev=1687219&r1=1687218&r2=1687219&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/message/WSSecEncryptedKey.java Wed Jun 24 09:39:00 2015
@@ -164,6 +164,13 @@ public class WSSecEncryptedKey extends W
         return encKeyId;
     }
 
+    public void clean() {
+        ephemeralKey = null;
+        symmetricKey = null;
+        encryptedEphemeralKey = null;
+    }
+    
+
     /**
      * Prepare the ephemeralKey and the tokens required to be added to the
      * security header
@@ -189,31 +196,35 @@ public class WSSecEncryptedKey extends W
             }
         }
         
-        //
-        // Get the certificate that contains the public key for the public key
-        // algorithm that will encrypt the generated symmetric (session) key.
-        //
-        X509Certificate remoteCert = useThisCert;
-        if (remoteCert == null) {
-            CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
-            cryptoType.setAlias(user);
-            if (crypto == null) {
-                throw new WSSecurityException(
-                                              WSSecurityException.ErrorCode.FAILURE,
-                                              "noUserCertsFound",
-                                              new Object[] {user, "encryption"});
-            }
-            X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
-            if (certs == null || certs.length <= 0) {
-                throw new WSSecurityException(
-                    WSSecurityException.ErrorCode.FAILURE,
-                    "noUserCertsFound",
-                    new Object[] {user, "encryption"});
+        if (encryptedEphemeralKey == null) {
+            //
+            // Get the certificate that contains the public key for the public key
+            // algorithm that will encrypt the generated symmetric (session) key.
+            //
+            X509Certificate remoteCert = useThisCert;
+            if (remoteCert == null) {
+                CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+                cryptoType.setAlias(user);
+                if (crypto == null) {
+                    throw new WSSecurityException(
+                                                  WSSecurityException.ErrorCode.FAILURE,
+                                                  "noUserCertsFound",
+                                                  new Object[] {user, "encryption"});
+                }
+                X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
+                if (certs == null || certs.length <= 0) {
+                    throw new WSSecurityException(
+                        WSSecurityException.ErrorCode.FAILURE,
+                        "noUserCertsFound",
+                        new Object[] {user, "encryption"});
+                }
+                remoteCert = certs[0];
             }
-            remoteCert = certs[0];
+            
+            prepareInternal(symmetricKey, remoteCert, crypto);
+        } else {
+            prepareInternal(symmetricKey);
         }
-        
-        prepareInternal(symmetricKey, remoteCert, crypto);
     }
 
     /**
@@ -420,6 +431,88 @@ public class WSSecEncryptedKey extends W
         xencCipherValue.appendChild(keyText);
     }
     
+    protected void prepareInternal(SecretKey secretKey) throws WSSecurityException {
+        Text keyText = 
+            WSSecurityUtil.createBase64EncodedTextNode(document, encryptedEphemeralKey);
+
+        encryptedKeyElement = createEncryptedKey(document, keyEncAlgo);
+        if (encKeyId == null || "".equals(encKeyId)) {
+            encKeyId = IDGenerator.generateID("EK-");
+        }
+        encryptedKeyElement.setAttributeNS(null, "Id", encKeyId);
+
+        if (keyIdentifierType == WSConstants.CUSTOM_SYMM_SIGNING
+            || keyIdentifierType == WSConstants.CUSTOM_SYMM_SIGNING_DIRECT
+            || keyIdentifierType == WSConstants.CUSTOM_KEY_IDENTIFIER) {
+            SecurityTokenReference secToken = new SecurityTokenReference(document);
+
+            switch (keyIdentifierType) {
+    
+                case WSConstants.CUSTOM_SYMM_SIGNING :
+                    Reference refCust = new Reference(document);
+                    if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
+                        refCust.setValueType(customEKTokenValueType);
+                    } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
+                    } else if (WSConstants.WSS_ENC_KEY_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
+                        refCust.setValueType(customEKTokenValueType);
+                    } else {
+                        refCust.setValueType(customEKTokenValueType);
+                    }
+                    refCust.setURI("#" + customEKTokenId);
+                    secToken.setReference(refCust);
+                    break;
+    
+                case WSConstants.CUSTOM_SYMM_SIGNING_DIRECT :
+                    Reference refCustd = new Reference(document);
+                    if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
+                        refCustd.setValueType(customEKTokenValueType);
+                    } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
+                    }  else if (WSConstants.WSS_ENC_KEY_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
+                        refCustd.setValueType(customEKTokenValueType);
+                    } else {
+                        refCustd.setValueType(customEKTokenValueType);
+                    }
+                    refCustd.setURI(customEKTokenId);
+                    secToken.setReference(refCustd);
+                    break;
+    
+                case WSConstants.CUSTOM_KEY_IDENTIFIER:
+                    secToken.setKeyIdentifier(customEKTokenValueType, customEKTokenId);
+                    if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
+                    } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
+                    } else if (WSConstants.WSS_ENC_KEY_VALUE_TYPE.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
+                    } else if (SecurityTokenReference.ENC_KEY_SHA1_URI.equals(customEKTokenValueType)) {
+                        secToken.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);
+                    }
+                    break;           
+    
+                default:
+                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "unsupportedKeyId");
+            }
+            Element keyInfoElement = 
+                document.createElementNS(
+                    WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":" + WSConstants.KEYINFO_LN
+                );
+            keyInfoElement.setAttributeNS(
+                WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
+            );
+            keyInfoElement.appendChild(secToken.getElement());
+            encryptedKeyElement.appendChild(keyInfoElement);
+        }
+
+        Element xencCipherValue = createCipherValue(document, encryptedKeyElement);
+        xencCipherValue.appendChild(keyText);
+    }
+
     /**
      * Add a BinarySecurityToken
      */
@@ -641,6 +734,10 @@ public class WSSecEncryptedKey extends W
         return encryptedEphemeralKey;
     }
     
+    public void setEncryptedEphemeralKey(byte[] encryptedKey) {
+        encryptedEphemeralKey = encryptedKey;
+    }
+    
     public void setCustomEKTokenValueType(String customEKTokenValueType) {
         this.customEKTokenValueType = customEKTokenValueType;
     }