com.projectsontracks.model.CaribooKey.java Source code

Java tutorial

Introduction

Here is the source code for com.projectsontracks.model.CaribooKey.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.projectsontracks.model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.commons.lang3.StringUtils;

/**
 *
 * @author lionel
 */
public class CaribooKey {

    private static final String KEY_FILE_EXTENSION = "txt";
    public static final int AES_DEFAULT_SIZE = 256;

    public final Cipher aesCipher;
    private int size;
    private byte[] key;
    private SecretKeySpec keySpec;

    public CaribooKey() throws NoSuchAlgorithmException, NoSuchPaddingException {
        // create AES shared key cipher
        this.aesCipher = Cipher.getInstance("AES");
        this.size = AES_DEFAULT_SIZE;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public byte[] getKey() {
        return key;
    }

    public void setKey(byte[] key) {
        this.key = key;
    }

    public SecretKeySpec getKeySpec() {
        return keySpec;
    }

    public void setKeySpec(SecretKeySpec keySpec) {
        this.keySpec = keySpec;
    }

    /**
     * Creates a new AES key
     *
     * @throws java.security.NoSuchAlgorithmException
     */
    public void createKey() throws NoSuchAlgorithmException {
        // Initialize the key generator
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(this.size);
        // Generates the key
        SecretKey skey = kgen.generateKey();
        // Returns the key in its primary encoding format, or null if this key does not support encoding.
        key = skey.getEncoded();
        //used to construct a SecretKey from a byte array, without having to go through a (provider-based) SecretKeyFactory.
        keySpec = new SecretKeySpec(key, "AES");
    }//createKey

    /**
     * Creates a new AES key but one that is user friendly
     *
     * @throws java.security.NoSuchAlgorithmException
     */
    public void createUserFriendlyKey() throws NoSuchAlgorithmException {
        // Initialize the key generator
        String id = UUID.randomUUID().toString().toUpperCase().substring(0, 32);
        key = id.getBytes();
        //used to construct a SecretKey from a byte array, without having to go through a (provider-based) SecretKeyFactory.
        keySpec = new SecretKeySpec(key, "AES");
    }//createKey

    /**
     * Open an AES key stored in an encrypted and password protected ZIP file
     * Then store the key in local variable byte[] key
     *
     * @param inputFileName
     * @param password
     * @throws java.security.GeneralSecurityException
     * @throws java.io.FileNotFoundException
     * @throws net.lingala.zip4j.exception.ZipException
     * @throws com.projectsontracks.model.CaribooException
     */
    public void loadKey(String inputFileName, String password)
            throws GeneralSecurityException, FileNotFoundException, IOException, ZipException, CaribooException {
        // read private key to be used to decrypt the AES key

        // Name of the file inside the ZIP
        String keyFileName = StringUtils.substringBeforeLast(inputFileName, ".") + "." + KEY_FILE_EXTENSION;
        keyFileName = StringUtils.substringAfterLast(keyFileName, "\\");

        // Initiate ZipFile object with the path/name of the zip file.
        ZipFile zipFile = new ZipFile(inputFileName);
        //System.out.println("ZIP Key file: " + inputFileName);
        //System.out.println("Key file: " + keyFileName);
        ZipParameters parameters = new ZipParameters();
        //parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to store compression
        //parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        if (zipFile.isEncrypted()) {
            zipFile.setPassword(password);
        }
        //parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
        //parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);

        //Get a list of FileHeader. FileHeader is the header information for all the files in the ZipFile
        List fileHeaderList = zipFile.getFileHeaders();
        // Loop through all the fileHeaders
        for (int i = 0; i < fileHeaderList.size(); i++) {
            FileHeader fileHeader = (FileHeader) fileHeaderList.get(i);
            if (fileHeader != null) {
                String fileName = fileHeader.getFileName();
                //System.out.println("  Zip contains : " + fileName);
                if (keyFileName != null && keyFileName.equalsIgnoreCase(fileName)) {
                    //Get the InputStream from the ZipFile
                    ZipInputStream is = zipFile.getInputStream(fileHeader);
                    File file = new File(fileName);
                    // read the InputStream
                    int readLen = -1;
                    byte[] buff = new byte[32];
                    while ((readLen = is.read(buff)) != -1) {
                    }
                    // Assign to local variable
                    this.key = buff;
                    keySpec = new SecretKeySpec(this.key, "AES");
                    //System.out.println("Key: " + new String(this.key));
                } else {
                    throw new CaribooException(fileName + " does not match " + keyFileName);
                }
            }
        } //for
    }//loadKey

    /**
     * Encrypts the AES key into a password protected ZIP file
     *
     * @param outputFile
     * @param password
     * @throws java.io.IOException
     * @throws java.security.GeneralSecurityException
     * @throws net.lingala.zip4j.exception.ZipException
     * @throws com.projectsontracks.model.CaribooException
     */
    public void saveKey(String outputFile, String password)
            throws IOException, GeneralSecurityException, ZipException, CaribooException {

        // write AES key
        String tmpFileName = StringUtils.substringBeforeLast(outputFile, ".") + "." + KEY_FILE_EXTENSION;
        FileOutputStream os = new FileOutputStream(tmpFileName);
        os.write(key);
        os.close();

        // Initiate ZipFile object with the path/name of the zip file.
        ZipFile zipFile = new ZipFile(outputFile);

        // Initiate Zip Parameters which define various properties such
        // as compression method, etc. More parameters are explained in other
        // examples
        ZipParameters parameters = new ZipParameters();
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to store compression

        // Set the compression level. This value has to be in between 0 to 9
        // Several predefined compression levels are available
        // DEFLATE_LEVEL_FASTEST - Lowest compression level but higher speed of compression
        // DEFLATE_LEVEL_FAST - Low compression level but higher speed of compression
        // DEFLATE_LEVEL_NORMAL - Optimal balance between compression level/speed
        // DEFLATE_LEVEL_MAXIMUM - High compression level with a compromise of speed
        // DEFLATE_LEVEL_ULTRA - Highest compression level but low speed
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);

        // Set the encryption flag to true
        // If this is set to false, then the rest of encryption properties are ignored
        parameters.setEncryptFiles(true);

        // Set the encryption method to AES Zip Encryption
        parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);

        // Set AES Key strength. Key strengths available for AES encryption are:
        // AES_STRENGTH_128 - For both encryption and decryption
        // AES_STRENGTH_192 - For decryption only
        // AES_STRENGTH_256 - For both encryption and decryption
        // Key strength 192 cannot be used for encryption. But if a zip file already has a
        // file encrypted with key strength of 192, then Zip4j can decrypt this file
        parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);

        // Set password
        parameters.setPassword(password);

        // Now add files to the zip file
        // Note: To add a single file, the method addFile can be used
        // Note: If the zip file already exists and if this zip file is a split file
        // then this method throws an exception as Zip Format Specification does not
        // allow updating split zip files
        zipFile.addFile(new File(tmpFileName), parameters);

        // delete the key file
        FileUtils.deleteTempFile(tmpFileName);
    }//saveKey
}