com.ibm.dbwkl.helper.CryptionModule.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.dbwkl.helper.CryptionModule.java

Source

/*******************************************************************************
 * Copyright (c) 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.ibm.dbwkl.helper;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import com.ibm.dbwkl.DB2WorkloadServiceDirectory;

import org.apache.commons.codec.binary.Base64;
import com.ibm.staf.STAFResult;

/**
 * This class uses public and private RSA encrypted BASE64 encoded security keys
 * to encrypt and decrypt incoming passwords or messages
 * 
 */
public class CryptionModule {

    /**
     * CryptionModule Instance
     */
    private static CryptionModule cryptionModule;

    /**
     * Cipher Instance for crypting
     */
    private Cipher cipher;

    /**
     * Base64 encoded Private Key
     */
    private final static String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJQsTlFtMJUa3V6KVNypLnINBLH9bKLIu8bC9+BEuvZsn3JUoiKTc4TM6YfK6osKvurn3JJUixS5dxNfc+61slM0KWCIChcuBydh4kxUUqbWAFvy5EP1RhZ/XGoU93Kb+LI30QhWcXxVNUCmwe8q8DYxmUYyNDDMqW2ruQGnFZvlAgMBAAECgYAyf1MFnx/CgRBWivBW73V7uwIRotumMqEEISgXD3VkTCqe7UcAX54r8SXZeIcscbIVHoXmfNeVbYuuV4aMIPIvsFJt+X8l+WKkW14ZxzzTzF1us2gBCzQWrK3y3c+1wiYpWrOUIPCaP5+x1xA05TAxboW2zl82qtj24BVEz7UdgQJBAOcNeTGJLAsjZR3hj6IOia+K7r1kdyQRKBzZ57okB1QRWiK/aIBpQe0fVMHTCatWXy8v5qLsQHRyuULpXnxwBsUCQQCkK/VSeqS7SmQbSQOD34NRnB747URQ3fuu5VC9QOJtoCA96Hpz/Z+xM4iUjQNOXxFmNUaGrEZ31GNoeh8yAZKhAkA7wfpUW3vurYrbfZkeetAVfMNebHt78owDWkBanjLfBVXgosyuWYrZfz72mlRn4gDgPW1TOfM5qupLafwsBvVZAkAlVbncn/eGgExzyA78loAOtyp0AcFfgpwSEiRiZbcYpymt6oiuiCcg7U9KOSdfU09ppwP67IK6DZrtz5f4j1MBAkEA2wlNtN5qRU8+6o0dkinnfvj0wkndAnIjsTN7DBOVIsV9Eu5K5naYs+C155i2RXNPF7DGOIKcIMfydSJNdsSKxA==";

    /**
     * Base64 encoded Public Key
     */
    private final static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCULE5RbTCVGt1eilTcqS5yDQSx/WyiyLvGwvfgRLr2bJ9yVKIik3OEzOmHyuqLCr7q59ySVIsUuXcTX3PutbJTNClgiAoXLgcnYeJMVFKm1gBb8uRD9UYWf1xqFPdym/iyN9EIVnF8VTVApsHvKvA2MZlGMjQwzKltq7kBpxWb5QIDAQAB";

    /**
     * SecurityPrefix for encrypted messages
     */
    public static final String SECURITY_PREFIX = "secured:";

    /**
     * SecurityPrefix for encrypted messages
     */
    public static final String PASSFILE_PREFIX = "file:";

    /**
     * Default path to the password file
     */
    private String passpath = DB2WorkloadServiceDirectory.getDB2WorkloadServiceDirectory() + "/pass";

    /**
     * Default private constructor for singelton Instance
     * @throws NoSuchPaddingException 
     * @throws NoSuchAlgorithmException 
     */
    private CryptionModule() throws NoSuchAlgorithmException, NoSuchPaddingException {
        this.cipher = Cipher.getInstance("RSA");
    }

    /**
     * Returns a singelton instance of CryptionModule
     * 
     * @return cryptionModule as singelton instance
     * @throws NoSuchPaddingException 
     * @throws NoSuchAlgorithmException 
     */
    public static CryptionModule getInstance() throws NoSuchAlgorithmException, NoSuchPaddingException {
        if (cryptionModule == null) {
            cryptionModule = new CryptionModule();
        }
        return cryptionModule;
    }

