org.opentravel.schemacompiler.security.PasswordHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.opentravel.schemacompiler.security.PasswordHelper.java

Source

/**
 * Copyright (C) 2014 OpenTravel Alliance (info@opentravel.org)
 *
 * 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 org.opentravel.schemacompiler.security;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;
import org.opentravel.schemacompiler.ioc.CompilerExtensionRegistry;

/**
 * Provides static utility methods for encrypting and testing passwords using a
 * Unix/Linux-compatible encryption algorithm.
 * 
 * @author S. Livezey
 */
public class PasswordHelper {

    protected static final String PUBLIC_KEYFILE = "/org/opentravel/schemacompiler/ota2-repository.pub";
    protected static final String PRIVATE_KEYFILE = "/org/opentravel/schemacompiler/ota2-repository.pri";
    protected static final String ENCRYPTION_ALGORITHM = "RSA";
    protected static final String CIPHER_TRANSFORMATION = ENCRYPTION_ALGORITHM + "/ECB/NoPadding";

    private static Cipher encryptionCipher;
    private static Cipher decryptionCipher;

    /**
     * Private constructor to prevent instantiation.
     */
    private PasswordHelper() {
    }

    /**
     * Encrypts the given plain-text password.
     * 
     * @param original
     *            the plain-text password to encrypt
     * @return String
     */
    public static synchronized final String encrypt(String original) {
        try {
            return Base64.encodeBase64String(encryptionCipher.doFinal(original.getBytes()));

        } catch (GeneralSecurityException e) {
            throw new IllegalArgumentException("Unable to encrypt password.", e);
        }
    }

    /**
     * Decrypts the given encrypted password.
     * 
     * @param encryptedPassword
     *            the encrypted password to decrypt
     * @return String
     */
    public static synchronized final String decrypt(String encryptedPassword) {
        try {
            return new String(decryptionCipher.doFinal(Base64.decodeBase64(encryptedPassword))).trim();

        } catch (GeneralSecurityException e) {
            throw new IllegalArgumentException("Unable to decrypt password.", e);
        }
    }

    /**
     * Returns true if the plain-text test password matches the encrypted one provided.
     * 
     * @param testPassword
     *            the plain-text password to test against the encrypted one
     * @param encryptedPassword
     *            the encrypted password to test
     * @return boolean
     */
    public static boolean isMatch(String testPassword, String encryptedPassword) {
        boolean result = false;

        if ((testPassword != null) && (encryptedPassword != null)) {
            result = testPassword.equals(decrypt(encryptedPassword));
        }
        return result;
    }

    /**
     * Returns an encryption cipher that is based on the public encryption key file located on the
     * application's classpath.
     * 
     * @return Cipher
     * @throws GeneralSecurityException
     *             thrown if encryption key is not valid
     * @throws IOException
     *             thrown if the contents of the public key file cannot be loaded
     */
    private static Cipher loadEncryptionCipher() throws GeneralSecurityException, IOException {
        BigInteger[] keyComponents = loadKeyFile(PUBLIC_KEYFILE);
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(keyComponents[0], keyComponents[1]);
        KeyFactory factory = KeyFactory.getInstance(ENCRYPTION_ALGORITHM);
        PublicKey publicKey = factory.generatePublic(keySpec);
        Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);

        cipher.init(Cipher.PUBLIC_KEY, publicKey);
        return cipher;
    }

    /**
     * Returns an decryption cipher that is based on the private encryption key file located on the
     * application's classpath.
     * 
     * @return Cipher
     * @throws GeneralSecurityException
     *             thrown if encryption key is not valid
     * @throws IOException
     *             thrown if the contents of the private key file cannot be loaded
     */
    private static Cipher loadDecryptionCipher() throws GeneralSecurityException, IOException {
        BigInteger[] keyComponents = loadKeyFile(PRIVATE_KEYFILE);
        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(keyComponents[0], keyComponents[1]);
        KeyFactory factory = KeyFactory.getInstance(ENCRYPTION_ALGORITHM);
        PrivateKey privateKey = factory.generatePrivate(keySpec);
        Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);

        cipher.init(Cipher.PRIVATE_KEY, privateKey);
        return cipher;
    }

    /**
     * Loads the contents of the key file from the specified location on the classpath.
     * 
     * @param fileLocation
     *            the classpath location of the file to load
     * @return BigInteger[] (modulus, exponent)
     * @throws IOException
     */
    private static BigInteger[] loadKeyFile(String fileLocation) throws IOException {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(
                    new InputStreamReader(CompilerExtensionRegistry.loadResource(fileLocation)));
            String modBase64 = reader.readLine();
            String expBase64 = reader.readLine();
            BigInteger modulus = new BigInteger(Base64.decodeBase64(modBase64));
            BigInteger exponent = new BigInteger(Base64.decodeBase64(expBase64));

            return new BigInteger[] { modulus, exponent };

        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (Throwable t) {
            }
        }
    }

    /**
     * Initializes the public and private keys used by the encryption algorithm.
     */
    static {
        try {
            encryptionCipher = loadEncryptionCipher();
            decryptionCipher = loadDecryptionCipher();

        } catch (Throwable t) {
            throw new ExceptionInInitializerError(t);
        }
    }

}