com.ccstats.crypto.io.JSONEncryptedStatement.java Source code

Java tutorial

Introduction

Here is the source code for com.ccstats.crypto.io.JSONEncryptedStatement.java

Source

/**
 * Copyright (c) 2016 Ahmed Sakr
 *
 * 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 com.ccstats.crypto.io;

import com.ccstats.analysis.TransactionPool;
import com.ccstats.crypto.AESWorker;
import com.ccstats.data.Statement;
import com.ccstats.data.Transaction;
import org.apache.commons.codec.DecoderException;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import javax.crypto.Cipher;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.time.LocalDate;

/**
 *
 * @author Ahmed Sakr
 * @since January 2, 2016.
 */
public class JSONEncryptedStatement {

    private Statement statement;
    private AESWorker worker;

    /**
     * Default constructor that requires no parameters for the construction of the object, usually useful when
     * the object is being constructed for reading purposes.
     */
    public JSONEncryptedStatement() {
        worker = new AESWorker();
    }

    /**
     * Constructor that takes a plain serialized statement as a parameter, usually useful when the
     * object is being constructed for writing purposes.
     *
     * @param statement The Serialized statement object.
     */
    public JSONEncryptedStatement(Statement statement) {
        this();
        this.statement = statement;
    }

    /**
     * Overrides the private statement attribute.
     *
     * @param statement The new statement.
     */
    public void setStatement(Statement statement) {
        this.statement = statement;
    }

    /**
     * Encrypts and writes all the data from the plain serialized statement to a .json file.
     *
     * @param absolutePath The absolute path of the .json output file. (including the file name)
     * @param password     The plaintext password to be used for encrypting the data.
     */
    public void write(String absolutePath, String password) throws IOException {

        if (statement == null) {
            return;
        }

        JSONObject main = new JSONObject();
        JSONObject transactions = new JSONObject();

        try {
            String date, description, amount, authorized;
            JSONObject transactionObj;
            Transaction transaction;

            if (!statement.isEmpty()) {
                for (int i = 0; i < statement.size(); i++) {
                    transaction = statement.get(i);
                    transactionObj = new JSONObject();

                    date = new String(worker.encrypt(password, transaction.getDate().toString()));
                    description = new String(worker.encrypt(password, transaction.getDescription()));
                    amount = new String(worker.encrypt(password, String.valueOf(transaction.getAmount())));
                    authorized = new String(worker.encrypt(password, String.valueOf(transaction.isAuthorized())));

                    transactionObj.put("date", date);
                    transactionObj.put("description", description);
                    transactionObj.put("amount", amount);
                    transactionObj.put("authorized", authorized);

                    transactions.put(String.format("transaction-%d", i + 1), transactionObj);
                }
            }
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException
                | InvalidParameterSpecException | InvalidKeySpecException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }

        main.put("aes-key-length", String.valueOf(worker.getKeyLength()));
        main.put("transactions", transactions);
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(absolutePath, false))) {
            writer.write(main.toJSONString());
        }
    }

    /**
     * An override of the original write method with a char array password instead of a String object.
     *
     * @param absolutePath The absolute path of the .json output file. (including the file name)
     * @param password     The plaintext password to be used for encrypting the data.
     */
    public void write(String absolutePath, char[] password) throws IOException {
        write(absolutePath, new String(password));
    }

    /**
     * An override of the original write method with the option to provide the filename and the absolute parent path
     * as different parameters as needed.
     *
     * @param filename           The .json file name.
     * @param absoluteParentPath The absolute path of the parent folder that will hold the .json file.
     * @param password           The plaintext password to be used for encrypting the data.
     */
    public void write(String filename, String absoluteParentPath, char[] password) throws IOException {
        write(absoluteParentPath + "\\" + filename, password);
    }

    /**
     * An override of the original write method with the option to provide the filename and the absolute parent path
     * as different parameters as needed. The password is also a String object instead of the accustomed char
     * array.
     *
     * @param filename           The .json file name.
     * @param absoluteParentPath The absolute path of the parent folder that will hold the .json file.
     * @param password           The plaintext password to be used for encrypting the data.
     */
    public void write(String filename, String absoluteParentPath, String password) throws IOException {
        write(absoluteParentPath + "\\" + filename, password);
    }

    /**
     * Reads an encrypted .json statement file and attempts to decrypt it. Once decrypted, the transactions can be
     * pooled and returned as a joint statement.
     *
     * @param absolutePath The absolute path to the encrypted statement, including the file name.
     * @param password The password sequence to be used while attempting the decryption.
     *
     * @return A statement object containing all the discovered transactions as a pool.
     */
    public Statement read(String absolutePath, String password)
            throws IOException, ParseException, BadPaddingException {
        TransactionPool transactions = new TransactionPool();
        JSONParser parser = new JSONParser();

        JSONObject main = (JSONObject) parser.parse(new FileReader(absolutePath));
        JSONObject encryptedTransactions = (JSONObject) main.get("transactions");

        worker.setKeyLength(Integer.valueOf((String) main.get("aes-key-length")));
        try {

            JSONObject current;
            String date, description, amount, authorized;
            for (Object o : encryptedTransactions.values()) {
                current = (JSONObject) o;
                date = new String(worker.decrypt(password, (String) current.get("date")));
                description = new String(worker.decrypt(password, (String) current.get("description")));
                amount = new String(worker.decrypt(password, (String) current.get("amount")));
                authorized = new String(worker.decrypt(password, (String) current.get("authorized")));

                transactions.add(new Transaction(description, LocalDate.parse(date), Double.valueOf(amount),
                        Boolean.valueOf(authorized)));
            }

        } catch (InvalidKeySpecException | NoSuchAlgorithmException | DecoderException | InvalidKeyException
                | InvalidAlgorithmParameterException | IllegalBlockSizeException | NoSuchPaddingException e) {
            e.printStackTrace();
        }

        return new Statement(transactions);
    }

    /**
     * An override to the write method with the minor change of allowing the password to be given as a char
     * array.
     *
     * @param absolutePath The absolute path to the encrypted statement, including the file name.
     * @param password The password sequence to be used while attempting the decryption.
     *
     * @return A statement object containing all the discovered transactions as a pool.
     */
    public Statement read(String absolutePath, char[] password)
            throws ParseException, BadPaddingException, IOException {
        return read(absolutePath, new String(password));
    }

    /**
     * An override to the write method with the following changes: allowing the filename and absolute parent path
     * to be input separately, and the password as a char array.
     *
     * @param fileName the alias of the encrypted statement.
     * @param absoluteParentPath The absolute path to the encrypted statement's parent folder.
     * @param password The password sequence to be used while attempting the decryption.
     *
     * @return A statement object containing all the discovered transactions as a pool.
     */
    public Statement read(String fileName, String absoluteParentPath, char[] password)
            throws ParseException, BadPaddingException, IOException {
        return read(absoluteParentPath + "\\" + fileName, password);
    }

    /**
     * An override to the write method with the minor change of allowing the password to be a String object.
     *
     * @param fileName the alias of the encrypted statement.
     * @param absoluteParentPath The absolute path to the encrypted statement's parent folder.
     * @param password The password sequence to be used while attempting the decryption.
     *
     * @return A statement object containing all the discovered transactions as a pool.
     */
    public Statement read(String fileName, String absoluteParentPath, String password)
            throws ParseException, BadPaddingException, IOException {
        return read(absoluteParentPath + "\\" + fileName, password);
    }
}