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

Java tutorial

Introduction

Here is the source code for org.vpac.grix.model.certificate.CertificationRequest.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.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;

import org.apache.log4j.Logger;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.util.encoders.Base64;
import org.globus.gsi.CertUtil;
import org.globus.util.PEMUtils;
import org.vpac.common.exceptions.MissingInformationException;
import org.vpac.grix.control.utils.GrixProperty;

/**
 * A certification request similar/compatible with the one created by openssl
 * e.g.: openssl req -newkey rsa:1024 -config ./apacgrid-openssl.cnf -out
 * usercert-request.pem
 * 
 * @author Markus Binsteiner
 * 
 */
public class CertificationRequest {

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

    private final String signatureAlgorithm;

    private GlobusKeyPair keypair;

    private String c = "";

    private String o = "";

    private String ou = "";

    private String cn = "";

    private String email = "";

    private X509Name dn = null;

    /**
     * Creates a certification request with the specified Subject. Generates a
     * RSA keypair. The private key has to be stored by the user manually.
     * 
     * @param c
     *            the country
     * @param o
     *            the organization
     * @param ou
     *            the organization unit
     * @param cn
     *            the name of the applicant
     * @param email
     *            the email address of the applicant
     * @param passphrase
     *            the passphrase to encrypt the private key
     * @throws GeneralSecurityException
     * @throws MissingInformationException
     * @throws
     */
    public CertificationRequest(String c, String o, String ou, String cn, String email, int keysize,
            String signature_algorithm, boolean hostcert)
            throws GeneralSecurityException, MissingInformationException {

        this.c = c;
        this.o = o;
        this.ou = ou;
        this.cn = cn;
        this.email = email;

        createDN(hostcert);

        this.keypair = GlobusKeyPair.globusKeyPairFactory(keysize);
        this.signatureAlgorithm = signature_algorithm;
    }

    /**
     * Creates a certification request with the specified Subject. Generates a
     * RSA keypair. The private key has to be stored by the user manually.
     * 
     * @param c
     *            the country
     * @param o
     *            the organization
     * @param ou
     *            the organization unit
     * @param cn
     *            the name of the applicant
     * @param passphrase
     *            the passphrase to encrypt the private key
     * @throws GeneralSecurityException
     * @throws MissingInformationException
     * @throws
     */
    public CertificationRequest(String c, String o, String ou, String cn, int keysize, String signature_algorithm,
            boolean hostcert) throws GeneralSecurityException, MissingInformationException {

        this.c = c;
        this.o = o;
        this.ou = ou;
        this.cn = cn;

        createDN(hostcert);

        this.keypair = GlobusKeyPair.globusKeyPairFactory(keysize);
        this.signatureAlgorithm = signature_algorithm;
    }

    /**
     * Creates a certification request without user details. Only sets the
     * signature algorithm and creates a keypair.
     * 
     * @throws GeneralSecurityException
     * @throws
     * 
     * @throws SecurityProviderException
     */
    public CertificationRequest(int keysize, String signature_algorithm) throws GeneralSecurityException {

        this.keypair = GlobusKeyPair.globusKeyPairFactory(keysize);
        this.signatureAlgorithm = signature_algorithm;
    }

    /**
     * Broken!!! This constructor does not read the public key in the .pem file
     * It just parses the subject line and fills the dn fields.
     * 
     * @param file
     *            the certificate request with a subject line containing the DN
     * @param signature_algorithm
     *            the algorithm for the private key. Use
     *            GrixProperty.getString("signature.algorithm");
     * @param hostcert
     *            whether the certification request was for a hostcert or not
     * @throws IOException
     * @throws MissingInformationException
     */
    public CertificationRequest(File file, String signature_algorithm, boolean hostcert)
            throws IOException, MissingInformationException {

        this.signatureAlgorithm = signature_algorithm;

        BufferedReader input = null;
        try {
            input = new BufferedReader(new FileReader(file));
            String line = null; // not declared within while loop

            while ((line = input.readLine()) != null) {
                if (line.startsWith("/C=")) {
                    parseDN(line, hostcert);
                }
            }
        } finally {
            try {
                if (input != null) {
                    // flush and close both "input" and its underlying
                    // FileReader
                    input.close();
                }
            } catch (Exception e) {
                // e.printStackTrace();
                myLogger.error(e);
            }
        }
    }

