Skip to content
This repository has been archived by the owner on Jun 10, 2019. It is now read-only.

[PLINK-227] - SAML 2.0 Subject EncryptedKey should contain KeyInfo #175

Merged
merged 1 commit into from
Aug 9, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;

/**
Expand Down Expand Up @@ -158,6 +159,17 @@ public interface STSCoreConfig {
*/
public PublicKey getServiceProviderPublicKey(String serviceName);

/**
* <p>
* Obtains the certificate of the specified service provider. The returned certificate is used to encrypt issued
* tokens.
* </p>
*
* @param serviceName the name of the service provider (normally the provider URL).
* @return a reference to the provider's {@code PublicKey}
*/
public X509Certificate getServiceProviderCertificate(String serviceName);

/**
* <p>
* Obtains the certificate identified by the specified alias.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -321,6 +322,41 @@ public PublicKey getServiceProviderPublicKey(String serviceName) {
return key;
}

/*
* (non-Javadoc)
*
* @see org.picketlink.identity.federation.core.wstrust.STSConfiguration#getServiceProviderPublicKey(java.lang.String)
*/
public X509Certificate getServiceProviderCertificate(String serviceName) {
X509Certificate x509 = null;

if (this.trustManager != null) {
try {
// try using the truststore alias from the service provider metadata.
ServiceProviderType provider = this.spMetadata.get(serviceName);
if (provider != null && provider.getTruststoreAlias() != null) {
Certificate cer = this.trustManager.getCertificate(provider.getTruststoreAlias());

if(cer instanceof X509Certificate) {
x509 = (X509Certificate)cer;
}
}

// if there was no truststore alias or no PKC under that alias, use the KeyProvider mapping.
if (x509 == null) {
Certificate cer = this.trustManager.getCertificate(provider.getTruststoreAlias());

if(cer instanceof X509Certificate) {
x509 = (X509Certificate)cer;
}
}
} catch (Exception e) {
throw logger.stsPublicKeyError(serviceName, e);
}
}
return x509;
}

/*
* (non-Javadoc)
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@
*/
package org.picketlink.identity.federation.core.wstrust;

import java.net.URI;
import java.security.KeyPair;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.namespace.QName;
import org.picketlink.common.PicketLinkLogger;
import org.picketlink.common.PicketLinkLoggerFactory;
import org.picketlink.common.constants.WSTrustConstants;
Expand Down Expand Up @@ -61,6 +49,19 @@
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.namespace.QName;
import java.net.URI;
import java.security.KeyPair;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;

/**
* <p>
* Default implementation of the {@code WSTrustRequestHandler} interface. It creates the request context containing the original
Expand Down Expand Up @@ -103,6 +104,7 @@ public RequestSecurityTokenResponse issue(RequestSecurityToken request, Principa

// first try to obtain the security token provider using the applies-to contents.
AppliesTo appliesTo = request.getAppliesTo();
X509Certificate providerCertificate = null;
PublicKey providerPublicKey = null;
if (appliesTo != null) {
String serviceName = WSTrustUtil.parseAppliesTo(appliesTo);
Expand All @@ -113,7 +115,11 @@ public RequestSecurityTokenResponse issue(RequestSecurityToken request, Principa
if (request.getTokenType() == null && tokenTypeFromServiceName != null)
request.setTokenType(URI.create(tokenTypeFromServiceName));

providerPublicKey = this.configuration.getServiceProviderPublicKey(serviceName);
providerCertificate = this.configuration.getServiceProviderCertificate(serviceName);

if(providerCertificate != null) {
providerPublicKey = providerCertificate.getPublicKey();
}

// provider = this.configuration.getProviderForService(serviceName);
/*
Expand Down Expand Up @@ -207,12 +213,12 @@ else if (logger.isDebugEnabled())
} catch (Exception e) {
throw logger.wsTrustCombinedSecretKeyError(e);
}
requestContext.setProofTokenInfo(WSTrustUtil.createKeyInfo(combinedSecret, providerPublicKey, keyWrapAlgo));
requestContext.setProofTokenInfo(WSTrustUtil.createKeyInfo(combinedSecret, providerPublicKey, keyWrapAlgo, providerCertificate));
} else {
// client secret has not been specified - use the sts secret only.
requestedProofToken.add(serverBinarySecret);
requestContext.setProofTokenInfo(WSTrustUtil.createKeyInfo(serverBinarySecret.getValue(), providerPublicKey,
keyWrapAlgo));
keyWrapAlgo, providerCertificate));
}
} else if (WSTrustConstants.KEY_TYPE_PUBLIC.equalsIgnoreCase(keyType.toString())) {
// try to locate the client cert in the keystore using the caller principal as the alias.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import org.apache.xml.security.encryption.EncryptedKey;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.X509Data;
import org.picketlink.common.PicketLinkLogger;
import org.picketlink.common.PicketLinkLoggerFactory;
import org.picketlink.common.constants.WSTrustConstants;
Expand All @@ -27,8 +29,10 @@
import org.picketlink.common.util.Base64;
import org.picketlink.common.util.DocumentUtil;
import org.picketlink.common.util.StaxParserUtil;
import org.picketlink.common.util.SystemPropertiesUtil;
import org.picketlink.config.federation.STSType;
import org.picketlink.identity.federation.core.saml.v2.util.SignatureUtil;
import org.picketlink.identity.federation.core.util.ProvidersUtil;
import org.picketlink.identity.federation.core.util.XMLEncryptionUtil;
import org.picketlink.identity.federation.core.wstrust.wrappers.Lifetime;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
Expand Down Expand Up @@ -67,10 +71,13 @@
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import static org.picketlink.common.util.StringUtil.*;

/**
* <p>
* Utility class that provides methods for parsing/creating WS-Trust elements.
Expand All @@ -82,6 +89,21 @@ public class WSTrustUtil {

private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();

// Set some system properties and Santuario providers. Run this block before any other class initialization.
static {
ProvidersUtil.ensure();
SystemPropertiesUtil.ensure();
String keyInfoProp = SystemPropertiesUtil.getSystemProperty("picketlink.encryption.includeKeyInfo", null);
if (isNotNull(keyInfoProp)) {
includeKeyInfoInEncryptedKey = Boolean.parseBoolean(keyInfoProp);
}
};

/**
* By default, we include the keyinfo in the EncryptedKey
*/
private static boolean includeKeyInfoInEncryptedKey = true;

