com.qut.middleware.esoemanager.manager.logic.impl.ServiceCryptoImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.qut.middleware.esoemanager.manager.logic.impl.ServiceCryptoImpl.java

Source

/* Copyright 2008, Queensland University of Technology
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy of 
 * the License at 
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
 * License for the specific language governing permissions and limitations under 
 * the License.
 */
package com.qut.middleware.esoemanager.manager.logic.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qut.middleware.crypto.CryptoProcessor;
import com.qut.middleware.crypto.exception.CryptoException;
import com.qut.middleware.esoemanager.Constants;
import com.qut.middleware.esoemanager.client.rpc.bean.KeyDetails;
import com.qut.middleware.esoemanager.exception.ManagerDAOException;
import com.qut.middleware.esoemanager.exception.RetrieveKeystoreException;
import com.qut.middleware.esoemanager.exception.RetrieveServiceCryptoException;
import com.qut.middleware.esoemanager.exception.ServiceCryptoCreationException;
import com.qut.middleware.esoemanager.exception.ServiceCryptoDeletionException;
import com.qut.middleware.esoemanager.manager.bean.KeyStoreBean;
import com.qut.middleware.esoemanager.manager.logic.ServiceCrypto;
import com.qut.middleware.esoemanager.manager.sqlmap.ManagerDAO;
import com.qut.middleware.saml2.identifier.IdentifierGenerator;

public class ServiceCryptoImpl implements ServiceCrypto {
    private ManagerDAO managerDAO;
    private IdentifierGenerator identifierGenerator;
    private CryptoProcessor cryptoProcessor;

    private int esoeENTID;
    private String esoeEntityID;

    private long expiryWarnTime = 5184000000L; // Will expire within 60 days
    private long expiryErrorTime = 2592000000L; // Will expire within 30 days

    private Logger logger = LoggerFactory.getLogger(ServiceCryptoImpl.class);

    public List<KeyDetails> retrieveServiceKeys(String serviceID) throws RetrieveServiceCryptoException {
        List<KeyDetails> keyDetailsList = new ArrayList<KeyDetails>();
        List<Map<String, Object>> keyStoreDetailsMap;

        try {
            Integer entID = new Integer(serviceID);
            if (entID.intValue() == this.esoeENTID) {
                Integer descID = this.managerDAO.getDescID(entID, Constants.IDP_DESCRIPTOR);
                keyStoreDetailsMap = this.managerDAO.queryKeyStoreDetails(descID);
            } else {
                Integer descID = this.managerDAO.getDescID(entID, Constants.SP_DESCRIPTOR);
                keyStoreDetailsMap = this.managerDAO.queryKeyStoreDetails(descID);
            }
        } catch (ManagerDAOException e) {
            throw new RetrieveServiceCryptoException("Exception when attempting to retrieve keystore", e);
        }

        if (keyStoreDetailsMap == null) {
            throw new RetrieveServiceCryptoException("No keystore details available for this service");
        }

        for (Map<String, Object> keyStoreDetail : keyStoreDetailsMap) {
            KeyDetails keyDetails = new KeyDetails();
            keyDetails.setExpiryDate((Date) keyStoreDetail.get(Constants.FIELD_PKI_EXPIRY_DATE));
            keyDetails.setKeypairName((String) keyStoreDetail.get(Constants.FIELD_PKI_KEYPAIRNAME));
            keyDetails.setKeystorePassphrase((String) keyStoreDetail.get(Constants.FIELD_PKI_KEYSTORE_PASSPHRASE));
            keyDetails.setKeypairPassphrase((String) keyStoreDetail.get(Constants.FIELD_PKI_KEYPAIR_PASSPHRASE));

            // Determine if we need to issue a warning or error about this key
            if (keyDetails.getExpiryDate().getTime() > System.currentTimeMillis()) {
                if (keyDetails.getExpiryDate().getTime() < System.currentTimeMillis() + this.expiryErrorTime)
                    keyDetails.setExpireError(true);
                else if (keyDetails.getExpiryDate().getTime() < System.currentTimeMillis() + this.expiryWarnTime)
                    keyDetails.setExpireWarn(true);
            }

            keyDetailsList.add(keyDetails);
        }

        return keyDetailsList;
    }