    private void parseDN(String line, boolean hostcert) throws MissingInformationException {

        this.c = line.substring(line.indexOf("/C=") + 3, line.indexOf("/O="));
        this.o = line.substring(line.indexOf("/O=") + 3, line.indexOf("/OU="));
        this.ou = line.substring(line.indexOf("/OU=") + 4, line.indexOf("/CN="));
        // if (!hostcert){
        if (line.indexOf("/Email") != -1) {
            this.cn = line.substring(line.indexOf("/CN=") + 4, line.indexOf("/Email="));
            this.email = line.substring(line.indexOf("/Email=") + 7);
        } else {
            this.cn = line.substring(line.indexOf("/CN=") + 4, line.indexOf("/E="));
            this.email = line.substring(line.indexOf("/E=") + 3);
        }
        // } else {
        // this.cn = line.substring( line.indexOf( "/CN=")+4 );
        // }
        createDN(hostcert);

    }

    /**
     * Concatenates all the user information to a DN and stores the DN into the
     * X509Name field dn.
     * 
     * @param hostcert
     *            whether this is for a hostcert or not
     * @throws MissingInformationException
     */
    public void createDN(boolean hostcert) throws MissingInformationException {

        ArrayList<String> missingInformation = new ArrayList<String>();

        if (this.c.equals(""))
            missingInformation.add("C");
        if (this.o.equals(""))
            missingInformation.add("O");
        if (this.ou.equals(""))
            missingInformation.add("OU");
        if (this.cn.equals(""))
            missingInformation.add("CN");
        if (this.email.equals(""))
            missingInformation.add("EMAIL");

        if (missingInformation.size() == 0) {
            if (!hostcert) {
                // user certificate
                this.dn = new X509Name(
                        "C=" + c + ", O=" + o + ", OU=" + ou + ", CN=" + cn + ", emailAddress=" + email);
            } else {
                // host certificate
                this.dn = new X509Name(
                        "C=" + c + ", O=" + o + ", OU=" + ou + ", CN=" + cn + ", emailAddress=" + email);

            }
        } else {

            throw new MissingInformationException("Could not create DN: not enough information available",
                    missingInformation);
        }
    }

    /**
     * Creates a certification request with the specified//
     * PEMUtils.writeBase64(ps, "-----BEGIN CERTIFICATE REQUEST-----", //
     * encodedData, "-----END CERTIFICATE REQUEST-----"); Subject.
     * 
     * @param dn
     *            the subject (e.g. "C=AU, O=APACGrid, OU=VPAC, ..."
     * @param keypair
     *            the GlobusKeyPair to use for the certification request.
     * @throws NoSuchPropertyException
     */
    public CertificationRequest(GlobusKeyPair keypair) {

        this.signatureAlgorithm = GrixProperty.getString("signature.algorithm");
        this.keypair = keypair;
    }

    /**
     * creates a encoded representation of the certification request.
     * 
     * @return the certification request.
     */
    public String getEncodedRequest() {

        String request_string = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        // stolen from jglobus.jar:

        // nothing in it
        DERSet derset = new DERSet();
        PublicKey pubkey = this.keypair.getPublicKey();
        PrivateKey privkey = this.keypair.getPrivateKey().getPrivateKey();

        PKCS10CertificationRequest request = null;

        try {
            // using the already implemented .getEncoded() function of
            // PKCS10CertificationRequest
            request = new PKCS10CertificationRequest(this.signatureAlgorithm, this.dn, pubkey, derset, privkey);

            PEMUtils.writeBase64(out, "-----BEGIN CERTIFICATE REQUEST-----", Base64.encode(request.getEncoded()),
                    "-----END CERTIFICATE REQUEST-----");

            request_string = out.toString();
            out.close();
        } catch (Exception e) {
            // TODO throw new SecurityProviderException("Could not write
            // certification request to file.");
            // e.printStackTrace();
            myLogger.error(e);
        }

        return request_string;
    }

