com.apporiented.hermesftp.utils.SecurityUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.apporiented.hermesftp.utils.SecurityUtil.java

Source

/*
 * ------------------------------------------------------------------------------
 * Hermes FTP Server
 * Copyright (c) 2005-2014 Lars Behnke
 * ------------------------------------------------------------------------------
 * 
 * This file is part of Hermes FTP Server.
 * 
 * Hermes FTP Server 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
 * (at your option) any later version.
 * 
 * Hermes FTP Server 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 Hermes FTP Server; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * ------------------------------------------------------------------------------
 */

package com.apporiented.hermesftp.utils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import com.apporiented.hermesftp.exception.FtpConfigException;

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

/**
 * Security related utility methods.
 * 
 * @author Lars Behnke
 */
public final class SecurityUtil {

    private static final String ALG_END = "}";

    private static final String ALG_START = "{";

    /**
     * Constructor hidden.
     */
    private SecurityUtil() {
        super();
    }

    /**
     * Calculates based on the passed parameters an hash code and returns its BASE64 representation. The
     * used algorithm is prepended.
     * 
     * @param password The password to encode.
     * @param algorithm The algorithm to use (MD5 e.g.)
     * @return The encoded password as string.
     * @throws NoSuchAlgorithmException Passed algorithm is not supported.
     */
    public static String digestPassword(String password, String algorithm) throws NoSuchAlgorithmException {
        if (password == null) {
            throw new IllegalArgumentException("No password passed");
        }
        String result = password.trim();
        if (algorithm == null) {
            return result;
        }
        MessageDigest digest = MessageDigest.getInstance(algorithm);
        digest.update(password.getBytes());
        byte[] digestedPassword = digest.digest();
        String base64password = new String(Base64.encodeBase64(digestedPassword));
        return ALG_START + algorithm + ALG_END + base64password;
    }

    /**
     * Checks the validity of the password password based on a given hash code. The hash code to check
     * against contains the used algorithm has prefix. Example: {MD5}Cwz8B/yoHJVquRgdhXb0qA==.
     * 
     * @param passwordHash The hash code to check against.
     * @param password The password to check.
     * @return True, if password is valid.
     * @throws NoSuchAlgorithmException Algorithm (from hash prefix) is not supported.
     */
    public static boolean checkPassword(String passwordHash, String password) throws NoSuchAlgorithmException {
        if (passwordHash == null || password == null) {
            return false;
        }
        String algorithm;
        int startIdx = passwordHash.indexOf(ALG_START);
        int endIdx = passwordHash.indexOf(ALG_END);
        if (startIdx == 0 && endIdx > startIdx) {
            algorithm = passwordHash.substring(startIdx + 1, endIdx);
            String hashStr = digestPassword(password.trim(), algorithm);
            return passwordHash.equals(hashStr);
        } else {
            return passwordHash.trim().equals(password.trim());
        }
    }

    /**
     * Create the security context required for SSL communication.
     * 
     * @param keyStoreFile The name of the keystore file.
     * @param keyStorePassword The password for the keystore.
     * @return The context.
     * @throws FtpConfigException Thrown on error in configuration.
     */
    public static SSLContext createSslContext(String keyStoreFile, char[] keyStorePassword)
            throws FtpConfigException {
        SSLContext sslContext;
        try {
            /* Get keystore file and password */
            InputStream ksInputStream = getKeyStoreInputStream(keyStoreFile);

            /*
             * Get the java keystore object an key manager. A keystore is where keys and
             * certificates are kept.
             */
            KeyStore keystore = KeyStore.getInstance("JKS");
            keystore.load(ksInputStream, keyStorePassword);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keystore, keyStorePassword);

            /*
             * An SSLContext is an environment for implementing JSSE. It is used to create a
             * ServerSocketFactory
             */
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(kmf.getKeyManagers(), null, null);
        } catch (KeyManagementException e) {

            throw new SecurityException("A key management authorization problem occurred.");
        } catch (FileNotFoundException e) {
            throw new SecurityException("The key store file could not be found.");
        } catch (KeyStoreException e) {
            throw new SecurityException("A key store problem occurred.");
        } catch (NoSuchAlgorithmException e) {
            throw new SecurityException("The hash algorithm is not supported.");
        } catch (CertificateException e) {
            throw new SecurityException("Certificate could not be loaded.");
        } catch (UnrecoverableKeyException e) {
            throw new SecurityException("Key store cannot be recovered.");
        } catch (IOException e) {
            throw new SecurityException("Reading the key store failed.");
        }
        return sslContext;
    }

    private static InputStream getKeyStoreInputStream(String ksFile) throws FileNotFoundException {
        if (ksFile == null) {
            throw new FileNotFoundException("Keystore file not defined.");
        }
        return new FileInputStream(ksFile);

    }

}