Before I begin: I've pretty recently fallen for crypto in a hard way, and while I've always enjoyed the novelty of simple ciphers, the nuts and bolts are now more like jewels and diamonds. To that end, I'd like to extend my thanks to you all for this forum, for the information you've posted here, and for the links to information hosted elsewhere. Thank you.

With that said, I'd like to dump my brain about this cipher. My apologies if anything written from here on out is blatantly obvious, elementary, just-plain-wrong, or otherwise. My thanks for any feedback or criticisms which contribute towards improvement...

I'd like to submit for your dissection, digestion and review, an output-feedback mode stream cipher that employs pseudo random rolling keys based on a master key seed. I call it KB15 and have implemented it in ... (is anyone looking?) ... Javascript. It is inspired by Bruce Schneier's "Solitaire" in the same way that tea is inspired by sugar, yet includes a few of my own discoveries. Of course none of these discoveries were truly my own, as they had already been long discovered in the crypto world.

The Stream Cipher:

Like all stream ciphers, KB15 works by assigning numeric values to a fixed set of letters and symbols, aka the stream. In this way, a stream cipher is both defined and limited by it's stream since any symbol unaccounted for cannot be encrypted and, therefore, will be dropped from the final message. KB15 has a total of 96 symbols in it's stream, these include: All English letters and symbols, as they appear on a standard QWERTY keyboard, spaces, line-breaks and tabs.

To encrypt a symbol, X, using a key, Y, we'll convert both X and Y into numbers, derived from their position in the stream, then add them together. The total of this addition will become the value of our encrypted character, Z.Code:var charStream = "»IdxWCsMrTFhOKNelwjUvAGZBYRmaiEcQHuVJoyPDfnzbtpqSkLgx0123456789\~\`\!\@\#\$\%\^\&\*\(\)\_\-\+\=\{\[\}\]\|\\\:\;\"\'\<\,\>\.\?\/\n\t ";

If Z exceeds the number of characters in our stream, we'll subtract the number of characters in our stream from it, in effect forcing it back to the beginning of the stream. Decryption follows the same process, but reversed.Code:var nextEncodedChar = charStream.indexOf(thisCipherValue) + charStream.indexOf(thisClearValue);

For this reason, in the Javascript implementation above, our stream begins with an unused symbol in position 0. This is because any number plus or minus 0 is itself and would defeat the algorithm.

Pseudo Random and Rolling Keys:

By default, KB15 generates a pseudo random, 62 character long key of alphanumeric symbols. If the key is not the same length as the text it is meant to encrypt, it will repeat itself until it is.

However, this is a security concern. If an attacker were to map out all of the possible values of each encryption key symbol against each clear text symbol, not only could they break the message, but a string of values that kept repeating themselves would be a dead giveaway.Code:for ( var f = cipherKeyLen; f < clearTextLen; f++ ) { c++; if ( c >= cipherKeyLen ) { c = 0; } cipherKeyArray.push(cipherKeyArray[c]); }

To this end, KB15 has several additional measures in place. The first of these measures is what I call "Paranoia." Paranoia, P, is not an uncommon concept in the crypto world: put simply, it just says "Hey, take the encrypted output you just made and encrypt that again." KB15 will do this as many times as specified by P.

That in itself is not enough, however. Say your Paranoia level were 2, aka encrypt the encrypted output once. If you used the same key for both stages of the encryption, what would be the point? The first layer of the onion would reveal the second layer without further analysis. This won't do as KB15 seeks to make any attacker work, and work hard, for that onion.Code:for ( var a = 0; a < p; a++ ) {

Queue the second measure: rolling keys. Rolling keys are, again, not an uncommon concept in the crypto world.

KB15 uses them as such: the user enters a master key. This master key can be any alphanumeric string of any finite length. The master key is parsed, one symbol at a time, and each symbol is converted into it's corresponding value in the stream. That value then undergoes the following equation: Rounding up to the nearest integer, take the number of the Paranoia phase that we're at plus Pi, and multiply it by the natural logarithm of 10, then take that total and add it to the square root of the number of the Paranoia phase that we're at.

Finally, if that number is greater than 48, aka halfway through our keystream, subtract the value of the Paranoia number we're at from it. If it is less than 48, add the value of the Paranoia number that we're at to it.Code:var p = Math.round(((p + Math.PI) * Math.LN10) + Math.sqrt(p));

The result of this will be a new, pseudo random key based upon the master seed key but ultimately different. KB15 will repeat this process for each phase of Paranoia, so that each layer of the onion is encrypted with a different key; a key the user could compute but, practically, does not know.Code:if ( thiscipherKeyArrayValue >= 48 ) { thiscipherKeyArrayValue = thiscipherKeyArrayValue - p; } else { thiscipherKeyArrayValue = thiscipherKeyArrayValue + p; }

This also introduces a security risk, however, because the equation, while pseudo random in appearance, is not truly random: it will follow a fixed and mathematically significant order. This means that, if an attacker were to examine all possible key possibilities, they could potentially discern the unique pattern created by this equation and discover the keys used for encryption.

To prevent this, the stream as defined in the charStream variable is arranged in a pseudo random order. This means that there isprobablymore/less linguistic correlation between any set of number values and therefore, theoretically, a higher number of possible keys which fit the profile of the equation - many of which are dead ends.

To add a further layer of complication, as a final measure, KB15 will reverse the order of every other pseudo random key that it uses.

The net result of all of this, then, is that not only is our onion pretty securely encrypted at multiple levels, but the end user can also utilize a dictionary based key without quite as much concern since that word won't actually be used to encrypt the text.Code:if ( a % 2 == 0 ) { return rollingKeyArray.join("").toString(); } else { return rollingKeyArray.reverse().join("").toString(); }

Of course, the best practice is to use a pseudo random master key as well. Also, any key used is ideally as long as, or very close to it, the length of the text it will encrypt. And, of course, do not use the same key twice. :p

Output:

The output modes programmed into KB15 are not cryptographically important. They are just formatting for human eyes. The first, and default, will return a constant string of alphanumeric symbols as the cipher text. This is called "Stream." The second will split the cipher text into blocks of 4 symbols each, separated by spaces, i.e. AAAA 0000 BBBB 1111. This is called "Block-4." The final mode will output the stream into lines consisting of 8 blocks, with each block containing 4 symbols, i.e. like PNG encoding. This is called "PNG-like."

Implementation:

I have implemented KB15 at: http://nullsnode.nfshost.com/KB15

I would be very honored if you tried it out and let me know your thoughts. This demo includes a 'console' of sorts which should give some glimpse into the inner workings of the algorithm. You can access thecommented codedirectly at: http://nullsnode.nfshost.com/KB15/kb15.js

Use:

In the event that anyone finds any portion of my code or implementation useful, you have my sincere gratitude and encouragement to use it on two conditions: 1. that it not be used for profit, and 2. that it not be used academically/professionally without attribution. Not that I presume either of these scenarios will happen, but I just want to put it out there.

Thank you for your time, I know this was long-winded. I welcome any feedback, questions, concerns, comments or otherwise - especially if I have missed something obvious.

As well, let me know if you have an algorithm that you'd like me to review, or any links or reading material that you think I should research. I would love to learn more.

- Null

Tweet This+ 1 thisPost To Linkedin