com.vmware.certificate.Client.java Source code

Java tutorial

Introduction

Here is the source code for com.vmware.certificate.Client.java

Source

/*
 * Copyright  2012-2015 VMware, Inc.  All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the License?); you may not
 * use this file except in compliance with the License.  You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS? BASIS, without
 * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.vmware.certificate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.apache.commons.codec.binary.Base64;

import com.sun.jna.Pointer;

/**
 * @author Anu Engineer
 *
 */
public class Client implements Iterable<X509Certificate> {
    public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----\n";
    public static final String END_CERT = "\n-----END CERTIFICATE-----";

    private String ServerName;

    public enum certFilters {
        ACTIVE_CERTIFICATES, REVOKED_CERTIFICATES, EXPIRED_CERTIFICATES, ALL_CERTIFICATES

    }

    /**
     * Creates a Client class that allows you to communicate to a VMCA Server
     *
     * @param ServerName
     *           - Name of the VMCA Server
     */
    public Client(String ServerName) {
        this.setServerName(ServerName);
        setEnumFilter(certFilters.ACTIVE_CERTIFICATES);

    }

    /**
     * Creates a Certificate from a PEM encoded String
     *
     * @param certificateString
     * @return
     * @throws Exception
     */
    public static X509Certificate getCertificateFromString(String certificateString) throws Exception {
        InputStream is = new ByteArrayInputStream(certificateString.getBytes());
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        X509Certificate c = (X509Certificate) cf.generateCertificate(is);
        return c;

    }

    private String encodeX509CertificatesToString(X509Certificate[] certs) throws Exception {
        if (certs == null || certs.length == 0) {
            return null;
        }

        int stringBuilderSize = certs.length * 1024; // approximate string builder
                                                     // size
        StringBuilder sb = new StringBuilder(stringBuilderSize);
        for (X509Certificate cert : certs) {
            String pem = getEncodedStringFromCertificate(cert);
            sb.append(pem);
            sb.append('\n');
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }

        return sb.toString();
    }

    /**
     * returns a PEM Encoded String from a X509Certificate
     *
     * @param certificate
     * @return
     * @throws Exception
     */
    private String getEncodedStringFromCertificate(X509Certificate certificate) throws Exception {
        if (certificate == null) {
            throw new IllegalStateException("Invalid Certificate, certificate cannot be null");
        }

        String encoded = new String(Base64.encodeBase64(certificate.getEncoded()));
        StringBuffer pemencode = new StringBuffer();
        for (int x = 0; x < encoded.length(); x++) {

            if ((x > 0) && (x % 64 == 0)) {
                pemencode.append("\n");
                pemencode.append(encoded.charAt(x));
            } else {
                pemencode.append(encoded.charAt(x));

            }
        }
        return BEGIN_CERT + pemencode.toString() + END_CERT;

    }

    /*
     * retuns a PEM encoded CSR
     *quest
     *           - A Fully populated and Signed PKCS10 Object
     * @return Base64 Encoded DER string
        
    public static String getEncodedStringFromPKCS10(PKCS10 certRequest)
     throws Exception {
     throw new IllegalStateException(
           "Invalid PKCS10 request, request cannot be null");
       }
       ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
       PrintStream printStream = new PrintStream(byteStream);
       certRequest.print(printStream);
       byte[] pkcsBytes = byteStream.toByteArray();
       return new String(pkcsBytes);
    }
        
    */
    /**
     * Gets root CA Certificate Array from VMCA
     *
     * @return X509Certificate Root CA Certificate
     * @throws Exception
     */
    public X509Certificate[] getRootCertificates() throws Exception {

        ArrayList<X509Certificate> trustedRoots = new ArrayList<X509Certificate>();
        trustedRoots.add(Client.getCertificateFromString(VMCAAdapter.GetRootCertificate(ServerName)));
        return trustedRoots.toArray(new X509Certificate[trustedRoots.size()]);
    }