/**
* <p>
* Creates an instance of {@code KeyIdentifierType} with the specified values.
Expand Down Expand Up @@ -399,7 +421,8 @@ public static byte[] P_SHA1(byte[] secret, byte[] seed, int requiredSize) throws
/**
* <p>
* Creates a {@code KeyInfoType} that wraps the specified secret. If the {@code encryptionKey} parameter is not null, the
* secret is encrypted using the specified public key before it is set in the {@code KeyInfoType}.
* secret is encrypted using the specified public key before it is set in the {@code KeyInfoType}. It also create a
* keyinfo with the information about the key used for the encryption
* </p>
*
* @param secret a {@code byte[]} representing the secret (symmetric key).
Expand All @@ -408,7 +431,7 @@ public static byte[] P_SHA1(byte[] secret, byte[] seed, int requiredSize) throws
* @return the constructed {@code KeyInfoType} instance.
* @throws WSTrustException if an error occurs while creating the {@code KeyInfoType} object.
*/
public static KeyInfoType createKeyInfo(byte[] secret, PublicKey encryptionKey, URI keyWrapAlgo) throws WSTrustException {
public static KeyInfoType createKeyInfo(byte[] secret, PublicKey encryptionKey, URI keyWrapAlgo, X509Certificate cer) throws WSTrustException {
KeyInfoType keyInfo = null;

// if a public key has been specified, encrypt the secret using the public key.
Expand All @@ -418,6 +441,16 @@ public static KeyInfoType createKeyInfo(byte[] secret, PublicKey encryptionKey,
// TODO: XMLEncryptionUtil should allow for the specification of the key wrap algorithm.
EncryptedKey key = XMLEncryptionUtil.encryptKey(document, new SecretKeySpec(secret, "AES"), encryptionKey,
secret.length * 8);

//if certificate is not null provide the information about the key
if (cer != null && includeKeyInfoInEncryptedKey == true) {
KeyInfo kiEnc = new KeyInfo(document);
X509Data xData = new X509Data(document);
xData.addIssuerSerial(cer.getIssuerDN().getName(), cer.getSerialNumber());
kiEnc.add(xData);
key.setKeyInfo(kiEnc);
}

Element encryptedKeyElement = XMLCipher.getInstance().martial(key);
keyInfo = new KeyInfoType();
keyInfo.addContent(encryptedKeyElement);
Expand All @@ -430,6 +463,22 @@ public static KeyInfoType createKeyInfo(byte[] secret, PublicKey encryptionKey,
return keyInfo;
}

/**
* <p>
* Creates a {@code KeyInfoType} that wraps the specified secret. If the {@code encryptionKey} parameter is not null, the
* secret is encrypted using the specified public key before it is set in the {@code KeyInfoType}.
* </p>
*
* @param secret a {@code byte[]} representing the secret (symmetric key).
* @param encryptionKey the {@code PublicKey} that must be used to encrypt the secret.
* @param keyWrapAlgo the key wrap algorithm to be used.
* @return the constructed {@code KeyInfoType} instance.
* @throws WSTrustException if an error occurs while creating the {@code KeyInfoType} object.
*/
public static KeyInfoType createKeyInfo(byte[] secret, PublicKey encryptionKey, URI keyWrapAlgo) throws WSTrustException {
return createKeyInfo(secret, encryptionKey, keyWrapAlgo, null);
}

/**
* <p>
* Creates a {@code KeyInfoType} that wraps the specified certificate.
Expand Down