    public KeyStoreBean retrieveKeystore(String serviceID, String keypairName)
            throws RetrieveServiceCryptoException {
        List<Map<String, Object>> keyStoreData;
        byte[] rawKeyStore;
        String keyStorePassphrase;
        KeyStore keyStore;

        KeyStoreBean result = new KeyStoreBean();

        try {
            Integer entID = new Integer(serviceID);
            if (entID.intValue() == this.esoeENTID) {
                Integer descID = this.managerDAO.getDescID(entID, Constants.IDP_DESCRIPTOR);
                keyStoreData = this.managerDAO.queryKeystoreBinary(descID);
            } else {
                Integer descID = this.managerDAO.getDescID(entID, Constants.SP_DESCRIPTOR);
                keyStoreData = this.managerDAO.queryKeystoreBinary(descID);
            }

            if (keyStoreData == null || keyStoreData.size() == 0) {
                this.logger.info("No key data returned for provided descriptor");
                throw new RetrieveKeystoreException("No key data returned for provided descriptor");
            }

            rawKeyStore = (byte[]) keyStoreData.get(0).get(Constants.FIELD_PKI_KEYSTORE);
            keyStorePassphrase = (String) keyStoreData.get(0).get(Constants.FIELD_PKI_KEYSTORE_PASSPHRASE);

            keyStore = this.cryptoProcessor.generateKeyStore();
            ByteArrayInputStream in = new ByteArrayInputStream(rawKeyStore);
            keyStore.load(in, keyStorePassphrase.toCharArray());

            result.setKeyStore(keyStore);
            result.setPassphrase(keyStorePassphrase);

            return result;
        } catch (NumberFormatException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        } catch (CertificateException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        } catch (ManagerDAOException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        } catch (RetrieveKeystoreException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        } catch (CryptoException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        } catch (IOException e) {
            throw new RetrieveServiceCryptoException(e.getLocalizedMessage(), e);
        }

    }

    public void createServiceKey(String serviceID) throws ServiceCryptoCreationException {
        String keyStorePassphrase;
        String keyPairName;
        String keyPairPassphrase;
        String keyPairSubjectDN;
        KeyPair spKeyPair;
        KeyStore keyStore;
        byte[] keyStoreBytes;

        try {
            Integer entID = new Integer(serviceID);

            if (entID.intValue() == this.esoeENTID) {
                keyPairSubjectDN = this.generateSubjectDN(this.esoeEntityID);
            } else {
                String serviceURL = null;
                Map<String, Object> description = this.managerDAO.queryServiceDescription(entID);
                if (description == null)
                    throw new ServiceCryptoCreationException("Unable to retrieve serviceURL for this service");

                serviceURL = (String) description.get(Constants.FIELD_SERVICE_URL);
                keyPairSubjectDN = this.generateSubjectDN(serviceURL);
            }

            keyPairName = this.identifierGenerator.generateXMLKeyName();

            keyStorePassphrase = this.generatePassphrase();
            keyPairPassphrase = this.generatePassphrase();

            keyStore = this.cryptoProcessor.generateKeyStore();
            spKeyPair = this.cryptoProcessor.generateKeyPair();
            this.cryptoProcessor.addKeyPair(keyStore, keyStorePassphrase, spKeyPair, keyPairName, keyPairPassphrase,
                    keyPairSubjectDN);
            keyStoreBytes = this.cryptoProcessor.convertKeystoreByteArray(keyStore, keyStorePassphrase);

            X509Certificate certificate = (X509Certificate) keyStore.getCertificate(keyPairName);

            /* Determine expiry date of PKI data */
            Calendar expiryDate = Calendar.getInstance();
            expiryDate.add(Calendar.YEAR, this.cryptoProcessor.getCertExpiryIntervalInYears());

            if (entID.intValue() == this.esoeENTID) {
                /** Commit key data to IDP reference */
                Integer descID_IDP = this.managerDAO.getDescID(entID, Constants.IDP_DESCRIPTOR);
                this.managerDAO.insertPublicKey(descID_IDP, expiryDate.getTime(), keyPairName,
                        this.cryptoProcessor.getCertIssuerDN(), certificate.getSerialNumber().toString(),
                        this.cryptoProcessor.convertPublicKeyByteArray(spKeyPair.getPublic()));

                this.managerDAO.insertPKIData(descID_IDP, expiryDate.getTime(), keyStoreBytes, keyStorePassphrase,
                        keyPairName, keyPairPassphrase);

                /** Commit key data to PDP reference */
                Integer descID_PDP = this.managerDAO.getDescID(entID, Constants.LXACML_PDP_DESCRIPTOR);
                this.managerDAO.insertPublicKey(descID_PDP, expiryDate.getTime(), keyPairName,
                        this.cryptoProcessor.getCertIssuerDN(), certificate.getSerialNumber().toString(),
                        this.cryptoProcessor.convertPublicKeyByteArray(spKeyPair.getPublic()));

                this.managerDAO.insertPKIData(descID_PDP, expiryDate.getTime(), keyStoreBytes, keyStorePassphrase,
                        keyPairName, keyPairPassphrase);

                /** Commit key data to Attribute Authority reference */
                Integer descID_AA = this.managerDAO.getDescID(entID, Constants.ATTRIBUTE_AUTHORITY_DESCRIPTOR);
                this.managerDAO.insertPublicKey(descID_AA, expiryDate.getTime(), keyPairName,
                        this.cryptoProcessor.getCertIssuerDN(), certificate.getSerialNumber().toString(),
                        this.cryptoProcessor.convertPublicKeyByteArray(spKeyPair.getPublic()));

                this.managerDAO.insertPKIData(descID_AA, expiryDate.getTime(), keyStoreBytes, keyStorePassphrase,
                        keyPairName, keyPairPassphrase);
            } else {
                Integer descID = this.managerDAO.getDescID(entID, Constants.SP_DESCRIPTOR);
                this.managerDAO.insertPublicKey(descID, expiryDate.getTime(), keyPairName,
                        this.cryptoProcessor.getCertIssuerDN(), certificate.getSerialNumber().toString(),
                        this.cryptoProcessor.convertPublicKeyByteArray(spKeyPair.getPublic()));
                this.managerDAO.insertPKIData(descID, expiryDate.getTime(), keyStoreBytes, keyStorePassphrase,
                        keyPairName, keyPairPassphrase);
            }

        } catch (NumberFormatException e) {
            throw new ServiceCryptoCreationException(e.getLocalizedMessage(), e);
        } catch (ManagerDAOException e) {
            throw new ServiceCryptoCreationException(e.getLocalizedMessage(), e);
        } catch (CryptoException e) {
            throw new ServiceCryptoCreationException(e.getLocalizedMessage(), e);
        } catch (KeyStoreException e) {
            throw new ServiceCryptoCreationException("Could not obtain certificate from new keystore.", e);
        }
    }

