All pastes #1796181 Raw Edit

Entropi (0.0.2)

public text v1 · immutable
#1796181 ·published 2010-02-14 12:45 UTC
rendered paste body
package entropi;

import java.io.*;
import java.security.*;

/**
 * Entropi is a "randomness and cryptography toolkit".
 *
 * @author gizmoguy
 * @version 0.0.2
 */
public class Main {

    /**
     * Determines what the user wants to do based upon the
     * specified command line arguments, and executes the appropriate method.
     *
     * @param args The command line arguments
     */
    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            printError();
        } else if (args[0].equals("xor_random") & args.length == 3) {
            xorRandom(args[1], args[2]);
        } else if (args[0].equals("xor") & args.length == 4) {
            xor(args[1], args[2], args[3]);
        } else if (args[0].equals("generate_random") & args.length == 3) {
            generateRandom(args[1], args[2]);
        } else if (args[0].equals("help") & args.length == 1){
            printHelp();
        } else {
            printError();
        }
    }

    /**
     * Takes an input file and XORs it with random bytes, creating 2 output
     * files. Essentially, a one-time pad cipher.
     *
     * @param inputFilename             The input file to be encrypted.
     * @param outputFilenameTemplate    The template for the names of the output
     *                                  files. The output filenames are equal to
     *                                  "<code>outputFilenameTemplate</code>.1"
     *                                  and
     *                                  "<code>outputFilenameTemplate</code>.2".
     * @return                          0 (success) or 1 (failure).
     * @throws Exception                An exception.
     */
    public static int xorRandom(String inputFilename, String outputFilenameTemplate) throws Exception {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

        File inputFile = new File(inputFilename);
        InputStream inputFileStream = null;
        long inputFileLength = 0;

        if (inputFile.exists() & inputFile.canRead() & inputFile.isFile()) {
            inputFileStream = new FileInputStream(inputFile);
            inputFileLength = inputFile.length();
        } else {
            if (inputFile.exists() == false) {
                System.out.println(inputFile.getAbsolutePath() + " does not exist.");

                System.out.println("Aborting...");

                return 1;
            }

            if (inputFile.canRead() == false) {
                System.out.println(inputFile.getAbsolutePath() + " cannot be read.");
            }

            if (inputFile.isFile() == false) {
                System.out.println(inputFile.getAbsolutePath() + " is not a file.");
            }

            System.out.println("Aborting...");

            return 1;
        }

        File outputFile1 = new File(outputFilenameTemplate + ".1");
        OutputStream outputFile1Stream = null;

        if (outputFile1.exists() == false) {
            outputFile1Stream = new FileOutputStream(outputFile1);
        } else {
            System.out.println(outputFile1.getAbsolutePath() + " already exists.");

            System.out.println("Aborting...");

            return 1;
        }

        File outputFile2 = new File(outputFilenameTemplate + ".2");
        OutputStream outputFile2Stream = null;

        if (outputFile2.exists() == false) {
            outputFile2Stream = new FileOutputStream(outputFile2);
        } else {
            System.out.println(outputFile2.getAbsolutePath() + " already exists.");
            
            System.out.println("Aborting...");
            
            return 1;
        }

        long byteCounter = 0;

        byte currentInputByte[] = new byte[1];
        byte currentRandomByte[] = new byte[1];
        byte currentOutputByte[] = new byte[1];
        
        while (byteCounter <= (inputFileLength - 1)) {
            System.out.println("XORing byte: " + (byteCounter + 1) + " of " + inputFileLength);
            inputFileStream.read(currentInputByte);
            random.nextBytes(currentRandomByte);
            currentOutputByte[0] = (byte)(currentInputByte[0] ^ currentRandomByte[0]);
            outputFile1Stream.write(currentRandomByte);
            outputFile2Stream.write(currentOutputByte);
            byteCounter++;
        }

        inputFileStream.close();
        outputFile1Stream.close();
        outputFile2Stream.close();

        System.out.println("XOR with random data complete. Created files:");
        System.out.println(outputFile1.getAbsolutePath());
        System.out.println(outputFile2.getAbsolutePath());

        return 0;
    }

    /**
     * Takes 2 input files and XORs them together, creating an output file.
     *
     * @param inputFilename1    The name of the first input file.
     * @param inputFilename2    The name of the second input file.
     * @param outputFilename    The name of the output file.
     * @return                  0 (success) or 1 (failure).
     * @throws Exception        An exception.
     */
    public static int xor(String inputFilename1, String inputFilename2, String outputFilename) throws Exception {
        File inputFile1 = new File(inputFilename1);
        InputStream inputFile1Stream = null;
        long inputFile1Length = 0;

        if (inputFile1.exists() & inputFile1.canRead() & inputFile1.isFile()) {
            inputFile1Stream = new FileInputStream(inputFile1);
            inputFile1Length = inputFile1.length();
        } else {
            if (inputFile1.exists() == false) {
                System.out.println(inputFile1.getAbsolutePath() + " does not exist.");

                System.out.println("Aborting...");

                return 1;
            }

            if (inputFile1.canRead() == false) {
                System.out.println(inputFile1.getAbsolutePath() + " cannot be read.");
            }

            if (inputFile1.isFile() == false) {
                System.out.println(inputFile1.getAbsolutePath() + " is not a file.");
            }

            System.out.println("Aborting...");

            return 1;
        }

        File inputFile2 = new File(inputFilename2);
        InputStream inputFile2Stream = null;
        long inputFile2Length = 0;

        if (inputFile2.exists() & inputFile2.canRead() & inputFile2.isFile()) {
            inputFile2Stream = new FileInputStream(inputFile2);
            inputFile2Length = inputFile2.length();
        } else {
            if (inputFile2.exists() == false) {
                System.out.println(inputFile2.getAbsolutePath() + " does not exist.");

                System.out.println("Aborting...");

                return 1;
            }

            if (inputFile2.canRead() == false) {
                System.out.println(inputFile2.getAbsolutePath() + " cannot be read.");
            }

            if (inputFile2.isFile() == false) {
                System.out.println(inputFile2.getAbsolutePath() + " is not a file.");
            }

            System.out.println("Aborting...");

            return 1;
        }

        File outputFile = new File(outputFilename);
        OutputStream outputFileStream = null;

        if (outputFile.exists() == false) {
            outputFileStream = new FileOutputStream(outputFile);
        } else {
            System.out.println(outputFile.getAbsolutePath() + " already exists.");
            
            System.out.println("Aborting...");

            return 1;
        }

        long inputFileShortestLength;

        long byteCounter = 0;

        byte currentInput1Byte[] = new byte[1];
        byte currentInput2Byte[] = new byte[1];
        byte currentOutputByte[] = new byte[1];

        if (inputFile1Length <= inputFile2Length) {
            inputFileShortestLength = inputFile1Length;
        } else {
            inputFileShortestLength = inputFile2Length;
        }

        while (byteCounter <= (inputFileShortestLength - 1)) {
            System.out.println("XORing byte: " + (byteCounter + 1) + " of " + inputFileShortestLength);
            inputFile1Stream.read(currentInput1Byte);
            inputFile2Stream.read(currentInput2Byte);
            currentOutputByte[0] = (byte)(currentInput1Byte[0] ^ currentInput2Byte[0]);
            outputFileStream.write(currentOutputByte);
            byteCounter++;
        }

        inputFile1Stream.close();
        inputFile2Stream.close();
        outputFileStream.close();

        System.out.println("XOR complete. Created file:");
        System.out.println(outputFile.getAbsolutePath());
        
        return 0;
    }

    /**
     * Generates an output file of specified length, consisting of random bytes.
     *
     * @param size              A string representing the desired size of the
     *                          output file.
     * @param outputFilename    The name of the output file.
     * @return                  0 (success) or 1 (failure).
     * @throws Exception        An exception.
     */
    public static int generateRandom(String size, String outputFilename) throws Exception {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

        float outputFileSizeNumber = 0;
        String outputFileSizeUnit = "0";

        if (size.matches("^\\d+\\.{0,1}\\d*[A-Z]{1}i?$")) {
            outputFileSizeNumber = Float.parseFloat(size.replaceAll("[A-Z]{1}i?$", ""));
            outputFileSizeUnit = size.replaceAll("^^\\d+\\.{0,1}\\d*", "");
        } else if (size.matches("^\\d+$")) {
            outputFileSizeNumber = Float.parseFloat(size);
        } else {
            System.out.println("" +
                    "<size> must match format:\n" +
                    "<sizeNumber><sizeUnit>\n" +
                    "where <sizeNumber> is a (decimal) number and <sizeUnit>\n" +
                    "is an appropriate unit multiple. For example:\n" +
                    "5G\n" +
                    "would represent 5 gigabytes (5 * 10^9). You can also leave\n" +
                    "the <sizeUnit> off and have <sizeNumber> as an integer, to\n" +
                    "represent just bytes. For example:\n" +
                    "2100\n" +
                    "would represent 2000 bytes (which would be identical to\n" +
                    "2.1K). Note that these quantities are specified as base-10,\n" +
                    "not base-2. To specify base-2 unit multiples, append an \"i\"\n" +
                    "to the unit multiple. For example:\n" +
                    "2Gi\n" +
                    "would represent 2 gibibytes (2 * 2^30). To represent 3.5\n" +
                    "kibibytes, you would type:\n" +
                    "3.5Ki\n." +
                    "which is 3.5 * 2^10, or 3.5 'binary' kilobytes.");

            System.out.println("Aborting...");

            return 1;
        }

        long outputFileSize = 0;

        if (outputFileSizeUnit.equals("K")) {
            outputFileSize = (long)(outputFileSizeNumber * 1000);
        } else if (outputFileSizeUnit.equals("M")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 2));
        } else if (outputFileSizeUnit.equals("G")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 3));
        } else if (outputFileSizeUnit.equals("T")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 4));
        } else if (outputFileSizeUnit.equals("P")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 5));
        } else if (outputFileSizeUnit.equals("E")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 6));
        } else if (outputFileSizeUnit.equals("Z")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 7));
        } else if (outputFileSizeUnit.equals("Y")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(1000, 8));
        } else if (outputFileSizeUnit.equals("Ki")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 10));
        } else if (outputFileSizeUnit.equals("Mi")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 20));
        } else if (outputFileSizeUnit.equals("Gi")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 30));
        } else if (outputFileSizeUnit.equals("Ti")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 40));
        } else if (outputFileSizeUnit.equals("Pi")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 50));
        } else if (outputFileSizeUnit.equals("Ei")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 60));
        } else if (outputFileSizeUnit.equals("Zi")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 70));
        } else if (outputFileSizeUnit.equals("Yi")) {
            outputFileSize = (long)(outputFileSizeNumber * Math.pow(2, 80));
        } else if (outputFileSizeUnit.equals("0")) {
            outputFileSize = (long)(outputFileSizeNumber);
        } else {
            System.out.println("" +
                    outputFileSizeUnit + " is not a recognised unit multiple.\n" +
                    "Accepted unit multiples are K, M, G, T, P, E, Z, Y, and\n" +
                    "none, which represent kilobytes, megabytes, gigabytes,\n" +
                    "terabytes, petabytes, exabytes, zettabytes, yottabytes, and\n" +
                    "bytes, respectively. Note that these are base-10 unit\n" +
                    "multiples. Accepted base-2 unit multiples are Ki, Mi, Gi,\n" +
                    "Ti, Pi, Ei, Zi, and Yi, which represent kibibytes,\n" +
                    "mebibytes, gibibytes, tebibytes, pebibytes, exbibytes,\n" +
                    "zebibytes, and yobibytes, respectvely.");

            System.out.println("Aborting...");

            return 1;
        }
        
        File outputFile = new File(outputFilename);
        OutputStream outputFileStream = null;

        if (outputFile.exists() == false) {
            outputFileStream = new FileOutputStream(outputFile);
        } else {
            System.out.println(outputFile.getAbsolutePath() + " already exists.");

            System.out.println("Aborting...");

            return 1;
        }

        long byteCounter = 0;

        byte currentRandomByte[] = new byte[1];

        while (byteCounter <= (outputFileSize - 1)) {
            System.out.println("Generating byte: " + (byteCounter + 1));
            random.nextBytes(currentRandomByte);
            outputFileStream.write(currentRandomByte);
            byteCounter++;
        }

        outputFileStream.close();

        System.out.println("Random file generation complete. Created file:");
        System.out.println(outputFile.getAbsolutePath());
        
        return 0;
    }

    /**
     * Prints help and usage information.
     */
    private static void printHelp() {
        System.out.println("" +
                "--------------------\n" +
                "--------------------\n" +
                "Entropi (ver. 0.0.1)\n" +
                "--------------------\n" +
                "--------------------\n" +
                "Entropi is a \"randomness and cryptography toolkit\".\n" +
                "\n" +
                "--------------------\n" +
                "XOR with random data\n" +
                "--------------------\n" +
                "Usage:\n" +
                "java -jar Entropi.jar xor_random <inputFilename> <outputFilenameTemplate>\n" +
                "\n" +
                "Takes \"inputFilename\" and XORs with random data, creating\n" +
                "files \"outputFilenameTemplate.1\" and\n" +
                "\"outputFilenameTemplate.2\". Essentially a one-time pad.\n" +
                "\n" +
                "For example:\n" +
                "java -jar Entropi.jar xor_random mysecret uselessfile\n" +
                "would produce \"uselessfile.1\" and \"uselessfile.2\".\n" +
                "\n" +
                "----------------------\n" +
                "XOR two files together\n" +
                "----------------------\n" +
                "Usage:\n" +
                "java -jar Entropi.jar xor <inputFilename1> <inputFilename2> <outputFilename>\n" +
                "\n" +
                "Takes \"inputFilename1\" and XORs with \"inputFilename2\",\n" +
                "creating file \"outputFilename\".\n" +
                "\n" +
                "For example:\n" +
                "java -jar Entropi.jar xor uselessfile.1 uselessfile.2 samemysecret\n" +
                "would produce \"samemysecret\".\n" +
                "\n" +
                "------------------------\n" +
                "Generating a random file\n" +
                "------------------------\n" +
                "Usage:\n" +
                "java -jar Entropi.jar generate_random <size> <outputFilename>\n" +
                "\n" +
                "Creates file \"outputFilename\" of size \"size\", consisting\n" +
                "of random bytes.\n" +
                "\n" +
                "<size> must match format:\n" +
                "<sizeNumber><sizeUnit>\n" +
                "where <sizeNumber> is a (decimal) number and <sizeUnit>\n" +
                "is an appropriate unit multiple. For example:\n" +
                "5G\n" +
                "would represent 5 gigabytes (5 * 10^9). You can also leave\n" +
                "the <sizeUnit> off and have <sizeNumber> as an integer, to\n" +
                "represent just bytes. For example:\n" +
                "2100\n" +
                "would represent 2000 bytes (which would be identical to\n" +
                "2.1K). Note that these quantities are specified as base-10,\n" +
                "not base-2. To specify base-2 unit multiples, append an \"i\"\n" +
                "to the unit multiple. For example:\n" +
                "2Gi\n" +
                "would represent 2 gibibytes (2 * 2^30). To represent 3.5\n" +
                "kibibytes, you would type:\n" +
                "3.5Ki\n." +
                "which is 3.5 * 2^10, or 3.5 'binary' kilobytes.\n" +
                "\n" +
                "For example:\n" +
                "java -jar Entropi.jar generate_random 5G random.txt\n" +
                "would produce a 5 gigabyte file called \"random.txt\", and:\n" +
                "java -jar Entropi.jar generate_random 10000 morerandom\n" +
                "would produce a 10000 byte file called \"morerandom\". This\n" +
                "would be analogous to:\n" +
                "java -jar Entropi.jar generate_random 10K morerandom\n");
    }

    /**
     * Prints an error message for when the application has been called
     * incorrectly.
     */
    private static void printError() {
        System.out.println("" +
                "Incorrect usage. Type:\n" +
                "java -jar Entropi.jar help\n" +
                "for help and usage information.");
    }
}