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