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 2016/01/07 14:12:42 UTC

svn commit: r1723533 - in /webservices/wss4j/trunk: ws-security-common/src/main/java/org/apache/wss4j/common/crypto/ ws-security-dom/src/main/java/org/apache/wss4j/dom/message/ ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/ ws-security-d...

Author: coheigea
Date: Thu Jan  7 13:12:41 2016
New Revision: 1723533

URL: http://svn.apache.org/viewvc?rev=1723533&view=rev
Log:
[WSS-565] - Support the ability to create and process EncryptedKeys that reference a PublicKey

Modified:
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java
    webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.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
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
    webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java
    webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java Thu Jan  7 13:12:41 2016
@@ -122,6 +122,20 @@ public class CertificateStore extends Cr
     }
 
     /**
+     * Gets the private key corresponding to the given PublicKey.
+     *
+     * @param publicKey The PublicKey corresponding to the private key
+     * @param callbackHandler The callbackHandler needed to get the password
+     * @return The private key
+     */
+    public PrivateKey getPrivateKey(
+        PublicKey publicKey,
+        CallbackHandler callbackHandler
+    ) throws WSSecurityException {
+        return null;
+    }
+    
+    /**
      * Gets the private key corresponding to the identifier. Not supported.
      *
      * @param identifier The implementation-specific identifier corresponding to the key

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java Thu Jan  7 13:12:41 2016
@@ -167,6 +167,18 @@ public interface Crypto {
     PrivateKey getPrivateKey(
         X509Certificate certificate, CallbackHandler callbackHandler
     ) throws WSSecurityException;
+    
+    /**
+     * Gets the private key corresponding to the given PublicKey.
+     *
+     * @param publicKey The PublicKey corresponding to the private key
+     * @param callbackHandler The callbackHandler needed to get the password
+     * @return The private key
+     */
+    PrivateKey getPrivateKey(
+        PublicKey publicKey,
+        CallbackHandler callbackHandler
+    ) throws WSSecurityException;
 
     /**
      * Gets the private key corresponding to the identifier.

Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java Thu Jan  7 13:12:41 2016
@@ -618,42 +618,63 @@ public class Merlin extends CryptoBase {
         }
 
         String identifier = getIdentifier(certificate, keystore);
-        try {
-            if (identifier == null || !keystore.isKeyEntry(identifier)) {
+        if (identifier == null) {
+            try {
                 String msg = "Cannot find key for alias: [" + identifier + "]";
                 String logMsg = createKeyStoreErrorMessage(keystore);
                 LOG.error(msg + logMsg);
                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                               new Object[] {msg});
+            } catch (KeyStoreException ex) {
+                throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILURE, ex, "noPrivateKey", 
+                        new Object[] {ex.getMessage()}
+                );
             }
-            String password = getPassword(identifier, callbackHandler);
-            if (password == null && privatePasswordSet) {
-                password = properties.getProperty(PREFIX + KEYSTORE_PRIVATE_PASSWORD);
-                if (password == null) {
-                    password = properties.getProperty(OLD_PREFIX + KEYSTORE_PRIVATE_PASSWORD);
-                }
-                if (password != null) {
-                    password = password.trim();
-                    password = decryptPassword(password, passwordEncryptor);
-                }
-            }
-            Key keyTmp = keystore.getKey(identifier, password == null
-                                         ? new char[]{} : password.toCharArray());
-            if (!(keyTmp instanceof PrivateKey)) {
-                String msg = "Key is not a private key, alias: [" + identifier + "]";
+        }
+        String password = getPassword(identifier, callbackHandler);
+        return getPrivateKey(identifier, password);
+    }
+    
+    /**
+     * Gets the private key corresponding to the given PublicKey.
+     *
+     * @param publicKey The PublicKey corresponding to the private key
+     * @param callbackHandler The callbackHandler needed to get the password
+     * @return The private key
+     */
+    public PrivateKey getPrivateKey(
+        PublicKey publicKey,
+        CallbackHandler callbackHandler
+    ) throws WSSecurityException {
+        if (keystore == null) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
+                                          new Object[] {"The keystore is null"});
+        }
+        if (callbackHandler == null) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
+                                          new Object[] {"The CallbackHandler is null"});
+        }
+
+        String identifier = getIdentifier(publicKey, keystore);
+        if (identifier == null) {
+            try {
+                String msg = "Cannot find key for alias: [" + identifier + "]";
                 String logMsg = createKeyStoreErrorMessage(keystore);
                 LOG.error(msg + logMsg);
                 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
-                                              new Object[]{msg});
+                                              new Object[] {msg});
+            } catch (KeyStoreException ex) {
+                throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILURE, ex, "noPrivateKey", 
+                        new Object[] {ex.getMessage()}
+                );
             }