    public void deleteServiceKey(String serviceID, String keypairName) throws ServiceCryptoDeletionException {
        Integer entID = new Integer(serviceID);
        try {
            if (entID.intValue() == this.esoeENTID) {
                Integer descID_IDP = this.managerDAO.getDescID(entID, Constants.IDP_DESCRIPTOR);
                this.managerDAO.deleteServiceKey(descID_IDP, keypairName);

                Integer descID_PDP = this.managerDAO.getDescID(entID, Constants.LXACML_PDP_DESCRIPTOR);
                this.managerDAO.deleteServiceKey(descID_PDP, keypairName);

                Integer descID_AA = this.managerDAO.getDescID(entID, Constants.ATTRIBUTE_AUTHORITY_DESCRIPTOR);
                this.managerDAO.deleteServiceKey(descID_AA, keypairName);
            } else {
                Integer descID = this.managerDAO.getDescID(entID, Constants.SP_DESCRIPTOR);
                this.managerDAO.deleteServiceKey(descID, keypairName);
            }
        } catch (ManagerDAOException e) {
            throw new ServiceCryptoDeletionException(e.getLocalizedMessage(), e);
        }
    }

    private String generatePassphrase() {
        SecureRandom random;
        String passphrase;
        byte[] buf;

        try {
            random = SecureRandom.getInstance("SHA1PRNG");
        } catch (NoSuchAlgorithmException nsae) {
            this.logger.error("NoSuchAlgorithmException when trying to create SecureRandom instance " //$NON-NLS-1$
                    + nsae.getLocalizedMessage());
            this.logger.debug(nsae.getLocalizedMessage(), nsae);
            random = new SecureRandom();
        }

        buf = new byte[Constants.PASSPHRASE_LENGTH];
        random.nextBytes(buf);
        passphrase = new String(Hex.encodeHex(buf));

        return passphrase;
    }

    private String generateSubjectDN(String service) {
        try {
            String result = new String();
            URL serviceURL = new URL(service);
            String[] components = serviceURL.getHost().split("\\.");
            for (String component : components) {
                if (result.length() != 0)
                    result = result + ",";

                result = result + "dc=" + component;
            }
            return result;
        } catch (MalformedURLException e) {
            this.logger.error("Error attempting to generate certificate subjectDN " + e.getLocalizedMessage());
            this.logger.debug(e.toString());
            return "dc=" + service;
        }
    }

    public ManagerDAO getManagerDAO() {
        return managerDAO;
    }

    public void setManagerDAO(ManagerDAO managerDAO) {
        this.managerDAO = managerDAO;
    }

    public IdentifierGenerator getIdentifierGenerator() {
        return identifierGenerator;
    }

    public void setIdentifierGenerator(IdentifierGenerator identifierGenerator) {
        this.identifierGenerator = identifierGenerator;
    }

    public CryptoProcessor getCryptoProcessor() {
        return cryptoProcessor;
    }

    public void setCryptoProcessor(CryptoProcessor cryptoProcessor) {
        this.cryptoProcessor = cryptoProcessor;
    }

    public int getEsoeENTID() {
        return esoeENTID;
    }

    public void setEsoeENTID(int esoeENTID) {
        this.esoeENTID = esoeENTID;
    }

    public String getEsoeEntityID() {
        return esoeEntityID;
    }

    public void setEsoeEntityID(String esoeEntityID) {
        this.esoeEntityID = esoeEntityID;
    }
}