    /**
     * @param plaintextedPassword
     * @return encrpytedPassword
     * @throws IOException 
     * @throws InvalidKeySpecException 
     * @throws NoSuchAlgorithmException 
     * @throws InvalidKeyException 
     * @throws BadPaddingException 
     * @throws IllegalBlockSizeException 
     */
    public STAFResult getEncryptedPassword(String plaintextedPassword)
            throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException {
        String encryptedPassword = null;

        RSAPublicKey publicKey = getPublicKey();

        this.cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] raw = plaintextedPassword.getBytes();

        // encrypt the message
        byte[] passBytes = this.cipher.doFinal(raw);

        // encode the encrypted message as base64
        encryptedPassword = Base64.encodeBase64String(passBytes);

        //omits CRLF
        encryptedPassword = encryptedPassword.replace("\r\n", "");

        return new STAFResult(STAFResult.Ok, encryptedPassword);
    }

    /**
     * @return PublicKey Instance
     * @throws NoSuchAlgorithmException
     * @throws IOException
     * @throws InvalidKeySpecException
     */
    private RSAPublicKey getPublicKey() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        KeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(PUBLIC_KEY));
        RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);

        return publicKey;
    }

    /**
     * @param encryptedPass
     * @return decryptedPassword
     * @throws IOException 
     * @throws InvalidKeySpecException 
     * @throws NoSuchAlgorithmException 
     * @throws InvalidKeyException 
     * @throws BadPaddingException 
     * @throws IllegalBlockSizeException 
     * @throws IllegalArgumentException 
     */
    public String getDecryptedPassword(String encryptedPass)
            throws IOException, InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException,
            IllegalBlockSizeException, BadPaddingException, IllegalArgumentException {
        String encryptedPassword = encryptedPass;
        String decryptedPassword = null;
        byte[] passbytes;

        if (encryptedPassword.startsWith(SECURITY_PREFIX)) {
            encryptedPassword = encryptedPassword.replace(SECURITY_PREFIX, "");
        } else if (encryptedPassword.startsWith(PASSFILE_PREFIX)) {
            encryptedPassword = encryptedPassword.replace(PASSFILE_PREFIX, "");
            encryptedPassword = readPassfile(encryptedPassword);
        } else {
            throw new IllegalArgumentException("The encrpted password is not of valid form. It must start with "
                    + SECURITY_PREFIX + " or " + PASSFILE_PREFIX);
        }
        passbytes = Base64.decodeBase64(encryptedPassword);

        this.cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
        // decode the message
        byte[] decryptedBytes = this.cipher.doFinal(passbytes);

        decryptedPassword = new String(decryptedBytes, "UTF8");

        return decryptedPassword;
    }

    /**
     * @return PrivateKey Instance
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private RSAPrivateKey getPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] privateKeyBytes = null;
        RSAPrivateKey privateKey = null;

        privateKeyBytes = getPrivateKeyBytes();
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);

        return privateKey;
    }

    /**
     * @return PrivateKeyBytes of the privateKeyFile
     * @throws IOException
     */
    private byte[] getPrivateKeyBytes() throws IOException {
        byte[] privateKeyBytes = Base64.decodeBase64(PRIVATE_KEY);

        return privateKeyBytes;
    }

    /**
     * @param path
     * @return byte Array with the encrypted password
     * @throws IOException
     */
    public String readPassfile(String path) throws IOException {
        String encryptedPassword;
        byte[] passbytes;

        if (path != null) {
            if (path.length() != 0) {
                this.passpath = path;
            }
        }

        File passfile = new File(this.passpath);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(passfile));
        passbytes = new byte[(int) passfile.length()];
        bis.read(passbytes);
        bis.close();

        encryptedPassword = new String(passbytes, "UTF8");

        return encryptedPassword;
    }

    /**
     * @param result
     *            as encryptedPassword
     * @param path
     * @return STAFResult
     */
    public STAFResult writePassfile(String result, String path) {
        byte[] passbytes;

        if (path != null) {
            if (path.length() != 0) {
                this.passpath = path;
            }
        }

        try {
            File passfile = new File(this.passpath);
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(passfile));
            passbytes = result.getBytes();
            bos.write(passbytes);
            bos.close();
        } catch (IOException e) {
            return new STAFResult(STAFResult.InvalidRequestString, "Error while wrting to path");
        }

        return new STAFResult(STAFResult.Ok, "Encrypted Password saved in " + this.passpath);
    }
}