Package org.apache.geronimo.security.ca

Source Code of org.apache.geronimo.security.ca.GeronimoCertificationAuthority

/**
*
*  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.apache.geronimo.security.ca;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Date;

import javax.security.auth.x500.X500Principal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.GBeanInfo;
import org.apache.geronimo.gbean.GBeanInfoBuilder;
import org.apache.geronimo.gbean.GBeanLifecycle;
import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.management.geronimo.CertificateRequestStore;
import org.apache.geronimo.management.geronimo.CertificateStore;
import org.apache.geronimo.management.geronimo.CertificateStoreException;
import org.apache.geronimo.management.geronimo.CertificationAuthority;
import org.apache.geronimo.management.geronimo.CertificationAuthorityException;
import org.apache.geronimo.management.geronimo.KeystoreException;
import org.apache.geronimo.management.geronimo.KeystoreInstance;
import org.apache.geronimo.system.serverinfo.ServerInfo;
import org.apache.geronimo.crypto.CaUtils;
import org.apache.geronimo.crypto.asn1.ASN1InputStream;
import org.apache.geronimo.crypto.asn1.DERBitString;
import org.apache.geronimo.crypto.asn1.DEREncodableVector;
import org.apache.geronimo.crypto.asn1.DERInteger;
import org.apache.geronimo.crypto.asn1.DERObject;
import org.apache.geronimo.crypto.asn1.DERSequence;
import org.apache.geronimo.crypto.asn1.pkcs.PKCSObjectIdentifiers;
import org.apache.geronimo.crypto.asn1.x509.AlgorithmIdentifier;
import org.apache.geronimo.crypto.asn1.x509.SubjectPublicKeyInfo;
import org.apache.geronimo.crypto.asn1.x509.TBSCertificateStructure;
import org.apache.geronimo.crypto.asn1.x509.Time;
import org.apache.geronimo.crypto.asn1.x509.V3TBSCertificateGenerator;
import org.apache.geronimo.crypto.asn1.x509.X509Name;
import org.apache.geronimo.security.SecurityNames;

/**
* A Certification Authority implementation using KeystoreInstance to store CA's private key,
* CertificateStore to store issued certificates and CertificateRequestStore to store certificate requests
*
* @version $Rev: 698367 $ $Date: 2008-09-23 17:51:48 -0400 (Tue, 23 Sep 2008) $
*/
public class GeronimoCertificationAuthority implements CertificationAuthority, GBeanLifecycle {
    private static final Logger log = LoggerFactory.getLogger(GeronimoCertificationAuthority.class);

    private ServerInfo serverInfo;
    private Kernel kernel;
    private AbstractName abstractName;

    // KeystoreInstance with CA's private key and certificate
    private KeystoreInstance caKeystore = null;
    // CertificateStore used to store all certificates issued by the CA
    private CertificateStore certStore = null;
    // Password for CA's keystore and private-key
    private char[] password;
    // CertificateRequestStore used to store certificate requests
    private CertificateRequestStore certReqStore = null;
   
    // Cache variables
    // Key alias
    private String alias;
    // CA's private key
    private PrivateKey caPrivateKey;
    // CA's public key
    private PublicKey caPublicKey;
    // CA's own certificate
    private Certificate caCert;
    // CA's name
    private X509Name caName;
   
    /**
     * Constructor
     *
     * @param caKeystore KeystoreInstance containing CA's private-key and certificate
     * @param certStore CertificateStore for storing certificates issued by this CA
     * @param certReqStore CeetificateRequestStore for storing certificates requests
     */
    public GeronimoCertificationAuthority(ServerInfo serverInfo, KeystoreInstance caKeystore, CertificateStore certStore, CertificateRequestStore certReqStore, Kernel kernel, AbstractName abstractName) {
        if(caKeystore == null) throw new IllegalArgumentException("caKeystore is null.");
        if(certStore == null) throw new IllegalArgumentException("certStore is null");
        if(certReqStore == null) throw new IllegalArgumentException("certReqStore is null");
        this.serverInfo = serverInfo;
        this.kernel = kernel;
        this.abstractName = abstractName;
        this.caKeystore = caKeystore;
        this.certStore = certStore;
        this.certReqStore = certReqStore;
    }

    /**
     * This method checks if the CA is locked.
     * @return true if CA is locked, false otherwise.
     */
    public boolean isLocked() {
        return password == null;
    }
   
    /**
     * This method locks the CA.
     */
     public void lock() {
        try {
            caKeystore.lockKeystore(password);
        } catch (KeystoreException e) {
            log.error("Error locking CA.", e);
        }
        password = null;
        caName = null;
        caCert = null;
        caPrivateKey = null;
        alias = null;
    }
   
