de.inpiraten.jdemocrator.TAN.generator.TANGenerator.java Source code

Java tutorial

Introduction

Here is the source code for de.inpiraten.jdemocrator.TAN.generator.TANGenerator.java

Source

package de.inpiraten.jdemocrator.TAN.generator;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;

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

import de.inpiraten.jdemocrator.TAN.TAN;
import de.inpiraten.jdemocrator.TAN.TANAuthority;
import de.inpiraten.jdemocrator.event.Event;
import de.inpiraten.jdemocrator.event.IllegalEntryException;
import de.inpiraten.jdemocrator.license.GPL;

/**
 * A class with a static main function to provide a command line interface for creating TANs
 * @author Andi Popp
 *
 */
public class TANGenerator {

    BufferedReader commandLineInput;
    Event event;
    TANAuthority tanAuthority;
    String[] masterTAN;

    /**
     * Creates a TANGenerator instance from a command line
     * @param commandLineInput
     * @throws IOException 
     */
    public TANGenerator(BufferedReader commandLineInput) throws IOException {
        this.commandLineInput = commandLineInput;

        //Get the event
        System.out.print("\nEnter the location of the event config file.\n> ");
        String configFileLocation = commandLineInput.readLine();

        try {
            this.event = new Event(configFileLocation);
        } catch (IOException e) {
            System.out.println("Config file could not be opened. Exiting.");
            System.exit(2);
        } catch (IllegalEntryException e) {
            System.out.println("Error in config file. Error message: " + e.getMessage());
            System.out.println("Exiting");
            System.exit(3);
        }

        //Get the Authority
        while (this.tanAuthority == null) {
            System.out.println("\nChoose the TAN Authority to generate TANs for");
            for (int i = 0; i < this.event.eventTANAuthority.length; i++) {
                System.out.println("(" + (i + 1) + ") " + this.event.eventTANAuthority[i].name + " ["
                        + this.event.eventTANAuthority[i].announceServerAddress + "]");
            }
            System.out.print("> ");
            try {
                byte choice = inputOption();
                this.tanAuthority = this.event.eventTANAuthority[choice - 1];
            } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
                System.out.println("Invalid input. Please try again.");
            }
        }

    }

    public static void main(String[] args) {

        //Intro message
        GPL.printLicenseNotice();
        System.out.println("\njDemocrator Authority TAN Generator");
        System.out.println("===================================\n");

        System.out.println("This programm will generate voting TANs for a semi-online secrete voting.");

        try {
            //Initialize TAN Generator
            TANGenerator G = new TANGenerator(new BufferedReader(new InputStreamReader(System.in)));

            //Randomly generate master TANs
            G.generateMasterTANs();

            //Generate TANs from master TANs
            TAN[][] tans = new TAN[G.event.numberOfElections][];
            for (int i = 0; i < tans.length; i++) {
                try {
                    tans[i] = G.event.TANType.generateFromMasterTAN(G.masterTAN[i], G.event,
                            G.event.numberOfVoters);
                } catch (NoSuchAlgorithmException e) {
                    System.out.println("The Key Derivation function described as " + G.event.keyDerivationFunction
                            + " is not supported. Exiting.");
                    System.exit(2);
                } catch (InvalidKeySpecException e) {
                    System.out.println("Invalied Key Spec Exception while generating TANs. Exiting.");
                    System.exit(3);
                }
            }

            //Mix up the TANs
            for (int i = 0; i < tans.length; i++) {
                shuffle(tans[i]);
            }

            //TODO Write the TANs and master TANs to (printable) files
        } catch (IOException e) {
            System.out.println("An I/O Error occured");
            System.exit(1);
        }

    }

    public void generateMasterTANs() throws IOException {
        //Read seed from System.in
        System.out.println("You will be asked to specify a random seed. Please enter a number of random");
        System.out.println("characters to your liking. This will help to seed a secure random number");
        System.out.println("generator which will generate the master TANs for every vote and derive the");
        System.out.println("TANs. The longer your seed the stronger your master TANs.");
        System.out.print("\nEnter the seed for the TAN generator.\n> ");
        String seed = commandLineInput.readLine();
        SecureRandom random = new SecureRandom(
                ArrayUtils.addAll(seed.getBytes(), ("" + System.currentTimeMillis()).getBytes()));

        //Get length of master TANs
        int masterTANlength = -1;
        while (masterTANlength < 6) {
            System.out.print("\nPlease enter the length of the master TANs in bytes. (Standard: 18)\n>");
            int input;
            try {
                input = inputInteger();
                if (input > 5) {
                    masterTANlength = input;
                } else if (input > 0) {
                    System.out
                            .println("Lengths shorter than 6 byte are too insecure. Please chose another length.");
                } else if (input == 0) {
                    masterTANlength = 18; //standard option
                } else
                    throw new NumberFormatException("Length of master TAN must be positive");
            } catch (NumberFormatException e) {
                System.out.println("Invalid input. Please try again.");
            }
        }

        this.masterTAN = new String[this.event.numberOfElections];
        byte[] rawTAN = new byte[masterTANlength];
        for (int i = 0; i < this.masterTAN.length; i++) {
            random.nextBytes(rawTAN);
            this.masterTAN[i] = Base64.encodeBase64String(rawTAN);
        }
    }

    private byte inputOption() throws NumberFormatException, IOException {
        String inputString = commandLineInput.readLine();
        //      System.out.println("DEBUG: Read the following line: "+inputString);
        if (inputString.equals(""))
            return 0;
        else
            return Byte.parseByte(inputString);
    }

    private int inputInteger() throws NumberFormatException, IOException {
        String inputString = commandLineInput.readLine();
        //      System.out.println("DEBUG: Read the following line: "+inputString);
        if (inputString.equals(""))
            return 0;
        else
            return Integer.parseInt(inputString);
    }

    private static void shuffle(TAN[] array) {
        Random r = new Random();
        for (int i = array.length - 1; i >= 0; i--) {
            int j = r.nextInt(i + 1);
            TAN h = array[j];
            array[j] = array[i];
            array[i] = h;
        }
    }
}