Package org.wso2.xkms2.service

Source Code of org.wso2.xkms2.service.XKMSServerCrypto

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.wso2.xkms2.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidator;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXParameters;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import org.apache.axiom.om.util.Base64;
import org.apache.axis2.AxisFault;
import org.apache.commons.discovery.Resource;
import org.apache.commons.discovery.ResourceIterator;
import org.apache.commons.discovery.jdk.JDKHooks;
import org.apache.commons.discovery.resource.DiscoverResources;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.X509NameTokenizer;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.KeyName;
import org.apache.xml.security.keys.content.KeyValue;
import org.apache.xml.security.keys.content.X509Data;
import org.apache.xml.security.keys.keyresolver.KeyResolverException;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureException;
import org.w3c.dom.Document;
import org.wso2.xkms2.Authentication;
import org.wso2.xkms2.InvalidReason;
import org.wso2.xkms2.KRSSRequest;
import org.wso2.xkms2.KRSSResult;
import org.wso2.xkms2.KeyBinding;
import org.wso2.xkms2.KeyBindingAbstractType;
import org.wso2.xkms2.KeyUsage;
import org.wso2.xkms2.LocateRequest;
import org.wso2.xkms2.LocateResult;
import org.wso2.xkms2.MessageAbstractType;
import org.wso2.xkms2.PrototypeKeyBinding;
import org.wso2.xkms2.QueryKeyBinding;
import org.wso2.xkms2.RecoverKeyBinding;
import org.wso2.xkms2.RecoverRequest;
import org.wso2.xkms2.RecoverResult;
import org.wso2.xkms2.RegisterRequest;
import org.wso2.xkms2.RegisterResult;
import org.wso2.xkms2.ReissueKeyBinding;
import org.wso2.xkms2.ReissueRequest;
import org.wso2.xkms2.ReissueResult;
import org.wso2.xkms2.RequestAbstractType;
import org.wso2.xkms2.RespondWith;
import org.wso2.xkms2.ResultMajor;
import org.wso2.xkms2.ResultMinor;
import org.wso2.xkms2.ResultType;
import org.wso2.xkms2.Status;
import org.wso2.xkms2.StatusValue;
import org.wso2.xkms2.UnverifiedKeyBinding;
import org.wso2.xkms2.UseKeyWith;
import org.wso2.xkms2.ValidReason;
import org.wso2.xkms2.ValidateRequest;
import org.wso2.xkms2.ValidateResult;
import org.wso2.xkms2.ValidityInterval;
import org.wso2.xkms2.XKMSException;
import org.wso2.xkms2.core.XKMSRequestData;
import org.wso2.xkms2.util.XKMSKeyUtil;
import org.wso2.xkms2.util.XKMSUtil;

public class XKMSServerCrypto {

    private static final Log LOG = LogFactory.getLog((XKMSServerCrypto.class)
            .getName());

    public static final String XKMS_SERVER_AUTHENTICATION_CODE = "org.wso2.xkms2.service.crypto.authen.code";

    public static final String XKMS_KEY_STORE_LOCATION = "org.wso2.xkms2.service.crypto.keystore.location";

    public static final String XKMS_KEY_STORE_PASSWORD = "org.wso2.xkms2.service.crypto.keystore.password";

    public static final String XKMS_SERVER_CERT_ALIACE = "org.wso2.xkms2.service.crypto.server.cert.aliase";

    public static final String XKMS_SERVER_KEY_PASSWORD = "org.wso2.xkms2.service.crypto.server.key.password";

    public static final String XKMS_ISSUER_CERT_ALIACE = "org.wso2.xkms2.service.crypto.issuer.cert.aliase";

    public static final String XKMS_ISSUER_KEY_PASSWORD = "org.wso2.xkms2.service.crypto.issuer.key.password";

    public static final String XKMS_DEFAULT_EXPIRY_INTERVAL = "org.wso2.xkms2.service.crypto.default.expriy.interval";

    public static final String XKMS_DEFAULT_PRIVATE_KEY_PASSWORD = "org.wso2.xkms2.service.crypto.default.private.key.password";

    public static final String XKMS_ENABLE_PERSISTENCE = "org.wso2.xkms2.service.crypto.persistence.enabled";

    public static final String PROP_ID_CERT_PROVIDER = "org.wso2.xkms2.service.crypto.cert.provider";

    static String SKI_OID = "2.5.29.14";

    private static CertificateFactory certFact;

    /** KeyStore which is used to store X509Certificate and private key entiries */
    private KeyStore keystore = null;

    protected KeyStore cacerts = null;

    /** Certificate to be used to sign issued X509Certificates */
    private X509Certificate cacert = null;

    /** Private key to be used to sign issued X509Certificates */
    private PrivateKey cakey = null;

    /** Private key to be used to sign response messages */
    private PrivateKey sekey = null;

    private Key authkey = null;

    private Key enkey = null;

    private Date caexpiry = null;

    private int validityPeriod;

    private Properties properties;

    private ClassLoader classLoader;

    private boolean canSupportPersistence = false;

    private boolean saveKeystore = false;

    private Document doc;

    public XKMSServerCrypto(Properties properties) throws XKMSException {
        this(properties, XKMSServerCrypto.class.getClassLoader());

    }

    public XKMSServerCrypto(Properties properties, ClassLoader classLoader)
            throws XKMSException {
        this.properties = properties;
        this.classLoader = classLoader;
        Init();
    }

    /*
     * Initializes this XKMSServerCrypto instance.
     */
    private void Init() throws XKMSException {
        String alias;
        String passcode;

        // setting the Server Authentication Key.
        passcode = properties
                .getProperty(XKMSServerCrypto.XKMS_SERVER_AUTHENTICATION_CODE);
        if (passcode != null && passcode.length() > 0) {
            authkey = XKMSKeyUtil.getAuthenticationKey(passcode);
        }

        // setting the <PrivateKey> encryption key
        passcode = properties
                .getProperty(XKMSServerCrypto.XKMS_SERVER_AUTHENTICATION_CODE);
        if (passcode != null && passcode.length() > 0) {
            enkey = XKMSKeyUtil.getPrivateKey(passcode, "DESede");
        }

        loadKeyStore();

        // settting Issuer certificate
        alias = properties.getProperty(XKMS_ISSUER_CERT_ALIACE);
        cacert = getCertificate(alias);

        caexpiry = cacert.getNotAfter();

        // setting Issuer key
        alias = properties.getProperty(XKMS_ISSUER_CERT_ALIACE);
        passcode = properties.getProperty(XKMS_ISSUER_KEY_PASSWORD);
        cakey = getPrivateKey(alias, passcode);

        // setting XKMS response message signing key
        alias = properties.getProperty(XKMS_SERVER_CERT_ALIACE);
        passcode = properties.getProperty(XKMS_SERVER_KEY_PASSWORD);
        sekey = getPrivateKey(alias, passcode);

        // setting the validaity period
        String noOfDays = properties.getProperty(XKMS_DEFAULT_EXPIRY_INTERVAL);
        if (noOfDays != null) {
            validityPeriod = Integer.parseInt(noOfDays);
        } else {
            // the default is one year
            validityPeriod = 365;
        }

        // setting persistence flag
        String persistence = properties.getProperty(XKMS_ENABLE_PERSISTENCE);
        if (persistence != null) {
            saveKeystore = Boolean.getBoolean(persistence);
        } else {
            saveKeystore = false;
        }

    }