    /**
     * Adding new root CA Certificate chain to VMCA
     *
     * @param certificateChain
     *           Chain of certificates in case VMCA becomes a subordinate CA. Remember that the leaf certificate goes first (at index 0).
     * @param key
     * @throws Exception
     */
    public void addRootCertificate(X509Certificate[] certificateChain, PrivateKey key) throws Exception {
        VMCAAdapter.AddRootCertificate(ServerName, encodeX509CertificatesToString(certificateChain),
                encodePrivateKeyToString(key));
    }

    /**
     * Gets root CA Certificate from VMCA
     *
     * @return X509Certificate Root CA Certificate
     * @throws Exception
     */

    public X509Certificate getRootCertificate() throws Exception {
        return Client.getCertificateFromString(VMCAAdapter.GetRootCertificate(ServerName));
    }

    /*
     * Returns a Signed Certificate from the Server
     *
     * @param certificateRequest
     *           -- A PKCS 10 Certificate request
     * @param notBefore
     *           - Start date of the Certificate
     * @param notAfter
     *           - End Date of the Certificate
     * @return X509Certificate
     * @throws Exception
     */

    public X509Certificate getCertificate(String certificateRequest, Date notBefore, Date notAfter)
            throws Exception {

        long epochNotBefore = notBefore.getTime();
        long epochNotAfter = notAfter.getTime();

        epochNotBefore = epochNotBefore / 1000;
        epochNotAfter = epochNotAfter / 1000;

        return getCertificateFromString(VMCAAdapter.VMCAGetSignedCertificateFromCSR(ServerName, certificateRequest,
                epochNotBefore, epochNotAfter));
    }

    private String encodePrivateKeyToString(PrivateKey key) throws UnsupportedEncodingException {
        if (key == null) {
            return null;
        }
        byte[] privBytes = key.getEncoded();
        String encoded = new String(Base64.encodeBase64(privBytes));
        StringBuffer pemencode = new StringBuffer();
        for (int x = 0; x < encoded.length(); x++) {

            if ((x > 0) && (x % 64 == 0)) {
                pemencode.append("\n");
                pemencode.append(encoded.charAt(x));
            } else {
                pemencode.append(encoded.charAt(x));

            }
        }
        return "-----BEGIN PRIVATE KEY-----\n" + pemencode.toString() + "\n" + "-----END PRIVATE KEY-----";
    }

    private String getPEMEncodedKey(KeyPair Keys) {
        byte[] privBytes = Keys.getPrivate().getEncoded();
        String encoded = new String(Base64.encodeBase64(privBytes));
        StringBuffer pemencode = new StringBuffer();
        for (int x = 0; x < encoded.length(); x++) {

            if ((x > 0) && (x % 64 == 0)) {
                pemencode.append("\n");
                pemencode.append(encoded.charAt(x));
            } else {
                pemencode.append(encoded.charAt(x));

            }
        }
        return "-----BEGIN PRIVATE KEY-----\n" + pemencode.toString() + "\n" + "-----END PRIVATE KEY-----";
    }

    /**
     * Returns a Signed Certificate from the Server
     *
     * @param Req
     *           -- A Request Object
     * @param Keys
     *           - A Java Key Pair Object
     * @param notBefore
     *           - Start Date for the Certificate
     * @param notAfter
     *           - End Date for the validity of the Certificate
     * @return X509Certificate that is signed by VMCA
     */
    public X509Certificate getCertificate(Request req, KeyPair Keys, Date notBefore, Date notAfter)
            throws Exception {

        long epochNotBefore = notBefore.getTime();
        long epochNotAfter = notAfter.getTime();

        epochNotBefore = epochNotBefore / 1000;
        epochNotAfter = epochNotAfter / 1000;
        String certString = VMCAAdapter.VMCAJavaGenCert(this.getServerName(), req.getName(), req.getCountry(),
                req.getLocality(), req.getState(), req.getOrganization(), req.getOrgunit(), req.getDnsname(),
                req.getUri(), req.getEmail(), req.getIpaddress(), req.getKeyusage(), 0, getPEMEncodedKey(Keys),
                epochNotBefore, epochNotAfter);

        return getCertificateFromString(certString);

    }

