org.vpac.grix.model.certificate.PKCS12Certificate.java Source code

Java tutorial

Introduction

Here is the source code for org.vpac.grix.model.certificate.PKCS12Certificate.java

Source

/* Copyright 2006 VPAC
 * 
 * This file is part of Grix.
 * Grix is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
    
 * Grix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
    
 * You should have received a copy of the GNU General Public License
 * along with Grix; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package org.vpac.grix.model.certificate;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration;

import org.apache.log4j.Logger;
import org.bouncycastle.util.encoders.Base64;
import org.globus.gsi.OpenSSLKey;
import org.globus.gsi.bc.BouncyCastleOpenSSLKey;
import org.globus.util.PEMUtils;
import org.vpac.common.model.GlobusLocations;

/**
 * This class represents a PKCS12 certificate, which contains of a private key
 * and a certificate (which is a public key signed by a ca). This class is not
 * really finished yet, so beware if you use it and read the documentation of
 * the constructors.
 * 
 * @author markus
 * 
 */
public class PKCS12Certificate {

    static final Logger myLogger = Logger.getLogger(PKCS12Certificate.class.getName());

    private OpenSSLKey privateKey;

    private X509Certificate x509certificate;

    private Certificate certificate;

    private String alias;

    /**
     * This constructor reads both (PEM encoded) private key and certificate.
     * It's usefull if you want to export a .p12 file. Beware: If created with
     * this constructor, this object does not actually hold a certificate. Maybe
     * it will later, but at the moment I don't have the time to clean up the
     * code.
     * 
     * @param pem_privateKey
     *            The filename of the private key
     * @param pem_certificate
     *            The filename of the certificate
     * @param alias
     *            The alias of the private key
     * @throws GeneralSecurityException
     * @throws IOException
     *             If there is a problem reading a file
     */
    public PKCS12Certificate(String pem_privateKey, String pem_certificate, String alias)
            throws IOException, GeneralSecurityException {

        // read certificate
        FileInputStream in = new FileInputStream(pem_certificate);
        CertificateFactory cf = CertificateFactory.getInstance("X509", "BC");
        x509certificate = (X509Certificate) cf.generateCertificate(in);
        in.close();

        // read private key

        privateKey = new BouncyCastleOpenSSLKey(pem_privateKey);

        this.alias = alias;

    }

    /**
     * Parses a p12 file and loads the first certificate and private key into
     * this object. Use this constructor if you want to export pem files out of
     * a .p12 file.
     * 
     * @param p12File
     * @param passphrase
     * @throws IOException
     * @throws GeneralSecurityException
     */
    public PKCS12Certificate(File p12File, char[] passphrase) throws IOException, GeneralSecurityException {

        KeyStore ks = KeyStore.getInstance("PKCS12");
        FileInputStream pkcs12File = new FileInputStream(p12File);
        ks.load(pkcs12File, passphrase);
        pkcs12File.close();

        Enumeration<String> aliases = ks.aliases();
        // this takes the first alias
        alias = aliases.nextElement();

        // while (aliases.hasMoreElements()){
        // System.out.println("Alias: "+aliases.nextElement());
        // }

        privateKey = new BouncyCastleOpenSSLKey((PrivateKey) ks.getKey(alias, passphrase));
        if (privateKey == null) {
            throw new GeneralSecurityException("No private key found in keystore.");
        }
        // System.out.println(privateKey.getFormat());

        java.security.cert.Certificate javaCertificate = ks.getCertificate(alias);
        // System.out.println(certificate.getPublicKey().getAlgorithm());
        if (javaCertificate == null) {
            Arrays.fill(passphrase, 'x');
            throw new GeneralSecurityException("No certificate found in keystore");
        }

        byte[] cert = null;

        cert = javaCertificate.getEncoded();

        cert = Base64.encode(cert);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PEMUtils.writeBase64(out, Certificate.PEM_HEADER, cert, Certificate.PEM_FOOTER);
        out.close();

        certificate = new Certificate(out.toString());

    }

    public boolean writeToP12File(char[] passphrase, String p12file) throws InvalidKeyException {

        X509Certificate[] certChain = new X509Certificate[1];
        KeyStore ks = null;
        try {
            ks = KeyStore.getInstance("PKCS12", "BC");
            ks.load(null, null);
            certChain[0] = x509certificate;
        } catch (Exception e) {
            // TODO
            e.printStackTrace();
        }

        try {
            privateKey.decrypt(new String(passphrase));

        } catch (GeneralSecurityException e1) {
            // TODO Auto-generated catch block
            // e1.printStackTrace();
            throw new InvalidKeyException();
        }

        FileOutputStream fos = null;
        // TODO check whether password is needed here or not
        try {
            ks.setKeyEntry(alias, privateKey.getPrivateKey(), null, certChain);
            fos = new FileOutputStream(p12file);
            ks.store(fos, passphrase);

        } catch (IOException ioe) {
            GlobusLocations.defaultLocations().getUserCertPKCS12().delete();
            return false;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            myLogger.debug("Could not write .p12 file");
            GlobusLocations.defaultLocations().getUserCertPKCS12().delete();
            throw new InvalidKeyException();
            // e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                myLogger.error(e);
            }
            // delete passphrase
            Arrays.fill(passphrase, 'x');
        }

        return true;
    }

    public static void main(String[] args) {
        System.out.println("Starting...");
        try {
            PKCS12Certificate cert = new PKCS12Certificate(new File("/home/markus/Desktop/test.p12"),
                    "xxx".toCharArray());

            cert.getCertificate().writeToFile(new File("/home/markus/usercert.pem"));
            cert.getPrivateKey().writeTo("/home/markus/userkey.pem");

        } catch (Exception e) {
            // e.printStackTrace();
            myLogger.error(e);
        }
        System.out.println("Finished.");
    }

    public Certificate getCertificate() {
        return certificate;
    }

    public OpenSSLKey getPrivateKey() {
        return privateKey;
    }

}