    public ResultType process(XKMSRequestData data) throws AxisFault {

        RequestAbstractType request = data.getRequest();
        this.doc = data.getDocument();

        if (request instanceof RegisterRequest) {
            return handleRegisterRequest((RegisterRequest) request);

        } else if (request instanceof ValidateRequest) {
            return handleValidateRequest((ValidateRequest) request);

        } else if (request instanceof ReissueRequest) {
            return handleReissueRequest((ReissueRequest) request);

        } else if (request instanceof LocateRequest) {
            return handleLocateRequest((LocateRequest) request);

        } else if (request instanceof RecoverRequest) {
            return handleRecoverRequest((RecoverRequest) request);
        }

        return null;
    }

    public RegisterResult handleRegisterRequest(RegisterRequest request) {

        try {
            prepare(request, request.getPrototypeKeyBinding());
            validate(request);

            PrototypeKeyBinding pkb = request.getPrototypeKeyBinding();
            String identifer = getSubjectDN(pkb);

            if (identifer == null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("No SubjectDN is specified");
                }

                throw new XKMSException(XKMSException.FAILURE, "NoSubjectDN");
            }

            PublicKey public1 = pkb.getKeyValue();
            PrivateKey private1 = null;

            // if a public key is not provided we need to generate both the
            // public key and private key
            if (public1 == null) {
                KeyPair keypair = XKMSKeyUtil.generateRSAKeyPair();
                public1 = keypair.getPublic();
                private1 = keypair.getPrivate();
            }

            // calculating the start and expiery dates.
            ValidityInterval validityInterval = pkb.getValidityInterval();
            Date[] adjustedInterval;
            if (validityInterval != null) {
                adjustedInterval = getAdjustedValidityInterval(validityInterval
                        .getNotBefore(), validityInterval.getOnOrAfter());
            } else {
                adjustedInterval = getAdjustedValidityInterval((Date) null,
                        (Date) null);
            }

            long serialNum = nextSerialNumber();
            String aliase = createAlias(serialNum);
            BigInteger serialNumber = BigInteger.valueOf(serialNum);

            X509Certificate cert;

            List keyUsage = pkb.getKeyUsage();
            if (keyUsage == null
                    || keyUsage.isEmpty()
                    || (keyUsage.size() == 1 && keyUsage
                            .contains(KeyUsage.EXCHANGE))) {
                cert = XKMSKeyUtil.getX509Certificate(identifer, serialNumber,
                        adjustedInterval[0], adjustedInterval[1], public1,
                        cacert, cakey);

            } else {

                cert = XKMSKeyUtil.getX509Certificate(identifer, serialNumber,
                        adjustedInterval[0], adjustedInterval[1], keyUsage
                                .contains(KeyUsage.SIGNATURE), keyUsage
                                .contains(KeyUsage.ENCRYPTION), public1,
                        cacert, cakey);
            }

            try {
                keystore.setCertificateEntry(aliase, cert);
                if (LOG.isDebugEnabled()) {
                    LOG
                            .debug("Adding the newly constructed X509Certificate to the keystore - \n "
                                    + cert);
                }

                if (private1 != null) {
                    Certificate[] chain = new Certificate[] { cert };
                    keystore.setKeyEntry(aliase, private1,
                            getPrivateKeyPassword(), chain);

                    if (LOG.isDebugEnabled()) {
                        LOG
                                .debug("Added the newly construct Private Key to the keystore - \n"
                                        + private1);
                    }
                }

                if (saveKeystore) {
                    saveKeystore();
                }

            } catch (KeyStoreException e) {
                LOG.error("Adding the certificate to keystore failed", e);
                throw new XKMSException(e);
            }

            RegisterResult result = XKMSUtil.createRegisterResult();
            buildResultType(request, result, aliase, keystore);
            return result;

        } catch (XKMSException ex) {

            RegisterResult resultType = XKMSUtil.createRegisterResult();
            buildFault(request, resultType, ex);
            return resultType;
        }
    }

    public ReissueResult handleReissueRequest(ReissueRequest request) {

        try {
            prepare(request, request.getReissueKeyBinding());
            validate(request);

            ReissueKeyBinding rkb = request.getReissueKeyBinding();
            X509Certificate cert = rkb.getCertValue();

            if (cert == null) {
                throw new XKMSException(XKMSException.FAILURE, "CertNotPresent");
            }

            String alias = getAliasForX509Cert(cert.getIssuerDN().getName(),
                    cert.getSerialNumber());

            if (alias == null) {
                throw new XKMSException(XKMSException.FAILURE, "CertNotFound");
            }

            ReissueResult result = XKMSUtil.creatReissueResult();
            buildResultType(request, result, alias, keystore);
            return result;

        } catch (XKMSException ex) {
            ReissueResult result = XKMSUtil.creatReissueResult();
            buildFault(request, result, ex);
            return result;
        }
    }

    public RecoverResult handleRecoverRequest(RecoverRequest request) {
        try {
            prepare(request, request.getRecoverKeyBinding());
            // TODO Validate ..
            RecoverKeyBinding recoverKeyBinding = request
                    .getRecoverKeyBinding();
            String[] aliases = null;

            X509Certificate cert = recoverKeyBinding.getCertValue();
            if (cert != null) {
                String issuerDN = cert.getIssuerDN().getName();
                BigInteger serialNumber = cert.getSerialNumber();

                String alias = getAliasForX509Cert(issuerDN, serialNumber);
                if (alias != null) {
                    aliases = new String[] { alias };
                }

            } else {
                String subjectDN = getSubjectDN(recoverKeyBinding);

                if (subjectDN != null) {
                    aliases = getAliasesForDN(subjectDN);
                }
            }

            if (aliases == null) {
                String keyName = recoverKeyBinding.getKeyName();
                if (keyName != null) {
                    aliases = new String[] { keyName };
                }
            }

            if (aliases == null || aliases.length < 1) {
                throw new XKMSException(XKMSException.NO_MATCH, "keyNotFound");
            }

            RecoverResult recoverResult = XKMSUtil.createRecoverResult();
            buildResultType(request, recoverResult, aliases[0], keystore);
            return recoverResult;

        } catch (XKMSException ex) {
            RecoverResult recoverResult = XKMSUtil.createRecoverResult();
            buildFault(request, recoverResult, ex);
            return recoverResult;
        }

    }

    /**
     * @param locate
     * @return
     */
    public LocateResult handleLocateRequest(LocateRequest locate) {
        try {
            QueryKeyBinding keybinding = locate.getQueryKeyBinding();

            String identifer = getSubjectDN(keybinding);
            String[] aliases = null;

            if (identifer == null) {
                KeyInfo keyInfo = keybinding.getKeyInfo();

                if (keyInfo != null) {
                    try {
                        KeyName keyName = keyInfo.itemKeyName(0);
                        if (keyName != null) {
                            aliases = new String[] { keyName.getKeyName() };
                        }
                    } catch (XMLSecurityException xme) {
                        throw new XKMSException(xme);
                    }
                }

                if (LOG.isDebugEnabled()) {
                    LOG.debug("No SubjectDN is specified");
                }
            } else {
                aliases = getAliasesForDN(identifer);
            }

            byte[] skiValue = getSKIValue(keybinding);
            if (skiValue != null) {
                String alias = getAliasForX509Cert(skiValue);
                if (alias != null) {
                    aliases = new String[] { alias };
                }
            }

            if (aliases == null || aliases.length == 0) {
                throw new XKMSException("KeyNotFound");
            }

            List keyUsage = keybinding.getKeyUsage();
            boolean digitalSigning = keyUsage.contains(KeyUsage.SIGNATURE);
            boolean dataEncryption = keyUsage.contains(KeyUsage.ENCRYPTION);

            List list = new ArrayList();
            for (int i = 0; i < aliases.length; i++) {
                String alias = aliases[i];
                X509Certificate cert = getCertificate(alias);

                if (cert != null) {
                    boolean[] ku = cert.getKeyUsage();

                    if (digitalSigning && !ku[0]) {
                        continue;
                    }
                    if (dataEncryption && !ku[3]) {
                        continue;
                    }
                    list.add(alias);
                }
            }

            if (list.isEmpty()) {
                throw new XKMSException(XKMSException.NO_MATCH, "KeyNotFound");
            }

            LocateResult result = XKMSUtil.createLocateResult();
            buildResultType((RequestAbstractType) locate, (ResultType) result);

            for (Iterator iterator = list.iterator(); iterator.hasNext();) {
                String alias = (String) iterator.next();
                X509Certificate[] certs = getCertificates(alias);
                UnverifiedKeyBinding ukb = new UnverifiedKeyBinding();

                addKeyInfo(locate.getRespondWith(), alias, certs, ukb);
                addKeyUsage(certs[0], ukb);
                result.addUnverifiedKeyBinding(ukb);
            }

            return result;

        } catch (XKMSException ex) {
            LocateResult result = XKMSUtil.createLocateResult();
            buildFault(locate, result, ex);
            return result;
        }
    }

    public ValidateResult handleValidateRequest(ValidateRequest validateRequest) {

        try {
            QueryKeyBinding queryKeyBinding = validateRequest
                    .getQueryKeyBinding();
            List respondWith = validateRequest.getRespondWith();

            KeyInfo keyInfo = queryKeyBinding.getKeyInfo();
            X509Certificate cert = null;

            if (keyInfo != null) {
                try {
                    cert = keyInfo.getX509Certificate();
                } catch (KeyResolverException e) {
                    throw new XKMSException(XKMSException.FAILURE, "keystore",
                            e);
                }
            }

            if (cert == null) {
                throw new XKMSException(XKMSException.FAILURE, "CertNotPresent");
            }

            if (verifyTrust(cert)) {
                ValidateResult validateResult = XKMSUtil.createValidateResult();
                buildResultType((RequestAbstractType) validateRequest,
                        (ResultType) validateResult);

                String subjectDN = cert.getIssuerDN().getName();
                BigInteger issuerSerial = cert.getSerialNumber();

                String alias = getAliasForX509Cert(subjectDN, issuerSerial);
                X509Certificate[] certs = getCertificates(alias);

                KeyBinding keyBinding = XKMSUtil.createKeyBinding();
                validateResult.addKeyBinding(keyBinding);

                addKeyInfo(respondWith, alias, certs, keyBinding);
                addKeyUsage(certs[0], keyBinding);
                addStatus(true, keyBinding);

                return validateResult;

            } else {

                ValidateResult result = XKMSUtil.createValidateResult();
                buildResultType((RequestAbstractType) validateRequest,
                        (ResultType) result);

                KeyBinding keybinding = XKMSUtil.createKeyBinding();
                X509Certificate[] certs = new X509Certificate[] { cert };

                addKeyInfo(validateRequest.getRespondWith(), null, certs,
                        keybinding);
                addKeyUsage(certs[0], keybinding);
                addStatus(false, keybinding);
                result.addKeyBinding(keybinding);

                return result;
            }

        } catch (XKMSException ex) {
            ValidateResult resultType = XKMSUtil.createValidateResult();
            buildFault(validateRequest, resultType, ex);
            return resultType;
        }
    }

    /*
     * Prepares an KRSSRequest message for validation.
     */
    private void prepare(KRSSRequest request,
            KeyBindingAbstractType abstractType) throws XKMSException {

        Authentication authentication = request.getAuthentication();
        authentication.setKeyBindingAuthenticationKey(authkey);

        KeyInfo keyInfo = abstractType.getKeyInfo();
        if (keyInfo != null) {
            try {

                KeyName itemKeyName = keyInfo.itemKeyName(0);
                if (itemKeyName != null) {
                    abstractType.setKeyName(itemKeyName.getKeyName());
                }

                PublicKey public1 = keyInfo.getPublicKey();
                if (public1 != null) {
                    abstractType.setKeyValue(public1);
                }

                X509Certificate cert = keyInfo.getX509Certificate();
                if (cert != null) {
                    abstractType.setCertValue(cert);
                    abstractType.setKeyValue(cert.getPublicKey());
                }

            } catch (KeyResolverException e) {
                LOG.error("", e);
                throw new XKMSException(XKMSException.FAILURE, "noKey", e);

            } catch (XMLSecurityException e) {
                LOG.error("", e);
                throw new XKMSException(XKMSException.FAILURE, "noKey", e);
            }
        }
    }

    private void validate(ReissueRequest reissueRequest) throws XKMSException {
        validate((KRSSRequest) reissueRequest);

        ReissueKeyBinding rkb = reissueRequest.getReissueKeyBinding();
        XMLSignature pop = reissueRequest.getProofOfPocession();

        Key key = rkb.getKeyValue();
        if (key == null) {
            X509Certificate cert = rkb.getCertValue();

            if (cert != null) {
                key = cert.getPublicKey();
            }
        }

        if (pop != null && key != null) {
            try {
                pop.checkSignatureValue(key);
            } catch (XMLSignatureException se) {
                throw new XKMSException(
                        "Proof-Of-Pocession varification failed", se);
            }
        }

    }

    private void validate(RegisterRequest registerRequest) throws XKMSException {

        validate((KRSSRequest) registerRequest);

        PrototypeKeyBinding pkb = registerRequest.getPrototypeKeyBinding();
        XMLSignature proofOfPossession = registerRequest.getProofOfPossession();

        Key key = pkb.getKeyValue();

        if (key != null) {
            try {
                proofOfPossession.checkSignatureValue(key);

            } catch (XMLSignatureException e) {
                LOG.error("", e);

                throw new XKMSException(
                        XKMSException.PROOF_OF_POSSESSION_REQUIRED,
                        "popRequired", e);
            }
        }
    }

    private void validate(KRSSRequest request) throws XKMSException {

        validate((MessageAbstractType) request);

        Authentication authentication = request.getAuthentication();
        XMLSignature keyBindingAuthentication = authentication
                .getKeyBindingAuthentication();

        Key keyBindingAuthenticationKey = authentication
                .getKeyBindingAuthenticationKey();
        try {
            if (!keyBindingAuthentication
                    .checkSignatureValue(keyBindingAuthenticationKey)) {
                throw new XKMSException(XKMSException.NO_AUTHENTICATION,
                        "invalidXMLSign");
            }
            System.out.println("success");
        } catch (XMLSignatureException e) {
            LOG.error("", e);
            throw new XKMSException(XKMSException.NO_AUTHENTICATION,
                    "invalidXMLSign", e);
        }
    }

    private void validate(MessageAbstractType abstractType)
            throws XKMSException {

        XMLSignature signature = abstractType.getSignature();
        if (signature != null) {
            X509Certificate x509Certificate = abstractType.getSignCert();

            try {
                signature.checkSignatureValue(x509Certificate);
            } catch (XMLSignatureException e) {
                LOG.error("", e);
                throw new XKMSException(XKMSException.NO_AUTHENTICATION,
                        "failedXMLSign", e);
            }
        }
    }

    private void buildResultType(RegisterRequest request,
            RegisterResult result, String aliase, KeyStore ks)
            throws XKMSException {

        buildResultType((RequestAbstractType) request, result, aliase, ks);
        org.wso2.xkms2.PrivateKey privateKey = getPrivateKey(aliase, ks);

        if (privateKey != null) {
            result.setPrivateKey(privateKey);
        }
    }

    private void buildResultType(ReissueRequest request, ReissueResult result,
            String aliase, KeyStore ks) throws XKMSException {

        buildResultType((RequestAbstractType) request, (KRSSResult) result,
                aliase, ks);
    }

    private void buildResultType(RecoverRequest request, RecoverResult result,
            String aliase, KeyStore ks) throws XKMSException {

        buildResultType((RequestAbstractType) request, (KRSSResult) result,
                aliase, ks);
        ;
        org.wso2.xkms2.PrivateKey privateKey = getPrivateKey(aliase, ks);

        if (privateKey != null) {
            result.setPrivateKey(privateKey);
        }
    }

    private void buildResultType(RequestAbstractType request,
            KRSSResult result, String aliase, KeyStore ks) throws XKMSException {

        buildResultType((RequestAbstractType) request, (ResultType) result);

        KeyBinding kb = XKMSUtil.createKeyBinding();
        result.addKeyBinding(kb);

        X509Certificate[] certs = getCertificates(aliase);

        List respondWithList = request.getRespondWith();
        addKeyInfo(respondWithList, aliase, certs, kb);

        addValidationInterval(certs[0], kb);
        addKeyUsage(certs[0], kb);
        addStatus(true, kb);
    }

    private void buildResultType(RequestAbstractType request, ResultType result)
            throws XKMSException {

        result.setServiceURI(request.getServiceURI());
        result.setResultMajor(ResultMajor.SUCCESS);
        result.setSignKey(sekey);
    }

    private org.wso2.xkms2.PrivateKey getPrivateKey(String aliase, KeyStore ks)
            throws XKMSException {

        String passcode = properties
                .getProperty(XKMS_DEFAULT_PRIVATE_KEY_PASSWORD);

        PrivateKey private1 = getPrivateKey(aliase, passcode);

        if (private1 != null) {
            X509Certificate cert = getCertificate(aliase);
            PublicKey public1 = cert.getPublicKey();
            KeyPair keyPair = new KeyPair(public1, private1);
            org.wso2.xkms2.PrivateKey privateKey = new org.wso2.xkms2.PrivateKey();
            privateKey.setRSAKeyPair(keyPair);
            privateKey.setKey(enkey);
            return privateKey;

        } else {
            return null;
        }
    }

    private String getSubjectDN(KeyBindingAbstractType abstractType) {
        List useKeyWiths = abstractType.getUseKeyWith();

        if (useKeyWiths == null || useKeyWiths.isEmpty()) {
            return null;
        }

        for (Iterator iterator = useKeyWiths.iterator(); iterator.hasNext();) {
            UseKeyWith useKeyWith = (UseKeyWith) iterator.next();

            if (UseKeyWith.PKIX.equals(useKeyWith.getApplication())) {
                return useKeyWith.getIdentifier();
            }
        }

        return null;
    }

    private byte[] getSKIValue(KeyBindingAbstractType abstractType) {
        List useKeyWiths = abstractType.getUseKeyWith();

        if (useKeyWiths == null || useKeyWiths.isEmpty()) {
            return null;
        }

        for (Iterator iterator = useKeyWiths.iterator(); iterator.hasNext();) {
            UseKeyWith useKeyWith = (UseKeyWith) iterator.next();

            if (UseKeyWith.SKI.equals(useKeyWith.getApplication())) {
                return Base64.decode(useKeyWith.getIdentifier());
            }
        }

        return null;
    }

    /**
     * Returns PKIX keystore of this sample service.
     *
     * @return the KeyStore of this sample service.
     */
    private void loadKeyStore() {

        InputStream is = null;

        try {
            String keyStorelocation = properties
                    .getProperty(XKMSServerCrypto.XKMS_KEY_STORE_LOCATION);
            String password = properties
                    .getProperty(XKMSServerCrypto.XKMS_KEY_STORE_PASSWORD);

            File keyStoreFile = new File(keyStorelocation);

            if (!keyStoreFile.exists()) {
                String wso2wsashome = System.getProperty("wso2wsas.home");

                if (wso2wsashome != null) {
                    keyStoreFile = new File(wso2wsashome + File.separator
                            + "conf" + File.separator + keyStorelocation);
                }
            }
            /**
             * If we don't find it, then look on the file system.
             */
            if (keyStoreFile.exists()) {
                try {
                    is = new FileInputStream(keyStorelocation);
                    properties.put(XKMS_KEY_STORE_LOCATION, keyStoreFile
                            .getAbsolutePath());
                    canSupportPersistence = true;

                } catch (FileNotFoundException e) {
                    throw new Exception(e);
                }
            }

            if (is == null) {
                // Look for the keystore in classpaths
                DiscoverResources disc = new DiscoverResources();
                disc.addClassLoader(JDKHooks.getJDKHooks()
                        .getThreadContextClassLoader());
                disc.addClassLoader(classLoader);

                ResourceIterator iterator = disc
                        .findResources(keyStorelocation);
                if (iterator.hasNext()) {
                    Resource resource = iterator.nextResource();
                    is = resource.getResourceAsStream();
                }

                if (is == null) {
                    iterator = disc.findResources("META-INF/"
                            + keyStorelocation);
                    if (iterator.hasNext()) {
                        Resource resource = iterator.nextResource();
                        is = resource.getResourceAsStream();
                    }
                }
            }
            if (is == null) {
                throw new Exception("specified keystore doesn't exist");
            }

            keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            keystore.load(is, password.toCharArray());

        } catch (Exception e) {
            throw new RuntimeException("Can't load keystore", e);

        } finally {
            // is.close();
        }
    }

    /**
     * Persist the keystore if persistance is enabled.
     *
     * @throws XKMSException
     */
    private void saveKeystore() throws XKMSException {
        if (canSupportPersistence) {
            try {
                String location = properties
                        .getProperty(XKMS_KEY_STORE_LOCATION);
                FileOutputStream outputStream = new FileOutputStream(location);
                String storePass = properties
                        .getProperty(XKMS_KEY_STORE_PASSWORD);
                keystore.store(outputStream, storePass.toCharArray());

            } catch (FileNotFoundException ex) {
                throw new XKMSException(ex);
            } catch (KeyStoreException e) {
                throw new XKMSException(e);
            } catch (NoSuchAlgorithmException e) {
                throw new XKMSException(e);
            } catch (CertificateException e) {
                throw new XKMSException(e);
            } catch (IOException e) {
                throw new XKMSException(e);
            }
        }
    }

    /**
     * @see org.apache.ws.security.components.crypto.Crypto#getPrivateKey(java.lang.String,
     *      java.lang.String)
     */
    public PrivateKey getPrivateKey(String alias, String password)
            throws IllegalArgumentException {

        if (alias == null) {
            throw new IllegalArgumentException("alias is null");
        }
        try {

            boolean b = keystore.isKeyEntry(alias);
            if (!b) {
                if (LOG.isDebugEnabled()) {
                    LOG.error("Cannot find key for alias: " + alias);
                }
                return null;
            }

            Key keyTmp = keystore.getKey(alias, password.toCharArray());

            if (!(keyTmp instanceof PrivateKey)) {
                throw new IllegalArgumentException(
                        "Key is not a private key, alias: " + alias);
            }

            return (PrivateKey) keyTmp;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void addKeyInfo(List respondWiths, String aliase,
            X509Certificate[] certs, KeyBindingAbstractType abstractType) {

        KeyInfo keyInfo = new KeyInfo(doc);

        for (Iterator iterator = respondWiths.iterator(); iterator.hasNext();) {
            RespondWith respondWith = (RespondWith) iterator.next();

            if (respondWith.equals(RespondWith.KEY_NAME)) {
                KeyName keyName = new KeyName(doc, aliase);
                keyInfo.add(keyName);

            } else if (respondWith.equals(RespondWith.KEY_VALUE)) {
                PublicKey publicKey = certs[0].getPublicKey();
                KeyValue keyValue = new KeyValue(doc, publicKey);
                keyInfo.add(keyValue);

            } else if (respondWith.equals(RespondWith.X_509_CERT)) {
                addX509Certificate(certs[0], keyInfo);

            } else if (respondWith.equals(RespondWith.X_509_CHAIN)) {
                for (int i = 0; i < certs.length; i++) {
                    addX509Certificate(certs[i], keyInfo);
                }

            } else {
                // TODO Implement the other RespondWith elements.
            }
        }
        abstractType.setKeyInfo(keyInfo);
    }

    private void addX509Certificate(X509Certificate cert, KeyInfo keyInfo) {

        X509Data data = new X509Data(doc);
        try {
            data.addCertificate(cert);
        } catch (XMLSecurityException se) {
            throw new RuntimeException(
                    "Adding the X509Certificate to X509Data object failed", se);
        }
        keyInfo.add(data);
    }

    private void addKeyUsage(X509Certificate cert, KeyBindingAbstractType kb) {

        // CHECKME
        // /////////////////////////////////////////////////////////////////////
        // setting the KeyUsage values
        boolean[] keyUsage = cert.getKeyUsage();
        if (keyUsage != null) {
            // digitalSignature
            if (keyUsage[0]) {
                kb.addKeyUsage(KeyUsage.SIGNATURE);
            }
            // dataEncipherment
            if (keyUsage[3]) {
                kb.addKeyUsage(KeyUsage.ENCRYPTION);
            }
        }
        // ////////////////////////////////////////////////////////////////////
    }

    private void addValidationInterval(X509Certificate cert, KeyBinding kb) {
        Date start = cert.getNotBefore();
        Date expiry = cert.getNotAfter();

        Calendar notBefore = Calendar.getInstance();
        notBefore.setTime(start);
        Calendar notAfter = Calendar.getInstance();
        notAfter.setTime(expiry);

        kb.setValidityInterval(notBefore, notAfter);
    }

    private void addStatus(boolean valid, KeyBinding kb) {
        Status status = new Status();
        status
                .setStatusValue((valid) ? StatusValue.VALID
                        : StatusValue.INVALID);
        if (valid) {
            status.addValidReason(ValidReason.ISSUER_TRUST);
            status.addValidReason(ValidReason.REVOCATION_STATUS);
            status.addValidReason(ValidReason.SIGNATURE);
            status.addValidReason(ValidReason.VALIDITY_INTERVAL);
        } else {
            status.addInvalidReason(InvalidReason.ISSUER_TRUST);
            status.addInvalidReason(InvalidReason.REVOCATION_STATUS);
            status.addInvalidReason(InvalidReason.SIGNATURE);
            status.addInvalidReason(InvalidReason.VALIDITY_INTERVAL);
        }
        kb.setStatus(status);
    }

    /*
     * Calcuates the start and expiry dates. The arguments are only advisory.
     */
    private Date[] getAdjustedValidityInterval(Calendar notBefore,
            Calendar notAfter) {
        Date start = (notBefore == null) ? null : notBefore.getTime();
        Date expiry = (notAfter == null) ? null : notAfter.getTime();
        return getAdjustedValidityInterval(start, expiry);
    }

    /*
     *
     */
    private Date[] getAdjustedValidityInterval(Date notBefore, Date notAfter) {
        Date start;
        Date expiryDate;

        Calendar ca = Calendar.getInstance();
        Date today = ca.getTime();

        if (notBefore != null) {
            if (notBefore.before(today)) {
                start = today;
            } else {
                start = notBefore;
            }
        } else {
            start = today;
        }

        if (notAfter == null) {
            ca.add(Calendar.DAY_OF_YEAR, validityPeriod);
            notAfter = ca.getTime();
        }

        if (notAfter.after(caexpiry)) {
            expiryDate = caexpiry;
        } else {
            expiryDate = notAfter;
        }

        return new Date[] { start, expiryDate };
    }

    private void buildFault(RequestAbstractType requestType,
            ResultType resultType, XKMSException ex) {

        resultType.setServiceURI(requestType.getServiceURI());

        Throwable t = ex.getCause();
        if (t != null) {
            LOG.fatal("Exception is thrown when processing", t);
        }

        int errorCode = ex.getErrorCode();
        switch (errorCode) {
        case XKMSException.NO_AUTHENTICATION:
            resultType.setResultMajor(ResultMajor.SENDER);
            resultType.setResultMinor(ResultMinor.NO_AUTHENTICATION);
            break;
        case XKMSException.NO_MATCH:
            resultType.setResultMajor(ResultMajor.SUCCESS);
            resultType.setResultMinor(ResultMinor.NO_MATCH);
            break;
        default:

            resultType.setResultMajor(ResultMajor.RECEIVER);
            resultType.setResultMinor(ResultMinor.FAILURE);
        }
    }

    private char[] getPrivateKeyPassword() {
        String password = properties
                .getProperty(XKMS_DEFAULT_PRIVATE_KEY_PASSWORD);
        return password.toCharArray();
    }

    /**
     * Creates an alias based on serial number
     *
     * @param serialNum
     *            the serial number
     * @return the newly created alias
     */
    private String createAlias(long serialNum) {
        String aliase = String.valueOf(serialNum);
        return aliase;
    }

    /**
     * We choose the current time of the server in milliseconds as the serial
     * number of the issued certificate.
     *
     * @return serialNumber
     */
    private long nextSerialNumber() {
        return System.currentTimeMillis();
    }

    /**
     * @see org.apache.ws.security.components.crypto.Crypto#getAliasForX509Cert(java.lang.String,
     *      java.math.BigInteger)
     */
    public String getAliasForX509Cert(String issuer, BigInteger serialNumber)
            throws XKMSException {
        return getAliasForX509Cert(issuer, serialNumber, true);
    }

    /**
     *
     * @param issuer
     * @param serialNumber
     * @param useSerialNumber
     * @return
     * @throws WSSecurityException
     */
    private String getAliasForX509Cert(String issuer, BigInteger serialNumber,
            boolean useSerialNumber) throws XKMSException {
        Vector issuerRDN = splitAndTrim(issuer);
        X509Certificate x509cert = null;
        Vector certRDN = null;
        Certificate cert = null;

        try {
            for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
                String alias = (String) e.nextElement();
                Certificate[] certs = keystore.getCertificateChain(alias);
                if (certs == null || certs.length == 0) {
                    // no cert chain, so lets check if getCertificate gives us a
                    // result.
                    cert = keystore.getCertificate(alias);
                    if (cert == null) {
                        return null;
                    }
                } else {
                    cert = certs[0];
                }
                if (!(cert instanceof X509Certificate)) {
                    continue;
                }
                x509cert = (X509Certificate) cert;
                if (!useSerialNumber
                        || useSerialNumber
                        && x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
                    certRDN = splitAndTrim(x509cert.getIssuerDN().getName());
                    if (certRDN.equals(issuerRDN)) {
                        return alias;
                    }
                }
            }
        } catch (KeyStoreException e) {
            throw new XKMSException("keystore");
        }
        return null;
    }

    private Vector splitAndTrim(String inString) {
        X509NameTokenizer nmTokens = new X509NameTokenizer(inString);
        Vector vr = new Vector();

        while (nmTokens.hasMoreTokens()) {
            vr.add(nmTokens.nextToken());
        }
        java.util.Collections.sort(vr);
        return vr;
    }

    /**
     * Lookup X509 Certificates in the keystore according to a given DN of the
     * subject of the certificate <p/> The search gets all alias names of the
     * keystore and gets the certificate (chain) for each alias. Then the DN of
     * the certificate is compared with the parameters.
     *
     * @param subjectDN
     *            The DN of subject to look for in the keystore
     * @return Vector with all alias of certificates with the same DN as given
     *         in the parameters
     * @throws org.apache.ws.security.WSSecurityException
     *
     */
    public String[] getAliasesForDN(String subjectDN) throws XKMSException {

        // The DN to search the keystore for
        Vector subjectRDN = splitAndTrim(subjectDN);
        Vector aliases = getAlias(subjectRDN, keystore);

        // If we can't find the issuer in the keystore then look at cacerts
        if (aliases.size() == 0 && cacerts != null) {
            aliases = getAlias(subjectRDN, cacerts);
        }

        // Convert the vector into an array
        String[] result = new String[aliases.size()];
        for (int i = 0; i < aliases.size(); i++)
            result[i] = (String) aliases.elementAt(i);

        return result;
    }

    private Vector getAlias(Vector subjectRDN, KeyStore store)
            throws XKMSException {
        // Store the aliases found
        Vector aliases = new Vector();

        Certificate cert = null;

        try {
            for (Enumeration e = store.aliases(); e.hasMoreElements();) {
                String alias = (String) 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.
                    cert = store.getCertificate(alias);
                    if (cert == null) {
                        return null;
                    }
                    certs = new Certificate[] { cert };
                } else {
                    cert = certs[0];
                }
                if (cert instanceof X509Certificate) {
                    Vector foundRDN = splitAndTrim(((X509Certificate) cert)
                            .getSubjectDN().getName());

                    if (subjectRDN.equals(foundRDN)) {
                        aliases.add(alias);
                    }
                }
            }
        } catch (KeyStoreException e) {
            throw new XKMSException(e);
        }
        return aliases;
    }

    /**
     * @see org.apache.ws.security.components.crypto.Crypto#getCertificateFactory()
     */
    public CertificateFactory getCertificateFactory() throws XKMSException {
        if (certFact == null) {
            try {
                String provider = properties.getProperty(PROP_ID_CERT_PROVIDER);
                if (provider == null || provider.length() == 0) {
                    certFact = CertificateFactory.getInstance("X.509");
                } else {
                    certFact = CertificateFactory
                            .getInstance("X.509", provider);
                }
            } catch (CertificateException e) {
                throw new XKMSException("unsupportedCertType");

            } catch (NoSuchProviderException e) {
                throw new XKMSException("noSecProvider");
            }
        }

        return certFact;
    }

    /**
     * Overridden because there's a bug in the base class where they don't use
     * the provider variant for the certificate validator.
     *
     * @param certs
     *            Certificate chain to validate
     * @return true if the certificate chain is valid, false otherwise
     * @throws WSSecurityException
     */
    public boolean validateCertPath(X509Certificate[] certs)
            throws XKMSException {

        try {
            // Generate cert path
            List cert_list = Arrays.asList(certs);
            CertPath path = getCertificateFactory().generateCertPath(cert_list);

            // Use the certificates in the keystore as TrustAnchors
            PKIXParameters param = new PKIXParameters(this.keystore);

            // Do not check a revocation list
            param.setRevocationEnabled(false);

            String provider = properties
                    .getProperty("org.apache.ws.security.crypto.merlin.cert.provider");

            CertPathValidator validator = null;

            if (provider == null || provider.length() == 0) {
                validator = CertPathValidator.getInstance("PKIX");
            } else {
                validator = CertPathValidator.getInstance("PKIX", provider);
            }
            validator.validate(path, param);
        } catch (java.security.NoSuchProviderException e) {
            throw new XKMSException("certpath");
        } catch (java.security.NoSuchAlgorithmException e) {
            throw new XKMSException("certpath");
        } catch (java.security.cert.CertificateException e) {
            throw new XKMSException("certpath");
        } catch (java.security.InvalidAlgorithmParameterException e) {
            throw new XKMSException("certpath");
        } catch (java.security.cert.CertPathValidatorException e) {
            throw new XKMSException("certpath");
        } catch (java.security.KeyStoreException e) {
            throw new XKMSException("certpath");
        }

        return true;
    }

    /**
     * Gets the list of certificates for a given alias. <p/>
     *
     * @param alias
     *            Lookup certificate chain for this alias
     * @return Array of X509 certificates for this alias name, or null if this
     *         alias does not exist in the keystore
     */
    public X509Certificate getCertificate(String alias) throws XKMSException {
        Certificate[] certs = null;
        Certificate cert = null;
        try {
            if (this.keystore != null) {
                // There's a chance that there can only be a set of trust stores
                certs = keystore.getCertificateChain(alias);
                if (certs == null || certs.length == 0) {
                    // no cert chain, so lets check if getCertificate gives us a
                    // result.
                    cert = keystore.getCertificate(alias);
                }
            }

            if (certs == null && cert == null && cacerts != null) {
                // Now look into the trust stores
                certs = cacerts.getCertificateChain(alias);
                if (certs == null) {
                    cert = cacerts.getCertificate(alias);
                }
            }

            if (cert != null) {
                return (X509Certificate) cert;

            } else if (certs == null) {
                // At this pont we don't have certs or a cert
                return null;
            } else {
                return (X509Certificate) certs[0];

            }
        } catch (KeyStoreException e) {
            throw new XKMSException("keystore");
        }
    }

    /**
     * Gets the list of certificates for a given alias. <p/>
     *
     * @param alias
     *            Lookup certificate chain for this alias
     * @return Array of X509 certificates for this alias name, or null if this
     *         alias does not exist in the keystore
     */
    public X509Certificate[] getCertificates(String alias) throws XKMSException {
        Certificate[] certs = null;
        Certificate cert = null;
        try {
            if (this.keystore != null) {
                // There's a chance that there can only be a set of trust stores
                certs = keystore.getCertificateChain(alias);
                if (certs == null || certs.length == 0) {
                    // no cert chain, so lets check if getCertificate gives us a
                    // result.
                    cert = keystore.getCertificate(alias);
                }
            }

            if (certs == null && cert == null && cacerts != null) {
                // Now look into the trust stores
                certs = cacerts.getCertificateChain(alias);
                if (certs == null) {
                    cert = cacerts.getCertificate(alias);
                }
            }

            if (cert != null) {
                certs = new Certificate[] { cert };
            } else if (certs == null) {
                // At this pont we don't have certs or a cert
                return null;
            }
        } catch (KeyStoreException e) {
            throw new XKMSException("keystore");
        }

        X509Certificate[] x509certs = new X509Certificate[certs.length];
        for (int i = 0; i < certs.length; i++) {
            x509certs[i] = (X509Certificate) certs[i];
        }
        return x509certs;
    }

    /**
     * Evaluate whether a given certificate should be trusted. Hook to allow
     * subclasses to implement custom validation methods however they see fit.
     * <p/> Policy used in this implementation: 1. Search the keystore for the
     * transmitted certificate 2. Search the keystore for a connection to the
     * transmitted certificate (that is, search for certificate(s) of the issuer
     * of the transmitted certificate 3. Verify the trust path for those
     * certificates found because the search for the issuer might be fooled by a
     * phony DN (String!)
     *
     * @param cert
     *            the certificate that should be validated against the keystore
     * @return true if the certificate is trusted, false if not (AxisFault is
     *         thrown for exceptions during CertPathValidation)
     * @throws WSSecurityException
     */
    protected boolean verifyTrust(X509Certificate cert) throws XKMSException {

        // If no certificate was transmitted, do not trust the signature
        if (cert == null) {
            return false;
        }

        String[] aliases = null;
        String alias = null;
        X509Certificate[] certs;

        String subjectString = cert.getSubjectDN().getName();
        String issuerString = cert.getIssuerDN().getName();
        BigInteger issuerSerial = cert.getSerialNumber();

        if (LOG.isDebugEnabled()) {
            LOG.debug("WSHandler: Transmitted certificate has subject "
                    + subjectString);
            LOG.debug("WSHandler: Transmitted certificate has issuer "
                    + issuerString + " (serial " + issuerSerial + ")");
        }

        // FIRST step
        // Search the keystore for the transmitted certificate

        // Search the keystore for the alias of the transmitted certificate

        alias = getAliasForX509Cert(issuerString, issuerSerial);

        if (alias != null) {
            // Retrieve the certificate for the alias from the keystore

            certs = getCertificates(alias);

            // If certificates have been found, the certificates must be
            // compared
            // to ensure againgst phony DNs (compare encoded form including
            // signature)
            if (certs != null && certs.length > 0 && cert.equals(certs[0])) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Direct trust for certificate with "
                            + subjectString);
                }
                return true;
            }
        } else {
            if (LOG.isDebugEnabled()) {
                LOG.debug("No alias found for subject from issuer with "
                        + issuerString + " (serial " + issuerSerial + ")");
            }
        }

        // SECOND step
        // Search for the issuer of the transmitted certificate in the keystore

        // Search the keystore for the alias of the transmitted certificates
        // issuer

        aliases = getAliasesForDN(issuerString);

        // If the alias has not been found, the issuer is not in the keystore
        // As a direct result, do not trust the transmitted certificate
        if (aliases == null || aliases.length < 1) {
            if (LOG.isDebugEnabled()) {
                LOG
                        .debug("No aliases found in keystore for issuer "
                                + issuerString + " of certificate for "
                                + subjectString);
            }
            return false;
        }

        // THIRD step
        // Check the certificate trust path for every alias of the issuer found
        // in the keystore
        for (int i = 0; i < aliases.length; i++) {
            alias = aliases[i];

            if (LOG.isDebugEnabled()) {
                LOG.debug("Preparing to validate certificate path with alias "
                        + alias + " for issuer " + issuerString);
            }

            // Retrieve the certificate(s) for the alias from the keystore

            certs = getCertificates(alias);

            // If no certificates have been found, there has to be an error:
            // The keystore can find an alias but no certificate(s)
            if (certs == null | certs.length < 1) {
                throw new XKMSException("noCertForAlias");
            }

            // Form a certificate chain from the transmitted certificate
            // and the certificate(s) of the issuer from the keystore
            // First, create new array
            X509Certificate[] x509certs = new X509Certificate[certs.length + 1];
            // Then add the first certificate ...
            x509certs[0] = cert;
            // ... and the other certificates
            for (int j = 0; j < certs.length; j++) {
                cert = certs[i];
                x509certs[certs.length + j] = cert;
            }
            certs = x509certs;

            // Use the validation method from the crypto to check whether the
            // subjects certificate was really signed by the issuer stated in
            // the certificate

            if (validateCertPath(certs)) {
                if (LOG.isDebugEnabled()) {
                    LOG
                            .debug("WSHandler: Certificate path has been verified for certificate with subject "
                                    + subjectString);
                }
                return true;
            }
        }

        LOG
                .debug("WSHandler: Certificate path could not be verified for certificate with subject "
                        + subjectString);
        return false;
    }

    public String getAliasForX509Cert(byte[] skiBytes) throws XKMSException {
        Certificate cert = null;
        boolean found = false;

        try {
            for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
                String alias = (String) e.nextElement();
                Certificate[] certs = keystore.getCertificateChain(alias);
                if (certs == null || certs.length == 0) {
                    // no cert chain, so lets check if getCertificate gives us a
                    // result.
                    cert = keystore.getCertificate(alias);
                    if (cert == null) {
                        return null;
                    }
                } else {
                    cert = certs[0];
                }
                if (!(cert instanceof X509Certificate)) {
                    continue;
                }
                byte[] data = getSKIBytesFromCert((X509Certificate) cert);
                if (data.length != skiBytes.length) {
                    continue;
                }
                if (Arrays.equals(data, skiBytes)) {
                    return alias;
                }
            }
        } catch (KeyStoreException e) {
            throw new XKMSException(e);
        }
        return null;
    }

    public byte[] getSKIBytesFromCert(X509Certificate cert)
            throws XKMSException {
        /*
         * Gets the DER-encoded OCTET string for the extension value (extnValue)
         * identified by the passed-in oid String. The oid string is represented
         * by a set of positive whole numbers separated by periods.
         */
        byte[] derEncodedValue = cert.getExtensionValue(SKI_OID);

        if (cert.getVersion() < 3 || derEncodedValue == null) {
            PublicKey key = cert.getPublicKey();
            if (!(key instanceof RSAPublicKey)) {
                throw new XKMSException("noSKIHandling");
            }
            byte[] encoded = key.getEncoded();
            // remove 22-byte algorithm ID and header
            byte[] value = new byte[encoded.length - 22];
            System.arraycopy(encoded, 22, value, 0, value.length);
            MessageDigest sha;
            try {
                sha = MessageDigest.getInstance("SHA-1");
            } catch (NoSuchAlgorithmException ex) {
                throw new XKMSException("noSKIHandling");
            }
            sha.reset();
            sha.update(value);
            return sha.digest();
        }

        /**
         * Strip away first four bytes from the DerValue (tag and length of
         * ExtensionValue OCTET STRING and KeyIdentifier OCTET STRING)
         */
        byte abyte0[] = new byte[derEncodedValue.length - 4];

        System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
        return abyte0;
    }
}
TOP

Related Classes of org.wso2.xkms2.service.XKMSServerCrypto

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.