-            return (PrivateKey) keyTmp;
-        } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException ex) {
-            throw new WSSecurityException(
-                WSSecurityException.ErrorCode.FAILURE, ex, "noPrivateKey", new Object[] {ex.getMessage()}
-            );
         }
+        String password = getPassword(identifier, callbackHandler);
+        return getPrivateKey(identifier, password);
     }
-
+    
     /**
      * Gets the private key corresponding to the identifier.
      *
@@ -685,6 +706,7 @@ public class Merlin extends CryptoBase {
                 }
                 if (pwd != null) {
                     pwd = pwd.trim();
+                    pwd = decryptPassword(pwd, passwordEncryptor);
                 }
             }
             Key keyTmp = keystore.getKey(identifier, pwd == null
@@ -1324,6 +1346,31 @@ public class Merlin extends CryptoBase {
                     return alias;
                 }
             }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "keystore");
+        }
+        return null;
+    }
+    
+    private String getIdentifier(PublicKey publicKey, KeyStore store)
+        throws WSSecurityException {
+        try {
+            for (Enumeration<String> e = store.aliases(); e.hasMoreElements();) {
+                String alias = e.nextElement();
+
+                Certificate[] certs = store.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a  result.
+                    Certificate retrievedCert = store.getCertificate(alias);
+                    if (retrievedCert != null) {
+                        certs = new Certificate[]{retrievedCert};
+                    }
+                }
+
+                if (certs != null && certs.length > 0 && certs[0].getPublicKey().equals(publicKey)) {
+                    return alias;
+                }
+            }
         } catch (KeyStoreException e) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "keystore");
         }

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=1723533&r1=1723532&r2=1723533&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 Thu Jan  7 13:12:41 2016
@@ -143,26 +143,30 @@ public class WSSecEncrypt extends WSSecE
         // algorithm that will encrypt the generated symmetric (session) key.
         //
         if (encryptSymmKey && encryptedEphemeralKey == null) {
-            X509Certificate remoteCert = getUseThisCert();
-            if (remoteCert == null) {
-                CryptoType cryptoType = null;
-                if (keyIdentifierType == WSConstants.ENDPOINT_KEY_IDENTIFIER) {
-                    cryptoType = new CryptoType(CryptoType.TYPE.ENDPOINT);
-                    cryptoType.setEndpoint(user);
-                } else {
-                    cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
-                    cryptoType.setAlias(user);
+            if (getUseThisPublicKey() != null) {
+                prepareInternal(symmetricKey, getUseThisPublicKey(), crypto);
+            } else {
+                X509Certificate remoteCert = getUseThisCert();
+                if (remoteCert == null) {
+                    CryptoType cryptoType = null;
+                    if (keyIdentifierType == WSConstants.ENDPOINT_KEY_IDENTIFIER) {
+                        cryptoType = new CryptoType(CryptoType.TYPE.ENDPOINT);
+                        cryptoType.setEndpoint(user);
+                    } else {
+                        cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+                        cryptoType.setAlias(user);
+                    }
+                    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];
                 }
-                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];
+                prepareInternal(symmetricKey, remoteCert, crypto);
             }
-            prepareInternal(symmetricKey, remoteCert, crypto);
         } else if (encryptedEphemeralKey != null) {
             prepareInternal(symmetricKey);
         } else {

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=1723533&r1=1723532&r2=1723533&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 Thu Jan  7 13:12:41 2016
@@ -21,6 +21,8 @@ package org.apache.wss4j.dom.message;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.security.spec.MGF1ParameterSpec;
 
@@ -30,6 +32,12 @@ import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.OAEPParameterSpec;
 import javax.crypto.spec.PSource;
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.dom.DOMStructure;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
+import javax.xml.crypto.dsig.keyinfo.KeyValue;
 
 import org.apache.wss4j.common.crypto.Crypto;
 import org.apache.wss4j.common.crypto.CryptoType;
@@ -122,6 +130,8 @@ public class WSSecEncryptedKey extends W
     private BinarySecurity bstToken;
 
     private X509Certificate useThisCert;
+    
+    private PublicKey useThisPublicKey;
 
     /**
      * Custom token value
@@ -198,53 +208,42 @@ public class WSSecEncryptedKey extends W
         }
 
         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"});
+            if (useThisPublicKey != null) {
+                prepareInternal(symmetricKey, useThisPublicKey, crypto);
+            } else {
+                //
+                // 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);
             }
-
-            prepareInternal(symmetricKey, remoteCert, crypto);
         } else {
             prepareInternal(symmetricKey);
         }
     }
-
-    /**
-     * Encrypt the symmetric key data and prepare the EncryptedKey element
-     *
-     * This method does the most work for to prepare the EncryptedKey element.
-     * It is also used by the WSSecEncrypt sub-class.
-     *
-     * @param secretKey The symmetric key
-     * @param remoteCert The certificate that contains the public key to encrypt the
-     *                   symmetric key data
-     * @param crypto An instance of the Crypto API to handle keystore and certificates
-     * @throws WSSecurityException
-     */
-    protected void prepareInternal(
-        SecretKey secretKey,
-        X509Certificate remoteCert,
-        Crypto crypto
-    ) throws WSSecurityException {
+    
+    private void encryptSymmetricKey(PublicKey encryptingKey, SecretKey keyToBeEncrypted) 
+        throws WSSecurityException {
         Cipher cipher = KeyUtils.getCipherInstance(keyEncAlgo);
         try {
             OAEPParameterSpec oaepParameterSpec = null;
@@ -274,9 +273,9 @@ public class WSSecEncryptedKey extends W
                     );
             }
             if (oaepParameterSpec == null) {
-                cipher.init(Cipher.WRAP_MODE, remoteCert);
+                cipher.init(Cipher.WRAP_MODE, encryptingKey);
             } else {
-                cipher.init(Cipher.WRAP_MODE, remoteCert.getPublicKey(), oaepParameterSpec);
+                cipher.init(Cipher.WRAP_MODE, encryptingKey, oaepParameterSpec);
             }
         } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
             throw new WSSecurityException(
@@ -289,12 +288,32 @@ public class WSSecEncryptedKey extends W
         }
 
         try {
-            encryptedEphemeralKey = cipher.wrap(secretKey);
+            encryptedEphemeralKey = cipher.wrap(keyToBeEncrypted);
         } catch (IllegalStateException | IllegalBlockSizeException | InvalidKeyException ex) {
             throw new WSSecurityException(
                 WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex
             );
         }
