Tom7byteselect stream cipher
This is a method of combining inline generators of any sort (in the code below I use LFSR skipstate generators) in a way which increases the complexity of the system. The idea is to use eight inline generators to select a byte from a keydependent permutation of bytes. The output is used as the input to the generators in the next round, and a 8bit wraparound counter is also xor'd with the output of the generators before entering the pbox. Because the 8bit counter ensures that the output from the generators can select any byte, even if it remains constant, the generators can have rather weak random properties without severely compromising the device's effectiveness (ie, sending it into a short cycle). Clocked LFSR's probably would not be too devastating. Of course, it makes more sense to use proper generators. In the implementation below I've used LFSR skipstate generators; anything else with good random properties is candidate, and the generators do not have to all be the same type (combining types, in fact, is a very sound idea). The code below initializes the pbox in the same manner as RC4, and initializes the generators as in Tom7fselect. Analysis Using my program stat, this produces welldistributed pseudo random bits for a variety of keys (up to degree 7). This is by no means a thorough test, but it performs as expected, at least. The biggest weakness I see in this is that the PBox does not change. This seems to make a knownplaintext pretty reasonable. Improvements The PBox does not change. I tried to think of an elegant way to make it change without totally ripping off RC4, but failed. It would greatly increase security to have the PBox change. Since the PBox must change by the key in this implementation anyway, this should not make hardware implementations much more difficult or expensive. The code below uses generators with periods which are not all relatively prime. I highly recommend using generators which are; my source of data Applied Cryptography did not have enough. LFSRs are considered insecure and probably should not be used. Implementation This implementation just spits out the bits in ascii notation as my other programs do, something like: while (EOF != (a=getc(stdin))) { ... get output byte ... putchar(a ^ output); } Would be a more appropriate main loop for a filter interface (note that DOS will not handle binary redirection well, but this will work under unix). /* C Implementation of Tom7byteselect generator (using skipstate LFSRs). This code is distributed under the GNU public license; see http://www.gnu.org/copyleft/gpl.html. I can't make any claims about the security of this algorithm because I am not a trained cryptographer, though it produces (as far as I can tell) statistically random output. This code should be thought about, but not used unless you know more about this than me. If you implement this, use generators which have lengths that are relatively prime, and combine different types of generators. Tom 7 http://tom7.org/ */ #include <stdio.h> #include <stdlib.h> #define INPUT_SKIPSTATE 1 #define s(a,b,c) m=a[(b)];a[(b)]=a[(c)];a[(c)]=m; // swap bytes b and c in array a typedef struct { unsigned long data; unsigned long mask; unsigned char len; unsigned char inputs; } LFSR; unsigned char generator(LFSR * g); unsigned char skipstate_generator(LFSR * g); LFSR G[8] = { {0,(1<<31)(1<<6)(1<<4)(1<<2)(1<<1)1,31,0}, {0,(1<<29)(1<<5)(1<<3)1,29,0}, {0,(1<<30)(1<<12),30,0}, {0,(1<<18)(1<<4)(1<<1)1,18,0}, {0,(1<<16)(1<<4),16,0}, {0,(1<<12)(1<<3)(1<<2)1,12,0}, {0,(1<<31)(1<<6)(1<<2)(1<<1)1,31,0}, {0,(1<<22)(1<<4),22,0} }; int main (int argc, char**argv) { int x,z,c,a,m,s; unsigned char output=0,counter=0; unsigned char P[256],K[256],j; char * key = argv[1]; if (argc < 2) { printf("%s key\n", argv[0]); exit(1); } s = strlen(key); for (x=c=0;x<8;x++) { G[x].data = key[c++%s] << 24; G[x].data = key[c++%s] << 16; G[x].data = key[c++%s] << 8 ; G[x].data = key[c++%s] ; a = key[c++%s]; while (a) generator(&G[x]); } for (x=0;x<256;x++) K[P[x]=x]=key[x%s]; for (x=j=0;x<256;x++) { j+=P[x]+K[x]; s(P,x,j); } /* Filled LFSR's, PBox with keydependent material */ if (argc>2) z = atoi(argv[2]); else z=1000; while (z) { for (x=0;x<8;x++) G[x].inputs = (output>>x)&1; output = counter++; for (x=0;x<8;x++) output ^= skipstate_generator(&G[x])<<x; output = P[output]; for (x=0;x<8;x++) putchar('0' + ((output>>x)&1)); } return 0; } unsigned char skipstate_generator(LFSR * g) { if (g>inputs & INPUT_SKIPSTATE) generator(g); g>inputs &= ~INPUT_SKIPSTATE; return generator(g); } unsigned char generator(LFSR * g) { if (!g>data) g>data; /* LFSR cannot hold 0, or it will cycle */ if (g>data & 1) { g>data = ((g>data ^ g>mask) >> 1)  (1<<g>len); /* g>len is already len1 */ return 1; } else { g>data>>=1; return 0; } } Back to Tom's Cryptography Thingie.
