Well after experimenting with strong encryption with Xenon 1.0 I realized the XOR one-time pad encryption was not going to cut it because many files nowadays have headers/footers/repetitive byte patters that may be able to be guessed by an attacker. This may give the attacker knowledge of a few bytes of the key and that may translate into knowing about half as many bytes of an updated key. Then with dedication, brilliant guesswork, and immense computing power, they may be able to figure out something around 10 bytes of some future message. That is why this type of security won't cut it - if my intent is for it to be unbreakable this is not adequate.
I made a few necessary improvements so that now it is possible to send the plaintext directly with the ciphertext - give it away to the attacker! - and the attacker will still not know a single byte of the updated or current key. That is much better. Of course I do not advise sending plaintext along with ciphertext for real-world uses.
This update keeps the same general code structure and file format, so I did not do a full 2.0 version change. 1.7 seemed sufficient. Same keys are compatible with 1.0 and 1.7, but obviously they will be handled differently.
That brings me to the next point - all of this newfound security had to come at a price of increased computing time and a requirement for a key to be seven times larger than the plaintext. However, remember that the key can be reused indefinitely with no risk of pattern detection (I would not advise sending the same exact message over and over, but if you did it would not be detectable). For indefinite use, it is recommended to have a key about 20 times larger than a regular message though. After that, you should be safe from all prying eyes.
What makes the new algorithm so much more secure? What happened in Xenon 1.0 was that a file was XOR'd with a one-use pad, and the contents of the plaintext file were used to update the key (after being put through a randomization algorithm). With the assumption that the attacker knew nothing about the message plaintext, this is effectively unbreakable.
However, as I mentioned above, many files that may be desirable to send for communications, such as word documents or html, have required header/footer contents which may be guessed by an attacker - thus for those bytes, the attacker would know both the key and the plaintext through guesswork, and if the attacker knows enough bytes of both key and plaintext they may be able to figure out the outputs of the randomization algorithm and thus the updated key. Admittedly, this does not do much for the attacker and requires immense guesswork, but still I believe this sacrifices the ideals of Xenon as unbreakable encryption.
Thus I decided that it was necessary for the encryption to have another step that makes it impossible to guess the original key values even if the plaintext is known. A good way to do this is by 'shuffling' the ciphertext after it has already been XOR'd - that is, moving the bytes around while keeping their values the same. It is a very powerful technique to obscure the original message because the factorial function (number of permutations) overtakes the uncertainty in message (ways to XOR message) after about 1000 bytes. Shuffling in such a way as to create maximum uncertainty while using a key is actually pretty difficult to do algorithmically. An ideal shuffle algorithm (in my view) would need to perform multiple list-sorting and searching (unsorting in a sense) operations, one for each byte. So a megabyte file would require sorting a list of more than a million indices and then searching through that list for each byte's location. It is very computationally intensive, so I did not implement the algorithm that way. Using an incremental offset presents another problem in that it is more structured (less possible permutations), but it is computationally realistic and effectively solves the original problem of preventing the attacker from knowing which key byte corresponds to each plaintext byte.
I have done lots of testing of multiple shuffling algorithms to find one that offers the most uncertainty for an attacker and Xenon 1.7 contains the one I found to be best. It offers 4 bytes of uncertainty in the location of each individual byte of the plaintext - even if the location of one byte is known, the location of the next one still has 4 bytes of uncertainty (technically that minus one). Most likely, this will be more uncertainty than the size of your message (if it is under 2 gigabytes) in which case the size of your message will be the effective uncertainty. It is pretty secure, considering that even 1 byte of uncertainty per byte of plaintext already makes it impossible to figure out the key with any assurance. As a result of this security, the key has to be 7 times larger than plaintext, the difference being used purely for shuffling the message.
If you have not used Xenon 1.0, check out the project page for details about Xenon keys since they act differently from keys you might be used to.
Download program file here. Code file is available here (and still as messy as before!).