Java tutorial
/* * ImportStream.java Created Sep 9, 2010 by Andrew Butler, PSL */ //package prisms.util; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; /** Wraps a stream that has been exported to import the data in readable form */ public class ImportStream extends java.io.InputStream { private java.io.InputStream theInput; /** * Wraps a stream with an import stream * * @param wrap The exported stream to wrap * @throws IOException If an error occurs wrapping the stream */ public ImportStream(java.io.InputStream wrap) throws IOException { java.util.zip.ZipInputStream zis; zis = new java.util.zip.ZipInputStream(ObfuscatingStream.unobfuscate(wrap)); zis.getNextEntry(); theInput = zis; } @Override public int read() throws IOException { return theInput.read(); } @Override public int read(byte[] b) throws IOException { return theInput.read(b); } @Override public int read(byte[] b, int off, int len) throws IOException { return theInput.read(b, off, len); } @Override public long skip(long n) throws IOException { return theInput.skip(n); } @Override public int available() throws IOException { return theInput.available(); } @Override public boolean markSupported() { return theInput.markSupported(); } @Override public synchronized void mark(int readlimit) { theInput.mark(readlimit); } @Override public synchronized void reset() throws IOException { theInput.reset(); } @Override public void close() throws IOException { theInput.close(); } } /** * A utility class that allows for easy simple obfuscation of streamed data */ class ObfuscatingStream { private static final char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * A class that obfuscates data as it is written to a binary stream */ public static class ObfuscatingOutputStream extends OutputStream { private OutputStream theOS; private int theWarp; private int theCount; ObfuscatingOutputStream(OutputStream os) { theOS = os; theWarp = -1; } /** * @see java.io.OutputStream#write(int) */ @Override public void write(int b) throws IOException { if (theWarp < 0) { theWarp = (int) (Math.random() * 8); theOS.write(theWarp); } int shift = (theWarp + theCount) % 8; theCount++; int toWrite = b & 0xff; toWrite = ((toWrite >> shift) | (toWrite << (8 - shift))) & 0xff; theOS.write(toWrite); } } /** * A class the unobfuscates data that was obfuscated by an {@link ObfuscatingOutputStream} as it * is read from an input stream */ public static class UnobfuscatingInputStream extends InputStream { private InputStream theIS; private int theWarp; private int theCount; UnobfuscatingInputStream(InputStream is) { theIS = is; theWarp = -1; } /** * @see java.io.InputStream#read() */ @Override public int read() throws IOException { if (theWarp < 0) theWarp = theIS.read(); int read = theIS.read(); if (read < 0) return read; int shift = (theWarp + theCount) % 8; theCount++; int ret = read & 0xff; ret = ((ret << shift) | (ret >> (8 - shift))) & 0xff; return ret; } } /** * Obfuscates an output stream * * @param os The binary output stream for this utility to write obfuscated data to * @return The output stream for the calling method to write unobfuscated data */ public static OutputStream obfuscate(OutputStream os) { return new ObfuscatingOutputStream(os); } /** * Unobfuscates an input stream * * @param is The binary input stream for this utililty to read obfuscated data from * @return The input stream for the calling method to read the unobfuscated data from */ public static InputStream unobfuscate(InputStream is) { return new UnobfuscatingInputStream(is); } /** * Obfuscates or unobfuscates the second command-line argument, depending on whether the first * argument starts with "o" or "u" * * @param args Command-line arguments * @throws IOException If an error occurs obfuscating or unobfuscating */ public static void main(String[] args) throws IOException { InputStream input = new ByteArrayInputStream(args[1].getBytes()); StringBuilder toPrint = new StringBuilder(); if (args[0].startsWith("o")) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); OutputStream out = obfuscate(bytes); int read = input.read(); while (read >= 0) { out.write(read); read = input.read(); } byte[] receiptBytes = bytes.toByteArray(); for (int b = 0; b < receiptBytes.length; b++) { int chr = (receiptBytes[b] + 256) % 256; toPrint.append(HEX_CHARS[chr >>> 4]); toPrint.append(HEX_CHARS[chr & 0xf]); } } else if (args[0].startsWith("u")) { input = unobfuscate(input); InputStreamReader reader = new InputStreamReader(input); int read = reader.read(); while (read >= 0) { toPrint.append((char) read); read = reader.read(); } } else throw new IllegalArgumentException("First argument must start with o or u"); System.out.println(toPrint.toString()); } }