rendered paste bodypackage entropi;import java.io.*;import java.security.*;/** * Entropi is a "randomness and cryptography toolkit". * * @author gizmoguy * @version 0.0.3 */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; } Runtime runtime = Runtime.getRuntime(); long arraySize = runtime.maxMemory() / 4; if (arraySize >= inputFileLength) { byte currentInputByte[] = new byte[(int)(inputFileLength)]; byte currentRandomByte[] = new byte[(int)(inputFileLength)]; byte currentOutputByte[] = new byte[(int)(inputFileLength)]; System.out.println("XORing bytes 1 to " + inputFileLength + " of " + inputFileLength); inputFileStream.read(currentInputByte); random.nextBytes(currentRandomByte); for (int i = 0; i < currentOutputByte.length; i++) { currentOutputByte[i] = (byte)(currentInputByte[i] ^ currentRandomByte[i]); } outputFile1Stream.write(currentRandomByte); outputFile2Stream.write(currentOutputByte); } else { byte currentInputByte[] = new byte[(int)(arraySize)]; byte currentRandomByte[] = new byte[(int)(arraySize)]; byte currentOutputByte[] = new byte[(int)(arraySize)]; long byteCounter = 0; while (byteCounter <= inputFileLength) { if ((inputFileLength - byteCounter) >= currentOutputByte.length) { System.out.println("XORing bytes " + (byteCounter + 1) + " to " + (byteCounter + currentOutputByte.length) + " of " + inputFileLength); inputFileStream.read(currentInputByte); random.nextBytes(currentRandomByte); for (int i = 0; i < currentOutputByte.length; i++) { currentOutputByte[i] = (byte)(currentInputByte[i] ^ currentRandomByte[i]); } outputFile1Stream.write(currentRandomByte); outputFile2Stream.write(currentOutputByte); } else { System.out.println("XORing bytes " + (byteCounter + 1) + " to " + inputFileLength + " of " + inputFileLength); inputFileStream.read(currentInputByte); random.nextBytes(currentRandomByte); for (int i = 0; i < currentOutputByte.length; i++) { currentOutputByte[i] = (byte)(currentInputByte[i] ^ currentRandomByte[i]); } outputFile1Stream.write(currentRandomByte, 0, (int)(inputFileLength - byteCounter)); outputFile2Stream.write(currentOutputByte, 0, (int)(inputFileLength - byteCounter)); } byteCounter += currentOutputByte.length; } } 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. In * the event that one input file is bigger than the other, only the shortest * sequence will be XORed (i.e. the smallest file), creating an output file * equal in length to the smallest 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; if (inputFile1Length <= inputFile2Length) { inputFileShortestLength = inputFile1Length; } else { inputFileShortestLength = inputFile2Length; } Runtime runtime = Runtime.getRuntime(); long arraySize = runtime.maxMemory() / 4; if (arraySize >= inputFileShortestLength) { byte currentInput1Byte[] = new byte[(int)(inputFileShortestLength)]; byte currentInput2Byte[] = new byte[(int)(inputFileShortestLength)]; byte currentOutputByte[] = new byte[(int)(inputFileShortestLength)]; System.out.println("XORing bytes 1 to " + inputFileShortestLength + " of " + inputFileShortestLength); inputFile1Stream.read(currentInput1Byte); inputFile2Stream.read(currentInput2Byte); for (int i = 0; i < currentInput1Byte.length; i++) { currentOutputByte[i] = (byte)(currentInput1Byte[i] ^ currentInput2Byte[i]); } outputFileStream.write(currentOutputByte); } else { byte currentInput1Byte[] = new byte[(int)(arraySize)]; byte currentInput2Byte[] = new byte[(int)(arraySize)]; byte currentOutputByte[] = new byte[(int)(arraySize)]; long byteCounter = 0; while (byteCounter <= inputFileShortestLength) { if ((inputFileShortestLength - byteCounter) >= currentOutputByte.length) { System.out.println("XORing bytes " + (byteCounter + 1) + " to " + (byteCounter + currentOutputByte.length) + " of " + inputFileShortestLength); inputFile1Stream.read(currentInput1Byte); inputFile2Stream.read(currentInput2Byte); for (int i = 0; i < currentOutputByte.length; i++) { currentOutputByte[i] = (byte)(currentInput1Byte[i] ^ currentInput2Byte[i]); } outputFileStream.write(currentOutputByte); } else { System.out.println("XORing bytes " + (byteCounter + 1) + " to " + inputFileShortestLength + " of " + inputFileShortestLength); inputFile1Stream.read(currentInput1Byte); inputFile2Stream.read(currentInput2Byte); for (int i = 0; i < currentOutputByte.length; i++) { currentOutputByte[i] = (byte)(currentInput1Byte[i] ^ currentInput2Byte[i]); } outputFileStream.write(currentOutputByte, 0, (int)(inputFileShortestLength - byteCounter)); } byteCounter += currentOutputByte.length; } } 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; } Runtime runtime = Runtime.getRuntime(); long arraySize = runtime.maxMemory() / 2; if (arraySize >= outputFileSize) { byte currentRandomByte[] = new byte[(int)(outputFileSize)]; System.out.println("Generating bytes 1 to " + outputFileSize + " of " + outputFileSize); random.nextBytes(currentRandomByte); outputFileStream.write(currentRandomByte); } else { byte currentRandomByte[] = new byte[(int)(arraySize)]; long byteCounter = 0; while (byteCounter <= outputFileSize) { random.nextBytes(currentRandomByte); if ((outputFileSize - byteCounter) >= currentRandomByte.length) { System.out.println("Generating bytes " + (byteCounter + 1) + " to " + (byteCounter + currentRandomByte.length) + " of " + outputFileSize); outputFileStream.write(currentRandomByte); } else { System.out.println("Generating bytes " + (byteCounter + 1) + " to " + outputFileSize + " of " + outputFileSize); outputFileStream.write(currentRandomByte, 0, (int)(outputFileSize - byteCounter)); } byteCounter += currentRandomByte.length; } } 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.3)\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\". In the event that one input\n" + "file is bigger than the other, only the shortest sequence will\n" + "be XORed (i.e. the smallest file), creating an output file\n" + "equal in length to the smallest file.\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."); }}