rendered paste bodypackage 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.");
}
}