     /**
      * This method unlocks the CA.
      * @param password Password to unlock the CA.
      */
    public void unlock(char[] password) throws CertificationAuthorityException{
        try {
            this.password = password;
            caKeystore.unlockKeystore(password);
            alias = caKeystore.listPrivateKeys(password)[0];
            caKeystore.unlockPrivateKey(alias, password, password);
            caCert = caKeystore.getCertificate(alias, password);
            caName = CaUtils.getSubjectX509Name(caCert);
            caPrivateKey = caKeystore.getPrivateKey(alias, password, password);
            caPublicKey = caCert.getPublicKey();
        } catch(Exception e) {
            throw new CertificationAuthorityException("Errors in unlocking CA.", e);
        }
    }
   
    /**
     * This method returns CA's name.
     * @throws Exception if CA is locked.
     */
    public X500Principal getName() throws CertificationAuthorityException {
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            return new X500Principal(caName.getEncoded());
        } catch (IOException e) {
            throw new CertificationAuthorityException("Error in getting CA name.", e);
        }
    }

    /**
     * This method returns CA's own certificate.
     * @throws Exception if CA is locked.
     */
    public Certificate getCertificate() throws CertificationAuthorityException {
        if(caCert == null) throw new CertificationAuthorityException("CA Certificate is null. CA may be locked.");
        try {
            return caCert = caKeystore.getCertificate(alias, password);
        } catch (KeystoreException e) {
            log.error("Error getting CA's certificate.", e);
        }
        return null;
    }
   
    /**
     * This method makes the CA issue a self-signed certificate with given details.  This method is usually
     * called while initializing the CA.
     *
     * @param sNo Serial number for self-signed certificate
     * @param validFromDate Certificate validity period start date
     * @param validToDate Certificate validity period end date
     * @param algorithm Signature algorithm for self-signed certificate
     */
    public void issueOwnCertificate(BigInteger sNo, Date validFromDate, Date validToDate, String algorithm) throws CertificationAuthorityException{
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            PublicKey publicKey = caCert.getPublicKey();
            Certificate cert = issueCertificate(getName(), publicKey, sNo, validFromDate, validToDate, algorithm);
            caKeystore.importPKCS7Certificate(alias, CaUtils.base64Certificate(cert), password);
            caCert = cert;
        } catch(Exception e) {
            throw new CertificationAuthorityException("Error in issuing own certificate.", e);
        }
    }
   
    /**
     * This method issues a certificate.
     *
     * @param subject Subject X500Principal
     * @param publicKey Subject's public key
     * @param sNo Serial number for the certificate to be issued
     * @param validFromDate Certificate validity period start date
     * @param validToDate Certificate validity period end date
     * @param algorithm Signature algorithm for the certificate
     * @return newly issued certificate
     */
    public Certificate issueCertificate(X500Principal subject, PublicKey publicKey, BigInteger sNo, Date validFromDate, Date validToDate, String algorithm) throws CertificationAuthorityException{
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            X509Name subName = CaUtils.getX509Name(subject);
            Certificate cert = issueCertificate(subName, caName, sNo, publicKey, caPrivateKey, validFromDate, validToDate, algorithm);
            cert.verify(caPublicKey);
            certStore.storeCertificate(cert);
            return cert;
        } catch(Exception e) {
            throw new CertificationAuthorityException("Error in issuing certificate.", e);
        }
    }
   
    /**
     * This method returns the highest serial number used by the CA.
     */
    public BigInteger getHighestSerialNumber() throws CertificationAuthorityException {
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            return certStore.getHighestSerialNumber();
        } catch (CertificateStoreException e) {
            throw new CertificationAuthorityException("Error in getting highest serial number for CA.", e);
        }
    }
   
    /**
     * This method checks if a Certificate with a given serial number is already issued.
     * @param sNo The serial number of the the certificate to be looked for
     * @return true if a certificate with the specified serial number has already been issued
     */
    public boolean isCertificateIssued(BigInteger sNo) throws CertificationAuthorityException {
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        return certStore.containsCertificate(sNo);
    }
   
    /**
     * This method returns the next serial number that can be used to issue a certificate and increments the
     * highest serial number.
     */
    public BigInteger getNextSerialNumber() throws CertificationAuthorityException {
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            return certStore.getNextSerialNumber();
        } catch (CertificateStoreException e) {
            throw new CertificationAuthorityException("Error in getting next serial number for CA.", e);
        }
    }
   
    /**
     * This method retrieves a certificate with the specified serial number.
     * @param sNo The serial number of the certificate to be retrieved
     * @return java.security.cert.Certificate instance of the certificate
     */
    public Certificate getCertificate(BigInteger sNo) throws CertificationAuthorityException {
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            return certStore.getCertificate(sNo);
        } catch (CertificateStoreException e) {
            throw new CertificationAuthorityException("Error getting certificate. serial number = "+sNo, e);
        }
    }

    /**
     * This method retrieves a certificate with the specified serial number.
     * @param sNo The serial number of the certificate to be retrieved
     * @return base64 encoded certificate text
     */
     public String getCertificateBase64Text(BigInteger sNo) throws CertificationAuthorityException {
        if(isLocked()) throw new CertificationAuthorityException("CA is locked.");
        try {
            return certStore.getCertificateBase64Text(sNo);
        } catch (CertificateStoreException e) {
            throw new CertificationAuthorityException("Error getting certificate. serial number = "+sNo, e);
        }
    }
   
    /**
     * This method issues a certificate.
     * @param subName Subject's name
     * @param caName Issuer's name
     * @param serialNum Serial number for the certificate
     * @param subPubKey Subject's public key
     * @param caPriKey Issuer's private key
     * @param validFromDate Certificate validity period start date
     * @param validToDate Certificate validity period end date
     * @param algorithm Signature algorithm for the certificate
     * @return issued certificate
     */
    private Certificate issueCertificate(X509Name subName, X509Name caName, BigInteger serialNum, PublicKey subPubKey, PrivateKey caPriKey, Date validFromDate, Date validToDate, String algorithm) throws Exception {
        AlgorithmIdentifier algId = null;
        if("MD2withRSA".equalsIgnoreCase(algorithm))
            algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.md2WithRSAEncryption);
        else if("MD5withRSA".equalsIgnoreCase(algorithm))
            algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);
        else if("SHA1withRSA".equalsIgnoreCase(algorithm))
            algId = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption);
        else
            throw new CertificationAuthorityException("Signature algorithm "+algorithm+" is not supported.");
       
        ASN1InputStream ais = new ASN1InputStream(subPubKey.getEncoded());
        DERObject subPubkeyDerObj = ais.readObject();
        SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(subPubkeyDerObj);
       
        // Create certificate generator and initialize fields
        // Certificate version is v3
        V3TBSCertificateGenerator v3certGen = new V3TBSCertificateGenerator();
        // Subject info
        v3certGen.setSubject(subName);
        v3certGen.setSubjectPublicKeyInfo(subPubKeyInfo);
        // Issuer info
        v3certGen.setIssuer(caName);
        // serial number
        v3certGen.setSerialNumber(new DERInteger(serialNum));
        // validity
        v3certGen.setStartDate(new Time(validFromDate));
        v3certGen.setEndDate(new Time(validToDate));
        // signature algorithm
        v3certGen.setSignature(algId);
       
        // Get the certificate info to be signed
        TBSCertificateStructure tbsCert = v3certGen.generateTBSCertificate();
        byte[] tobesigned = tbsCert.getEncoded();
       
        // Create the signature
        Signature signatureObj = Signature.getInstance(algorithm);
        signatureObj.initSign(caPriKey);
        signatureObj.update(tobesigned);
        byte[] signature = signatureObj.sign();
       
        // Compose tbsCert, algId and signature into a DER sequence.
        // This will be the certificate in DER encoded form
        DEREncodableVector certDerVec = new DEREncodableVector();
        certDerVec.add(tbsCert);
        certDerVec.add(algId);
        certDerVec.add(new DERBitString(signature));
        DERSequence certDerSeq = new DERSequence(certDerVec);
        byte[] certData = certDerSeq.getEncoded();
       
        // Create a java.security.cert.Certificate object
        Certificate certificate = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(certData));

        return certificate;
    }

    public void doFail() {
    }

    public void doStart() throws Exception {
        if(caKeystore.isKeystoreLocked()) {
            lock();
        }
    }

    public void doStop() throws Exception {
    }
    public static final GBeanInfo GBEAN_INFO;

    static {
        GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(GeronimoCertificationAuthority.class, SecurityNames.CERTIFICATION_AUTHORITY);
        infoFactory.addAttribute("kernel", Kernel.class, false);
        infoFactory.addAttribute("abstractName", AbstractName.class, false);
        infoFactory.addReference("ServerInfo", ServerInfo.class);
        infoFactory.addReference("KeystoreInstance", KeystoreInstance.class, SecurityNames.KEYSTORE_INSTANCE);
        infoFactory.addReference("CertificateStore", CertificateStore.class, "CertificateStore");
        infoFactory.addReference("CertificateRequestStore", CertificateRequestStore.class, "CertificateRequestStore");
        infoFactory.addInterface(CertificationAuthority.class);
        infoFactory.setConstructor(new String[]{"ServerInfo", "KeystoreInstance", "CertificateStore", "CertificateRequestStore", "kernel", "abstractName"});

        GBEAN_INFO = infoFactory.getBeanInfo();
    }
    public static GBeanInfo getGBeanInfo() {
        return GBEAN_INFO;
    }
}
TOP

Related Classes of org.apache.geronimo.security.ca.GeronimoCertificationAuthority

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.