+    }
+
+    /**
+     * Encrypt the symmetric key data and prepare the EncryptedKey element
+     *
+     * This method does the most work for to prepare the EncryptedKey element.
+     * It is also used by the WSSecEncrypt sub-class.
+     *
+     * @param secretKey The symmetric key
+     * @param remoteCert The certificate that contains the public key to encrypt the
+     *                   symmetric key data
+     * @param crypto An instance of the Crypto API to handle keystore and certificates
+     * @throws WSSecurityException
+     */
+    protected void prepareInternal(
+        SecretKey secretKey,
+        X509Certificate remoteCert,
+        Crypto crypto
+    ) throws WSSecurityException {
+        encryptSymmetricKey(remoteCert.getPublicKey(), secretKey);
 
         //
         // Now we need to setup the EncryptedKey header block 1) create a
@@ -439,6 +458,67 @@ public class WSSecEncryptedKey extends W
             xencCipherValue.appendChild(keyText);
         }
     }
+    
+    protected void prepareInternal(
+        SecretKey secretKey,
+        PublicKey remoteKey,
+        Crypto crypto
+    ) throws WSSecurityException {
+        encryptSymmetricKey(remoteKey, secretKey);
+
+        //
+        // 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 keyIdentifier parameter
+        // 4) Create the CipherValue element structure and insert the encrypted
+        // session key
+        //
+        encryptedKeyElement = createEncryptedKey(document, keyEncAlgo);
+        if (encKeyId == null || "".equals(encKeyId)) {
+            encKeyId = IDGenerator.generateID("EK-");
+        }
+        encryptedKeyElement.setAttributeNS(null, "Id", encKeyId);
+
+        if (customEKKeyInfoElement != null) {
+            encryptedKeyElement.appendChild(document.adoptNode(customEKKeyInfoElement));
+        } else {
+            try {
+                XMLSignatureFactory signatureFactory;
+                try {
+                    signatureFactory = XMLSignatureFactory.getInstance("DOM", "ApacheXMLDSig");
+                } catch (NoSuchProviderException ex) {
+                    signatureFactory = XMLSignatureFactory.getInstance("DOM");
+                }
+                
+                KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
+                KeyValue keyValue = keyInfoFactory.newKeyValue(remoteKey);
+                String keyInfoUri = getIdAllocator().createSecureId("KI-", null);
+                KeyInfo keyInfo =
+                    keyInfoFactory.newKeyInfo(
+                        java.util.Collections.singletonList(keyValue), keyInfoUri
+                    );
+                
+                keyInfo.marshal(new DOMStructure(encryptedKeyElement), null);
+            } catch (java.security.KeyException | MarshalException ex) {
+                LOG.error("", ex);
+                throw new WSSecurityException(
+                    WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex
+                );
+            }
+        }
+
+        Element xencCipherValue = createCipherValue(document, encryptedKeyElement);
+        if (storeBytesInAttachment) {
+            final String attachmentId = getIdAllocator().createId("", document);
+            WSSecurityUtil.storeBytesInAttachment(xencCipherValue, document, attachmentId,
+                                                  encryptedEphemeralKey, attachmentCallbackHandler);
+        } else {
+            Text keyText =
+                WSSecurityUtil.createBase64EncodedTextNode(document, encryptedEphemeralKey);
+            xencCipherValue.appendChild(keyText);
+        }
+    }
 
     protected void prepareInternal(SecretKey secretKey) throws WSSecurityException {
         encryptedKeyElement = createEncryptedKey(document, keyEncAlgo);
@@ -666,10 +746,22 @@ public class WSSecEncryptedKey extends W
     public void setUseThisCert(X509Certificate cert) {
         useThisCert = cert;
     }
-
+    
     public X509Certificate getUseThisCert() {
         return useThisCert;
     }
+    
+    /**
+     * Set the PublicKey to use for encryption.
+     * @param key the PublicKey instance to use for encryption
+     */
+    public void setUseThisPublicKey(PublicKey key) {
+        useThisPublicKey = key;
+    }
+    
+    public PublicKey getUseThisPublicKey() {
+        return useThisPublicKey;
+    }
 
     /**
      * @return Returns the encryptedKeyElement.

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/EncryptedKeyProcessor.java Thu Jan  7 13:12:41 2016
@@ -23,7 +23,9 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
 import java.security.PrivateKey;
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.security.spec.MGF1ParameterSpec;
 import java.util.ArrayList;
@@ -35,6 +37,7 @@ import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.OAEPParameterSpec;
 import javax.crypto.spec.PSource;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -135,6 +138,7 @@ public class EncryptedKeyProcessor imple
 
         X509Certificate[] certs = null;
         STRParser.REFERENCE_TYPE referenceType = null;
+        PublicKey publicKey = null;
         boolean symmetricKeyWrap = isSymmetricKeyWrap(encryptedKeyTransportMethod);
         if (!symmetricKeyWrap) {
             if (SecurityTokenReference.SECURITY_TOKEN_REFERENCE.equals(keyInfoChildElement.getLocalName())
@@ -151,14 +155,28 @@ public class EncryptedKeyProcessor imple
                 referenceType = parserResult.getCertificatesReferenceType();
             } else {
                 certs = getCertificatesFromX509Data(keyInfoChildElement, data);
+                if (certs == null) {
+                    XMLSignatureFactory signatureFactory;
+                    try {
+                        signatureFactory = XMLSignatureFactory.getInstance("DOM", "ApacheXMLDSig");
+                    } catch (NoSuchProviderException ex) {
+                        signatureFactory = XMLSignatureFactory.getInstance("DOM");
+                    }
+                    
+                    publicKey = X509Util.parseKeyValue((Element)keyInfoChildElement.getParentNode(), 
+                                                       signatureFactory);
+                }
             }
-
-            if (certs == null || certs.length < 1 || certs[0] == null) {
+            
+            if (publicKey == null && (certs == null || certs.length < 1 || certs[0] == null)) {
                 throw new WSSecurityException(
                                           WSSecurityException.ErrorCode.FAILURE,
                                           "noCertsFound",
                                           new Object[] {"decryption (KeyId)"});
             }
+            if (certs != null && certs.length > 0) {
+                publicKey = certs[0].getPublicKey();
+            }
         }
 
         // Check for compliance against the defined AlgorithmSuite
@@ -167,7 +185,7 @@ public class EncryptedKeyProcessor imple
                 AlgorithmSuiteValidator(algorithmSuite);
 
             if (!symmetricKeyWrap) {
-                algorithmSuiteValidator.checkAsymmetricKeyLength(certs[0]);
+                algorithmSuiteValidator.checkAsymmetricKeyLength(publicKey);
             }
             algorithmSuiteValidator.checkEncryptionKeyWrapAlgorithm(
                 encryptedKeyTransportMethod
@@ -191,9 +209,10 @@ public class EncryptedKeyProcessor imple
             decryptedBytes = getSymmetricDecryptedBytes(data, wsDocInfo, keyInfoChildElement,
                                                         refList, encryptedEphemeralKey);
         } else {
+            PrivateKey privateKey = getPrivateKey(data, certs, publicKey);
             decryptedBytes = getAsymmetricDecryptedBytes(data, wsDocInfo, encryptedKeyTransportMethod,
                                                          encryptedEphemeralKey, refList,
-                                                         elem, certs[0]);
+                                                         elem, privateKey);
         }
 
         List<WSDataRef> dataRefs = decryptDataRefs(refList, wsDocInfo, decryptedBytes, data);
@@ -217,10 +236,26 @@ public class EncryptedKeyProcessor imple
         if (referenceType != null) {
             result.put(WSSecurityEngineResult.TAG_X509_REFERENCE_TYPE, referenceType);
         }
+        if (publicKey != null) {
+            result.put(WSSecurityEngineResult.TAG_PUBLIC_KEY, publicKey);
+        }
         wsDocInfo.addResult(result);
         wsDocInfo.addTokenElement(elem);
         return Collections.singletonList(result);
     }
+    
+    private PrivateKey getPrivateKey(
+        RequestData data, X509Certificate[] certs, PublicKey publicKey
+    ) throws WSSecurityException {
+        try {
+            if (certs != null) {
+                return data.getDecCrypto().getPrivateKey(certs[0], data.getCallbackHandler());
+            }
+            return data.getDecCrypto().getPrivateKey(publicKey, data.getCallbackHandler());
+        } catch (WSSecurityException ex) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
+        }
+    }
 
     private static byte[] getSymmetricDecryptedBytes(
         RequestData data,
@@ -249,14 +284,13 @@ public class EncryptedKeyProcessor imple
         byte[] encryptedEphemeralKey,
         Element refList,
         Element encryptedKeyElement,
-        X509Certificate cert
+        PrivateKey privateKey
     ) throws WSSecurityException {
         if (data.getDecCrypto() == null) {
             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noDecCryptoFile");
         }
         Cipher cipher = KeyUtils.getCipherInstance(encryptedKeyTransportMethod);
         try {
-            PrivateKey privateKey = data.getDecCrypto().getPrivateKey(cert, data.getCallbackHandler());
             OAEPParameterSpec oaepParameterSpec = null;
             if (WSConstants.KEYTRANSPORT_RSAOEP.equals(encryptedKeyTransportMethod)
                 || WSConstants.KEYTRANSPORT_RSAOEP_XENC11.equals(encryptedKeyTransportMethod)) {
@@ -406,15 +440,15 @@ public class EncryptedKeyProcessor imple
     }
 
     private X509Certificate[] getCertificatesFromX509Data(
-        Element strElement,
+        Element keyInfoChildElement,
         RequestData data
     ) throws WSSecurityException {
 
-        if (WSConstants.SIG_NS.equals(strElement.getNamespaceURI())
-            && WSConstants.X509_DATA_LN.equals(strElement.getLocalName())) {
+        if (WSConstants.SIG_NS.equals(keyInfoChildElement.getNamespaceURI())
+            && WSConstants.X509_DATA_LN.equals(keyInfoChildElement.getLocalName())) {
             data.getBSPEnforcer().handleBSPRule(BSPRule.R5426);
 
-            Element x509Child = getFirstElement(strElement);
+            Element x509Child = getFirstElement(keyInfoChildElement);
 
             if (x509Child != null && WSConstants.SIG_NS.equals(x509Child.getNamespaceURI())) {
                 if (WSConstants.X509_ISSUER_SERIAL_LN.equals(x509Child.getLocalName())) {
@@ -444,7 +478,7 @@ public class EncryptedKeyProcessor imple
 
         return null;
     }
-
+    
     private Element getFirstElement(Element element) {
         for (Node currentChild = element.getFirstChild();
              currentChild != null;

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SignatureProcessor.java Thu Jan  7 13:12:41 2016
@@ -33,11 +33,8 @@ import java.util.List;
 import java.util.Map;
 
 import javax.xml.crypto.Data;
-import javax.xml.crypto.MarshalException;
 import javax.xml.crypto.NodeSetData;
 import javax.xml.crypto.OctetStreamData;
-import javax.xml.crypto.XMLStructure;
-import javax.xml.crypto.dom.DOMStructure;
 import javax.xml.crypto.dsig.Manifest;
 import javax.xml.crypto.dsig.Reference;
 import javax.xml.crypto.dsig.SignedInfo;
@@ -47,9 +44,6 @@ import javax.xml.crypto.dsig.XMLSignatur
 import javax.xml.crypto.dsig.XMLSignatureFactory;
 import javax.xml.crypto.dsig.XMLValidateContext;
 import javax.xml.crypto.dsig.dom.DOMValidateContext;
-import javax.xml.crypto.dsig.keyinfo.KeyInfo;
-import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
-import javax.xml.crypto.dsig.keyinfo.KeyValue;
 import javax.xml.crypto.dsig.spec.ExcC14NParameterSpec;
 import javax.xml.crypto.dsig.spec.HMACParameterSpec;
 
@@ -85,6 +79,7 @@ import org.apache.wss4j.dom.transform.ST
 import org.apache.wss4j.dom.transform.STRTransformUtil;
 import org.apache.wss4j.dom.util.EncryptionUtils;
 import org.apache.wss4j.dom.util.WSSecurityUtil;
+import org.apache.wss4j.dom.util.X509Util;
 import org.apache.wss4j.dom.util.XmlSchemaDateFormat;
 import org.apache.wss4j.dom.validate.Credential;
 import org.apache.wss4j.dom.validate.Validator;
@@ -154,7 +149,7 @@ public class SignatureProcessor implemen
                 && WSConstants.WSSE_NS.equals(child.getNamespaceURI()))) {
                 data.getBSPEnforcer().handleBSPRule(BSPRule.R5417);
 
-                publicKey = parseKeyValue(keyInfoElement);
+                publicKey = X509Util.parseKeyValue(keyInfoElement, signatureFactory);
                 if (validator != null) {
                     credential.setPublicKey(publicKey);
                     principal = new PublicKeyPrincipalImpl(publicKey);
@@ -290,57 +285,6 @@ public class SignatureProcessor implemen
         }
     }
 
-    private PublicKey parseKeyValue(
-        Element keyInfoElement
-    ) throws WSSecurityException {
-        KeyValue keyValue = null;
-        try {
-            //
-            // Look for a KeyValue object
-            //
-            keyValue = getKeyValue(keyInfoElement);
-        } catch (MarshalException ex) {
-            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
-        }
-
-        if (keyValue != null) {
-            try {
-                //
-                // Look for a Public Key in Key Value
-                //
-                return keyValue.getPublicKey();
-            } catch (java.security.KeyException ex) {
-                LOG.error(ex.getMessage(), ex);
-                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
-            }
-        } else {
-            throw new WSSecurityException(
-                    WSSecurityException.ErrorCode.INVALID_SECURITY, "unsupportedKeyInfo"
-            );
-        }
-    }
-
-    /**
-     * Get the KeyValue object from the KeyInfo DOM element if it exists
-     */
-    private KeyValue getKeyValue(
-        Element keyInfoElement
-    ) throws MarshalException {
-        XMLStructure keyInfoStructure = new DOMStructure(keyInfoElement);
-        KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
-        KeyInfo keyInfo = keyInfoFactory.unmarshalKeyInfo(keyInfoStructure);
-        List<?> list = keyInfo.getContent();
-
-        for (int i = 0; i < list.size(); i++) {
-            XMLStructure xmlStructure = (XMLStructure) list.get(i);
-            if (xmlStructure instanceof KeyValue) {
-                return (KeyValue)xmlStructure;
-            }
-        }
-        return null;
-    }
-
-
     /**
      * Verify the WS-Security signature.
      *

Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/util/X509Util.java Thu Jan  7 13:12:41 2016
@@ -29,8 +29,17 @@ import org.w3c.dom.Node;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.XMLStructure;
+import javax.xml.crypto.dom.DOMStructure;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
+import javax.xml.crypto.dsig.keyinfo.KeyValue;
 
 import java.io.IOException;
+import java.security.PublicKey;
+import java.util.List;
 
 public final class X509Util {
     private static final org.slf4j.Logger LOG =
@@ -107,5 +116,54 @@ public final class X509Util {
         }
         return decryptedData;
     }
+    
+    public static PublicKey parseKeyValue( Element keyInfoElement,
+                                           XMLSignatureFactory signatureFactory) throws WSSecurityException {
+        KeyValue keyValue = null;
+        try {
+            //
+            // Look for a KeyValue object
+            //
+            keyValue = getKeyValue(keyInfoElement, signatureFactory);
+        } catch (MarshalException ex) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
+        }
+
+        if (keyValue != null) {
+            try {
+                //
+                // Look for a Public Key in Key Value
+                //
+                return keyValue.getPublicKey();
+            } catch (java.security.KeyException ex) {
+                LOG.error(ex.getMessage(), ex);
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
+            }
+        } else {
+            throw new WSSecurityException(
+                WSSecurityException.ErrorCode.INVALID_SECURITY, "unsupportedKeyInfo"
+            );
+        }
+    }
+
+    /**
+     * Get the KeyValue object from the KeyInfo DOM element if it exists
+     */
+    public static KeyValue getKeyValue(Element keyInfoElement,
+                                       XMLSignatureFactory signatureFactory) throws MarshalException {
+        XMLStructure keyInfoStructure = new DOMStructure(keyInfoElement);
+        KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
+        KeyInfo keyInfo = keyInfoFactory.unmarshalKeyInfo(keyInfoStructure);
+        List<?> list = keyInfo.getContent();
+
+        for (int i = 0; i < list.size(); i++) {
+            XMLStructure xmlStructure = (XMLStructure) list.get(i);
+            if (xmlStructure instanceof KeyValue) {
+                return (KeyValue)xmlStructure;
+            }
+        }
+        return null;
+    }
+
 
 }