    /**
     * Writes the certification request to a PEM encoded file
     * 
     * @param certReqFile
     *            the file
     * @throws IOException
     * @throws Exception
     */
    public void writeToPEMFile(File certReqFile) throws IOException {

        if (!certReqFile.getParentFile().exists())
            if (!certReqFile.getParentFile().mkdirs())
                throw new IOException("Could not create directory: " + certReqFile.getParent());

        // if ( !certReqFile.canWrite() ) throw new
        // IOException("Can not write file: "+certReqFile.toString());

        PrintStream ps = null;

        try {
            ps = new PrintStream(new FileOutputStream(certReqFile));

            ps.print("\n\n" + "Please mail the following certificate request to "
                    + GrixProperty.getString("CA_EMAIL_ADDRESS") + "\n" + "\n"
                    + "==================================================================\n" + "\n"
                    + "Certificate Subject:\n" + "\n" + CertUtil.toGlobusID(this.dn.toString()) + "\n" + "\n"
                    + "The above string is known as your user certificate subject, and it \n"
                    + "uniquely identifies this user.\n" + "\n"
                    + "To install this user certificate, please save this e-mail message\n"
                    + "into the following file.\n" + "\n" + "\n" + certReqFile.getAbsolutePath() + "\n" + "\n"
                    + "\n" + "      You need not edit this message in any way. Simply \n"
                    + "      save this e-mail message to the file.\n" + "\n" + "\n"
                    + "If you have any questions about the certificate contact\n" + "the Certificate Authority at "
                    + GrixProperty.getString("CA_EMAIL_ADDRESS") + "\n" + "\n" + getEncodedRequest());
        } finally {
            if (ps != null) {
                ps.close();
            }
        }

    }

    /**
     * @return the keypair
     */
    public GlobusKeyPair getKeypair() {

        return keypair;
    }

    /**
     * @param keypair
     *            the keypair to set
     */
    public void setKeypair(GlobusKeyPair keypair) {

        this.keypair = keypair;
    }

    /**
     * @return the c
     */
    public String getC() {

        return c;
    }

    /**
     * @param c
     *            the c to set
     */
    public void setC(String c) {

        this.c = c;
    }

    /**
     * @return the cn
     */
    public String getCn() {

        return cn;
    }

    /**
     * @param cn
     *            the cn to set
     */
    public void setCn(String cn) {

        this.cn = cn;
    }

    /**
     * @return the dn
     */
    public X509Name getDn() {

        return dn;
    }

    public String getDNwithoutEmail() {

        int index = dn.toString().indexOf(",E=");
        if (index == -1)
            index = dn.toString().indexOf(",Email=");
        return dn.toString().substring(0, index);
    }

    /**
     * @param dn
     *            the dn to set
     */
    public void setDn(X509Name dn) {

        this.dn = dn;
    }

    /**
     * @return the email
     */
    public String getEmail() {

        return email;
    }

    /**
     * @param email
     *            the email to set
     */
    public void setEmail(String email) {

        this.email = email;
    }

    /**
     * @return the o
     */
    public String getO() {

        return o;
    }

    /**
     * @param o
     *            the o to set
     */
    public void setO(String o) {

        this.o = o;
    }

    /**
     * @return the ou
     */
    public String getOu() {

        return ou;
    }

    /**
     * @param ou
     *            the ou to set
     */
    public void setOu(String ou) {

        this.ou = ou;
    }

}