com.raphfrk.bukkit.eventlink.SSLUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.raphfrk.bukkit.eventlink.SSLUtils.java

Source

/*******************************************************************************
 * Copyright (C) 2012 Raphfrk
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
package com.raphfrk.bukkit.eventlink;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.security.KeyManagementException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.security.auth.x500.X500Principal;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;

public class SSLUtils {

    // Don't forget to sync random
    static final SecureRandom random = new SecureRandom();
    static final Object randomLock = new Object();

    static public final Object fileLock = new Object();

    static boolean generateCertificateFile(File file, int keySize, String password, String algorithm,
            String certificateAlgorithm, String certificateName, boolean forceWrite) {

        KeyPair keyPair;
        X509Certificate cert;
        X509V3CertificateGenerator certGen = null;

        String providerName = "BC";

        if (Security.getProvider(providerName) == null) {
            Security.addProvider(new BouncyCastleProvider());
            if (Security.getProvider(providerName) == null) {
                EventLink.logger.log("Crypt libray (" + providerName + ") provider not installed");
                return false;
            }
        }

        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);

            synchronized (randomLock) {
                keyPairGenerator.initialize(keySize, random);
            }

            keyPair = KeyPairGenerator.getInstance(algorithm).generateKeyPair();

            certGen = new X509V3CertificateGenerator();

            certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
            certGen.setIssuerDN(new X500Principal(certificateName));
            certGen.setNotBefore(new Date(System.currentTimeMillis() - 10000));
            certGen.setNotAfter(new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000));
            certGen.setSubjectDN(new X500Principal(certificateName));
            certGen.setPublicKey(keyPair.getPublic());
            certGen.setSignatureAlgorithm(certificateAlgorithm);

            cert = certGen.generate(keyPair.getPrivate(), "BC");
        } catch (IllegalArgumentException iae) {
            EventLink.logger.log("Unable to find provider (BC)");
            iae.printStackTrace();
            if (certGen != null) {
                Iterator itr = certGen.getSignatureAlgNames();
                while (itr.hasNext()) {
                    System.out.println("Algorithm: " + itr.next());
                }
            }
            return false;
        } catch (NoSuchProviderException nspe) {
            EventLink.logger.log("Unable to find provider (BC)");
            nspe.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException nsa) {
            EventLink.logger.log("Unable to implement algorithm (" + certificateAlgorithm + ")");
            if (certGen != null) {
                Iterator<String> itr = certGen.getSignatureAlgNames();
                while (itr.hasNext()) {
                    String algName = itr.next();
                    System.out.println("Algorithm: " + algName + " " + (algName.equals(certificateAlgorithm)));
                }
            }
            nsa.printStackTrace();
            return false;
        } catch (InvalidKeyException ike) {
            EventLink.logger.log("Unable to generate key");
            ike.printStackTrace();
            return false;
        } catch (SignatureException se) {
            EventLink.logger.log("Signature error");
            se.printStackTrace();
            return false;
        } catch (CertificateEncodingException cee) {
            EventLink.logger.log("Encoding error");
            cee.printStackTrace();
            return false;
        }

        return createKeyFile(file, password, keyPair, cert, forceWrite);

    }

    static boolean createKeyFile(File file, String password, KeyPair keyPair, Certificate cert, boolean force) {

        char[] passwordArray = password.toCharArray();

        KeyStore ks;

        try {
            ks = KeyStore.getInstance("JKS");
            ks.load(null, passwordArray);
        } catch (KeyStoreException e) {
            EventLink.logger.log("Keystore creation error");
            e.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        } catch (CertificateException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

        if (keyPair != null && cert != null) {
            Certificate[] certs = new Certificate[1];
            certs[0] = cert;

            System.out.println(cert.toString());

            try {
                ks.setKeyEntry("privateKeyAlias", keyPair.getPrivate(), passwordArray, certs);
            } catch (KeyStoreException e) {
                EventLink.logger.log("Failed to add keys to store");
                e.printStackTrace();
                return false;
            }
        }

        synchronized (fileLock) {
            FileOutputStream fos = null;
            try {
                if (force || !file.exists()) {
                    ks.store(fos = new FileOutputStream(file), passwordArray);
                }

            } catch (KeyStoreException e) {
                e.printStackTrace();
                return false;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return false;
            } catch (CertificateException e) {
                e.printStackTrace();
                return false;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                    }
                }
            }
        }

        return true;

    }

    static KeyStore loadKeyStore(File file, String password) {
        char[] passwordArray = password.toCharArray();

        KeyStore ks = null;

        if (file == null || !file.exists()) {
            return null;
        }

        FileInputStream fis = null;

        synchronized (fileLock) {
            try {
                ks = KeyStore.getInstance("JKS");
                fis = new FileInputStream(file);
                ks.load(fis, passwordArray);
            } catch (KeyStoreException e) {
                EventLink.logger.log("Keystore creation error");
                e.printStackTrace();
                return null;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return null;
            } catch (CertificateException e) {
                e.printStackTrace();
                return null;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } finally {
                try {
                    if (fis != null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    return null;
                }
            }
        }

        return ks;
    }

    static public Enumeration<String> getAliases(File file, String password) {

        KeyStore ks = loadKeyStore(file, password);

        try {
            return ks.aliases();
        } catch (KeyStoreException e) {
            return null;
        }

    }

    static public Certificate getCertificate(File file, String password) {

        KeyStore ks = loadKeyStore(file, password);
        if (ks == null) {
            return null;
        }

        Enumeration<String> aliases;

        try {
            aliases = ks.aliases();
            if (aliases.hasMoreElements()) {
                return ks.getCertificate(aliases.nextElement());
            } else {
                return null;
            }
        } catch (KeyStoreException e) {
            EventLink.logger.log("Unable to read alias list");
            return null;
        }

    }

    static public PrivateKey getPrivateKey(File file, String password) {

        KeyStore ks = loadKeyStore(file, password);
        if (ks == null) {
            return null;
        }

        char[] passwordArray = password.toCharArray();

        try {

            PrivateKey privateKey = null;

            try {
                privateKey = (PrivateKey) ks.getKey("privateKeyAlias", passwordArray);
            } catch (UnrecoverableKeyException e) {
                EventLink.logger.log("Unable to read keys from keystore");
                return null;
            } catch (NoSuchAlgorithmException e) {
                EventLink.logger.log("Unable to read keys from keystore (unknown algorithm)");
                e.printStackTrace();
                return null;
            }

            if (privateKey == null) {
                return null;
            }

            return privateKey;

        } catch (KeyStoreException e) {
            EventLink.logger.log("Unable to read alias list");
            return null;
        }

    }

    static String getFullAlias(KeyStore ks, String serverName) {

        Enumeration<String> aliases;

        try {
            aliases = ks.aliases();
        } catch (KeyStoreException e) {
            return null;
        }

        while (aliases.hasMoreElements()) {
            String current = aliases.nextElement();
            if (current.startsWith(serverName + ";")) {
                return current;
            }
        }

        return null;

    }

    static String removeCertificate(File file, String password, String serverName) {

        synchronized (fileLock) {

            KeyStore ks = loadKeyStore(file, password);

            if (ks == null) {
                return "Failed to load keystore";
            }

            String alias = getFullAlias(ks, serverName);
            if (alias == null) {
                return serverName + " not found in keystore";
            }

            try {
                if (ks.getCertificate(alias) == null) {
                    return serverName + " not found in keystore";
                }
            } catch (KeyStoreException kse) {
                kse.printStackTrace();
                return "Error scanning keystore for cert";
            }

            try {
                ks.deleteEntry(alias);
            } catch (KeyStoreException e) {
                EventLink.logger.log("Failed to remove " + alias + " from store");
                e.printStackTrace();
                return "Error removing key from store";
            }

            return (saveKeyStore(ks, file, password)) ? (alias + " removed from keystore")
                    : "Failed to save updated keystore";

        }

    }

    static boolean addCertificate(File file, String password, String alias, Certificate cert) {

        synchronized (fileLock) {

            KeyStore ks = loadKeyStore(file, password);

            if (ks == null) {
                return false;
            }

            try {
                if (ks.getCertificate(alias) != null) {
                    EventLink.logger.log("Certificate already exists for: " + alias);
                    return false;
                }
            } catch (KeyStoreException kse) {
                kse.printStackTrace();
                return false;
            }

            try {
                ks.setCertificateEntry(alias, cert);
            } catch (KeyStoreException e) {
                EventLink.logger.log("Failed to add cert to store");
                e.printStackTrace();
                return false;
            }

            return saveKeyStore(ks, file, password);

        }

    }

    static boolean saveKeyStore(KeyStore ks, File file, String password) {

        char[] passwordArray = password.toCharArray();

        FileOutputStream out = null;

        synchronized (fileLock) {
            try {
                EventLink.logger.log("Saving certs to store: " + file);
                out = new FileOutputStream(file);
                ks.store(out, passwordArray);
            } catch (KeyStoreException e) {
                e.printStackTrace();
                return false;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return false;
            } catch (CertificateException e) {
                e.printStackTrace();
                return false;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            } finally {
                if (out != null) {
                    try {
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        return false;
                    }
                }
            }
        }

        return true;

    }

    static public KeyManager[] getKeyManagers(File file, String password) {

        char[] passwordArray = password.toCharArray();

        KeyStore ks;

        if (file == null || !file.exists()) {
            return null;
        }

        synchronized (fileLock) {
            FileInputStream fis = null;
            try {
                ks = KeyStore.getInstance("JKS");
                ks.load(fis = new FileInputStream(file), passwordArray);
            } catch (KeyStoreException e) {
                EventLink.logger.log("Keystore creation error");
                e.printStackTrace();
                return null;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return null;
            } catch (CertificateException e) {
                e.printStackTrace();
                return null;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        return null;
                    }
                }
            }
        }

        KeyManagerFactory keyManagerFactory;
        try {
            keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(ks, passwordArray);
        } catch (NoSuchAlgorithmException e) {
            return null;
        } catch (UnrecoverableKeyException e) {
            return null;
        } catch (KeyStoreException e) {
            e.printStackTrace();
            return null;
        }

        return keyManagerFactory.getKeyManagers();

    }

    static SSLSocket getSSLSocket(String hostname, int portnum, KeyManager[] keyManagers,
            TrustManager trustManager) {

        SSLContext sc;
        try {
            sc = SSLContext.getInstance("SSL");
        } catch (NoSuchAlgorithmException e) {
            return null;
        }

        try {
            sc.init(keyManagers, new TrustManager[] { trustManager }, new SecureRandom());
        } catch (KeyManagementException e) {
            return null;
        }

        try {
            SSLSocket socket = (SSLSocket) sc.getSocketFactory().createSocket(hostname, portnum);

            return socket;
        } catch (UnknownHostException e) {
            return null;
        } catch (IOException e) {
            return null;
        }

    }

    static ServerSocket getSSLServerSocket(EventLink p, int portnum, KeyManager[] keyManagers,
            TrustManager trustManager) throws BindException {

        SSLContext sc;

        try {
            sc = SSLContext.getInstance("SSL");
        } catch (NoSuchAlgorithmException e) {
            return null;
        }

        try {
            sc.init(keyManagers, new TrustManager[] { trustManager }, new SecureRandom());
        } catch (KeyManagementException e) {
            p.log("Keymanager exception");
            return null;
        }

        ServerSocket socket = null;

        boolean success = false;

        try {
            socket = sc.getServerSocketFactory().createServerSocket(portnum);
            success = true;
        } catch (UnknownHostException e) {
            p.log("Unknown hostname starting server");
            return null;
        } catch (BindException be) {
            throw be;
        } catch (IOException e) {
            p.log("IO exception starting server");
            return null;
        } finally {
            if (!success) {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                    }
                    socket = null;
                }
            }
        }

        return socket;

    }

    static public String getHostname(String hostname) {
        String[] split = hostname.split(":");

        if (split.length > 1) {
            return split[0];
        } else {
            return hostname;
        }
    }

    static public int getPortnum(String hostname) {
        String[] split = hostname.split(":");

        if (split.length > 1) {
            try {
                return Integer.parseInt(split[1]);
            } catch (NumberFormatException nfe) {
                return 25365;
            }
        } else {
            return 25365;
        }
    }

    static void closeSocket(Socket s) {
        try {
            s.close();
        } catch (IOException ioe) {
        }
    }

}