Modified: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java?rev=1723533&r1=1723532&r2=1723533&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/EncryptionTest.java Thu Jan  7 13:12:41 2016
@@ -19,6 +19,7 @@
 
 package org.apache.wss4j.dom.message;
 
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -30,6 +31,7 @@ import org.apache.wss4j.common.WSEncrypt
 import org.apache.wss4j.common.bsp.BSPRule;
 import org.apache.wss4j.common.crypto.Crypto;
 import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.crypto.CryptoType;
 import org.apache.wss4j.common.ext.WSSecurityException;
 import org.apache.wss4j.common.util.DOM2Writer;
 import org.apache.wss4j.common.util.KeyUtils;
@@ -218,6 +220,39 @@ public class EncryptionTest extends org.
             (REFERENCE_TYPE)actionResult.get(WSSecurityEngineResult.TAG_X509_REFERENCE_TYPE);
         assertTrue(referenceType == REFERENCE_TYPE.KEY_IDENTIFIER);
     }
+    
+    @Test
+    public void testEncryptionDecryptionPublicKey() throws Exception {
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setKeyIdentifierType(WSConstants.KEY_VALUE);
+        builder.setKeyEncAlgo(WSConstants.KEYTRANSPORT_RSAOEP);
+        Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+        WSSecHeader secHeader = new WSSecHeader(doc);
+        secHeader.insertSecurityHeader();
+        
+        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+        cryptoType.setAlias("wss40");
+        X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
+        assertNotNull(certs);
+        builder.setUseThisPublicKey(certs[0].getPublicKey());
+        
+        Document encryptedDoc = builder.build(doc, crypto, secHeader);
+
+        String outputString =
+            XMLUtils.prettyDocumentToString(encryptedDoc);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(outputString);
+        }
+        assertFalse(outputString.contains("counter_port_type"));
+
+        WSSecurityEngine newEngine = new WSSecurityEngine();
+        WSHandlerResult results =
+            newEngine.processSecurityHeader(encryptedDoc, null, keystoreCallbackHandler, crypto);
+
+        WSSecurityEngineResult actionResult =
+                results.getActionResults().get(WSConstants.ENCR).get(0);
+        assertNotNull(actionResult.get(WSSecurityEngineResult.TAG_PUBLIC_KEY));
+    }
 
     /**
      * Test that encrypt and then again encrypts (Super encryption) WS-Security