Critique of FilterInputStream and FilterOutputStream classes
It looks like you have covered the bases quite well. There are some things I would like to suggest, and the first one is the most important:


  The performance of Input/Output Streams that read/write 1 byte at a time is really, really bad. You should also override the bulk read(...)/write(...) methods.


Now, when you get around to doing the bulk methods, you will have some challenges with getting the byte manipulation right, but that's another problem.... ;-)

Now in your decrypt routine you have:

int b = super.read();
return (b != -1 ? b ^ XOR_KEY : b);


I don't like this. The reason is that it has too much negative logic..... and even though it relates b to a constant -1 you return b instead of -1. Consider the following alternative:

return b == -1 ? -1 : b ^ XOR_KEY;


I know it is a minor nit-pick, but it does make a difference.

On that note, you had better make sure that XOR_KEY is always positive... a negative XOR_KEY will cause the result to be negative, and break all sorts of InputStream readers.

Now, you say the key should be as long as the message... that's not true. Even some of the best algorithms use 2048-bit keys (256 bytes). and many of them use much less (16 bytes...).

Additionally, you hint that you know that storing the key the way you do is incorrect ... It should be passed in as a constructed value or something, and not hard-coded as a static variable.

What you have is more than 'adequate', it is neat, and appears to be fully accurate... but, in order to be good, or great, it needs to do the bulk-operations...