    /**
     * Revokes a Certificate
     *
     * @param certificate
     * @throws Exception
     */
    public void RevokeCertificate(X509Certificate certificate) throws Exception {
        VMCAAdapter.RevokeCertificate(ServerName, getEncodedStringFromCertificate(certificate));
    }

    /**
     * Gets the Name of the Server we are talking to
     *
     * @return Server Name
     */
    public String getServerName() {
        return ServerName;
    }

    /**
     * Gets the VMCA Server Version
     *
     * @return Version String
     * @throws Exception
     */
    public String getServerVersion() throws Exception {
        return VMCAAdapter.getServerVersion(ServerName);
    }

    /**
     * Sets the ServerName which we are communicating
     *
     * @param serverName
     */
    public void setServerName(String serverName) {
        ServerName = serverName;
    }

    /* (non-Javadoc)
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public Iterator<X509Certificate> iterator() {
        return new VMCACertIterator(ServerName, filterToInteger(getEnumFilter()));

    }

    /**
     * @return the enumFilter
     */
    public certFilters getEnumFilter() {
        return enumFilter;
    }

    /**
     * @param enumFilter
     *           the enumFilter to set
     */
    public void setEnumFilter(certFilters enumFilter) {
        this.enumFilter = enumFilter;
    }

    private certFilters enumFilter;

    /**
     * filter to Integer, since I am using ENUM java Enum to Integer is not
     * direct
     *
     * @param filter
     * @return
     */
    private static int filterToInteger(final certFilters filter) {
        switch (filter) {
        case ACTIVE_CERTIFICATES:
            return 0;
        case REVOKED_CERTIFICATES:
            return 1;
        case EXPIRED_CERTIFICATES:
            return 2;
        case ALL_CERTIFICATES:
            return 4;
        }
        return 0;
    }

    private class VMCACertIterator implements Iterator<X509Certificate> {
        private Pointer ctx;
        private String nextCert;
        private int certFilter;

        /**
         * Ctor for Iterator
         *
         * @param serverName
         * @param certFilter
         */
        public VMCACertIterator(String serverName, int certFilter) {
            try {
                this.certFilter = certFilter;
                ctx = VMCAAdapter.VMCAOpenEnumContext(serverName, this.certFilter);
            } catch (Exception e) {
                // Nothing much to do here.
            }
        }

        @Override
        public boolean hasNext() {
            try {
                if (ctx != null) {
                    nextCert = VMCAAdapter.VMCAGetNextCertificate(ctx);
                    if (nextCert != null) {
                        return true;
                    } else {
                        VMCAAdapter.VMCACloseEnumContext(ctx);
                        ctx = null;
                    }
                }
            } catch (Exception e) {
                if (ctx != null) {
                    VMCAAdapter.VMCACloseEnumContext(ctx);
                    ctx = null;
                }
            }
            return false;
        }

        @Override
        public X509Certificate next() {
            try {
                return Client.getCertificateFromString(nextCert);
            } catch (Exception e) {
                throw new NoSuchElementException(e.getMessage());
            }
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException(
                    "To Remove or Revoke a Certificate, Please use Revoke Certificate");

        }

    }

    public void getCRL(String existingCRL, String string) throws VMCAException {
        @SuppressWarnings("unused")
        String returnedCRL = VMCAAdapter.VMCAGetCRL(this.getServerName(), existingCRL, string);
    }

    public void PublishRoots() throws VMCAException, Exception {
        VMCAAdapter.VMCAPublishRoots(this.getServerName());
    }

}