KeyUtil.java revision 272ac8a1a482b3baeff7293aac5de828cfd1ee69
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster/**
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster *
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster *
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * The contents of this file are subject to the terms
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * of the Common Development and Distribution License
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * (the License). You may not use this file except in
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * compliance with the License.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster *
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * You can obtain a copy of the License at
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * opensso/legal/CDDLv1.0.txt
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * See the License for the specific language governing
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * permission and limitations under the License.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster *
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * When distributing Covered Code, include this CDDL
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Header Notice in each file and include the License file
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * at opensso/legal/CDDLv1.0.txt.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * If applicable, add the following below the CDDL Header,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * with the fields enclosed by brackets [] replaced by
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * your own identifying information:
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster *
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * $Id: KeyUtil.java,v 1.5 2009/06/08 23:41:03 madan_ranganath Exp $
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster *
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Portions Copyrighted 2013-2014 ForgeRock AS
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster */
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterpackage com.sun.identity.federation.key;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.util.Map;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.util.List;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.util.Hashtable;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.util.Iterator;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.io.ByteArrayInputStream;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.security.cert.CertificateFactory;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.security.PublicKey;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.security.PrivateKey;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport java.security.cert.X509Certificate;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport org.apache.xml.security.encryption.XMLCipher;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.common.SystemConfigurationUtil;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.federation.common.FSUtils;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.federation.common.IFSConstants;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.federation.jaxb.entityconfig.BaseConfigType;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.federation.meta.IDFFMetaUtils;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.liberty.ws.common.jaxb.xmlsig.KeyInfoType;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.liberty.ws.common.jaxb.xmlsig.X509DataElement;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.liberty.ws.meta.jaxb.ProviderDescriptorType;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.liberty.ws.meta.jaxb.KeyDescriptorType;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.saml.common.SAMLConstants;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.saml.xmlsig.KeyProvider;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster/**
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * The <code>KeyUtil</code> provides methods to obtain
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * the hosting entity's signing key and decryption key, and
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * to obtain a partner entity's signature verification key
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * and encryption related information
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster */
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterpublic class KeyUtil {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private static KeyProvider kp = null;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // key is EntityID|Role
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // value is EncInfo
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster public static Hashtable encHash = new Hashtable();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // key is EntityID|Role
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // value is X509Certificate
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster protected static Hashtable sigHash = new Hashtable();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster static {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster try {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster kp = (KeyProvider)Class.forName(SystemConfigurationUtil.getProperty(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster SAMLConstants.KEY_PROVIDER_IMPL_CLASS,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster SAMLConstants.JKS_KEY_PROVIDER)).newInstance();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster } catch (ClassNotFoundException cnfe) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster FSUtils.debug.error(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "KeyUtil static block:" +
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster " Couldn't find the class.",
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster cnfe);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster kp = null;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster } catch (InstantiationException ie) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster FSUtils.debug.error(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "KeyUtil static block:" +
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster " Couldn't instantiate the key provider instance.",
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ie);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster kp = null;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster } catch (IllegalAccessException iae) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster FSUtils.debug.error(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "KeyUtil static block:" +
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster " Couldn't access the default constructor.",
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster iae);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster kp = null;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster }
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster }
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private KeyUtil() {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster }
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster /**
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Returns the instance of <code>KeyProvider</code>.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @return <code>KeyProvider</code>
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster */
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster public static KeyProvider getKeyProviderInstance() {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster return kp;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster }
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster /**
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Returns the host entity's signing certificate alias.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @param baseConfig <code>BaseConfigType</code> for the host entity
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @return <code>String</code> for host entity's signing
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * certificate alias
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster */
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster public static String getSigningCertAlias(BaseConfigType baseConfig) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster Map map = IDFFMetaUtils.getAttributes(baseConfig);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster List list = (List)map.get(IFSConstants.SIGNING_CERT_ALIAS);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if ((list != null) && (!list.isEmpty())) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String alias = (String)list.get(0);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if ((alias != null) && (alias.length() != 0) && (kp != null)) {
return alias;
}
}
return null;
}
/**
* Returns the host entity's decryption key.
* @param baseConfig <code>BaseConfigType</code> for the host entity
* @return <code>PrivateKey</code> for decrypting a message received
* by the host entity
*/
public static PrivateKey getDecryptionKey(BaseConfigType baseConfig) {
Map map = IDFFMetaUtils.getAttributes(baseConfig);
List list = (List)map.get(IFSConstants.ENCRYPTION_CERT_ALIAS);
PrivateKey decryptionKey = null;
if ((list != null) && (!list.isEmpty())) {
String alias = (String)list.get(0);
if ((alias != null) && (alias.length() != 0) && (kp != null)) {
decryptionKey = kp.getPrivateKey(alias);
}
}
return decryptionKey;
}
/**
* Returns the partner entity's signature verification certificate.
* @param providerDescriptor <code>ProviderDescriptorType</code> for
* the partner entity
* @param entityID partner entity's ID
* @param isIDP whether partner entity's role is IDP or SP
* @return <code>X509Certificate</code> for verifying the partner
* entity's signature
*/
public static X509Certificate getVerificationCert(
ProviderDescriptorType providerDescriptor, String entityID,
boolean isIDP) {
String role = (isIDP) ? "idp":"sp";
if (FSUtils.debug.messageEnabled()) {
FSUtils.debug.message("KeyUtil.getVerificationCert: " +
"Entering... \nEntityID=" + entityID + "\nRole=" + role);
}
// first try to get it from cache
String index = entityID.trim() + "|" + role;
X509Certificate cert = (X509Certificate)sigHash.get(index);
if (cert != null) {
return cert;
}
// else get it from meta
if (providerDescriptor == null) {
FSUtils.debug.error("KeyUtil.getVerificationCert: " +
"Null ProviderDescriptorType input for entityID=" +
entityID + " in " + role + " role.");
return null;
}
KeyDescriptorType kd =
getKeyDescriptor(providerDescriptor, "signing");
if (kd == null) {
FSUtils.debug.error("KeyUtil.getVerificationCert: " +
"No signing KeyDescriptor for entityID=" +
entityID + " in " + role + " role.");
return null;
}
cert = getCert(kd);
if (cert == null) {
FSUtils.debug.error("KeyUtil.getVerificationCert: " +
"No signing cert for entityID=" +
entityID + " in " + role + " role.");
return null;
}
sigHash.put(index, cert);
return cert;
}
/**
* Returns the encryption information which will be used in
* encrypting messages intended for the partner entity.
* @param providerDescriptor <code>ProviderDescriptorType</code> for
* the partner entity
* @param entityID partner entity's ID
* @param isIDP whether partner entity's role is IDP or SP
* @return <code>EncInfo</code> which includes partner entity's
* public key for wrapping the secret key, data encryption algorithm,
* and data encryption strength
*/
public static EncInfo getEncInfo(ProviderDescriptorType providerDescriptor,
String entityID, boolean isIDP) {
String role = (isIDP) ? "idp":"sp";
if (FSUtils.debug.messageEnabled()) {
FSUtils.debug.message("KeyUtil.getEncInfo: " +
"Entering... \nEntityID=" + entityID + "\nRole="+role);
}
// first try to get it from cache
String index = entityID.trim()+"|"+role;
EncInfo encInfo = (EncInfo)encHash.get(index);
if (encInfo != null) {
return encInfo;
}
// else get it from meta
if (providerDescriptor == null) {
FSUtils.debug.error("KeyUtil.getEncInfo: " +
"Null ProviderDescriptorType input for entityID=" +
entityID + " in " + role + " role.");
return null;
}
KeyDescriptorType kd =
getKeyDescriptor(providerDescriptor, "encryption");
if (kd == null) {
FSUtils.debug.error("KeyUtil.getEncInfo: " +
"No encryption KeyDescriptor for entityID=" +
entityID + " in " + role + " role.");
return null;
}
X509Certificate cert = getCert(kd);
if (cert == null) {
FSUtils.debug.error("KeyUtil.getEncInfo: " +
"No encryption cert for entityID=" +
entityID + " in " + role + " role.");
return null;
}
String algorithm = kd.getEncryptionMethod();
int keySize = kd.getKeySize().intValue();
if ((algorithm == null) || (algorithm.length() == 0)) {
algorithm = XMLCipher.AES_128;
keySize = 128;
}
PublicKey pk = cert.getPublicKey();
if (pk != null) {
encInfo = new EncInfo(pk, algorithm, keySize);
}
if (encInfo != null) {
encHash.put(index, encInfo);
}
return encInfo;
}
/**
* Returns <code>KeyDescriptorType</code> from
* <code>ProviderDescriptorType</code>.
* @param providerDescriptor <code>ProviderDescriptorType</code> which
* contains <code>KeyDescriptor</code>s.
* @param usage type of the <code>KeyDescriptorType</code> to be retrieved.
* Its value is "encryption" or "signing".
* @return KeyDescriptorType in <code>ProviderDescriptorType</code> that
* matched the usage type.
*/
public static KeyDescriptorType getKeyDescriptor(
ProviderDescriptorType providerDescriptor, String usage) {
if (providerDescriptor == null) {
return null;
}
List list = providerDescriptor.getKeyDescriptor();
Iterator iter = list.iterator();
KeyDescriptorType kd = null;
String use = null;
KeyDescriptorType noUsageKD = null;
while (iter.hasNext()) {
kd = (KeyDescriptorType)iter.next();
use = kd.getUse();
if ((use == null) || (use.trim().length() == 0)) {
if (noUsageKD == null) {
noUsageKD = kd;
}
continue;
}
if (use.trim().toLowerCase().equals(usage)) {
break;
} else {
kd = null;
}
}
if (kd != null) {
return kd;
} else {
return noUsageKD;
}
}
/**
* Returns certificate stored in <code>KeyDescriptorType</code> in
* <code>ProviderDescriptorType</code>.
* @param providerDescriptor <code>ProviderDescriptorType</code> which
* contains <code>KeyDescriptor</code>s.
* @param usage type of the <code>KeyDescriptorType</code> to be retrieved.
* Its value is "encryption" or "signing".
* @return X509Certificate contained in <code>KeyDescriptorType</code>; or
* <code>null</code> if no certificate is included.
*/
public static X509Certificate getCert(
ProviderDescriptorType providerDescriptor, String usage) {
return getCert(getKeyDescriptor(providerDescriptor, usage));
}
/**
* Returns certificate stored in <code>KeyDescriptorType</code>.
* @param kd <code>KeyDescriptorType</code> which contains certificate info
* @return X509Certificate contained in <code>KeyDescriptorType</code>; or
* <code>null</code> if no certificate is included.
*/
public static X509Certificate getCert(KeyDescriptorType kd) {
if (kd == null) {
return null;
}
KeyInfoType ki = kd.getKeyInfo();
if (ki == null) {
FSUtils.debug.error("KeyUtil.getCert: No KeyInfo.");
return null;
}
X509DataElement data = (X509DataElement) ki.getContent().get(0);
byte[] bt =
((com.sun.identity.liberty.ws.common.jaxb.xmlsig.X509DataType.X509Certificate)
data.getX509IssuerSerialOrX509SKIOrX509SubjectName().get(0)).
getValue();
CertificateFactory cf = null;
try {
cf = CertificateFactory.getInstance("X.509");
} catch (java.security.cert.CertificateException ce) {
FSUtils.debug.error("KeyUtil.getCert: " +
"Unable to get CertificateFactory for X.509 type", ce);
return null;
}
ByteArrayInputStream bais = new ByteArrayInputStream(bt);
X509Certificate retCert = null;
try {
while (bais.available() > 0) {
retCert = (X509Certificate)cf.generateCertificate(bais);
}
} catch (java.security.cert.CertificateException ce) {
FSUtils.debug.error("KeyUtil.getCert: " +
"Unable to generate certificate from byte "+
"array input stream.", ce);
return null;
}
return retCert;
}
}