/* Frogbit demonstration and challenge program Copyright (C) 1996 CONNOTECH Experts-Conseils Inc. Author: Thierry Moreau CONNOTECH Experts-Conseils Inc. 9130 Place de Montgolfier Montreal, Qc Canada H2M 2A1 Date: April 17, 1996, revised April 2005 Revision History: Bug fix in LFSR generator(!). Idiosyncracies of 16-bit C. Fixed a name clash with a BSD definition in string.h Removed huffman coding for packing the final state in the verbose mode Reverted to binary ciphertext file; default binary cleartext file; command-line options starting with - instead of + Added the -o[1-7] option to omit from 1 to 7 bits from the end of the file, for enhanced flexibility in the standard challenge Enhanced source code readability with the last source code change Fixed a bug in state input rule enforcement Implemented 20 LFSRs from pi hexadecimal notation instead of 10 simpler LFSRs for the 10 frogbit PRNGs Changed from most significant bit first to least significant bit first Minor source code readability enhancements Purposes: 1) to foster cryptanalysis attempts against the Frogbit hash function, 2) to foster cryptanalysis attempts against the Frogbit encryption, granted a 25-years old attack on the underlying stream cipher. Comment: This program provides a simple file encryption capability, but the (claimed) distinctive advantage of the Frogbit algorithm is DATA INTEGRITY protection. As a consequence, the "challenge" aspect of this program relates to finding collision in a hash function. Prerequisite: This is cryptographic stuff. The intended reader is familiar with the subject area. Practical limitations: No attempt has been made to make the encryption capability convenient and/or portable. Little validation is applied to the input data (but the parameter values are forced to abide by the theoretical requirements). Moreover, although the cryptographic strength of this program is conjectured to be good, an important component (the underlying pseudo-random algorithm) has been deliberately chosen to be an INSECURE alternative. User's guide: This is ANSI C source code. The compiled program is a command-line utility, taking four optional file names: cleartext file, ciphertext file, final secret key file, and initial secret key file. The main challenge is to find two pairs that produce the same final secret key file. The auxiliary challenge is to find an algorithm that recovers the initial secret key file from a cleartext file and the corresponding ciphertext file. How to read this source code: Sequentially. Housekeeping stuff is identified with /**/ /* at the beginning of each line. In addition, /*RULE*/ /* identifies places in the source code where a theoretical rule is enforced (in the context of processing the initial secret key file). */ /**********************************************************************/ /*** ***/ /*** The base Frogbit algorithm ***/ /*** ***/ /**********************************************************************/ typedef int ind_t; typedef int bit; /*--------------------------------------------------------------------*/ /*---------------- the state of the Frogbit algorithm ----------------*/ ind_t T[10]; /* the current permutation table, T(i-1-r'(i-1)) */ ind_t d_; /* the current key stream number, d'(i-1) */ bit s; /* the previous bit, s{i-1} */ /* local variables for the run length process */ ind_t r_; /* the current bounded run count, r'(i-1) */ ind_t acc_d; /* accumulated binary representation K2{i-1}, k2{i}*/ /*--------------------------------------------------------------------*/ /*------------------ keystream "drift" accumulators ------------------*/ /* These accumulators are for information purposes. Their final values may come into play for a hash code. The active state of the pseudo-random generators is dealt with later. */ struct cntr { unsigned long c; /* A count of consumed keystream bits ... */ int i; /* ... for this key stream source. */ } drift_cnt[10]; /*--------------------------------------------------------------------*/ /*------------------ the index permutation process -------------------*/ void index_permutation(int j) { int temp; int temp_d_= T[j]; switch((d_<<1)+s) { case 0: temp=T[0];T[0]=T[5];T[5]=T[2];T[2]=T[7];T[7]=temp; temp=T[1];T[1]=T[8];T[8]=T[6];T[6]=T[4];T[4]=T[3];T[3]=T[9]; T[9]=temp; break; case 1: temp=T[0];T[0]=T[2];T[2]=T[7];T[7]=temp; temp=T[1];T[1]=T[3];T[3]=T[6];T[6]=T[9];T[9]=T[4];T[4]=T[8]; T[8]=T[5];T[5]=temp; break; case 2: temp=T[0];T[0]=T[6];T[6]=T[8];T[8]=T[9];T[9]=T[5];T[5]=T[7]; T[7]=T[1];T[1]=temp; temp=T[2];T[2]=T[4];T[4]=T[3];T[3]=temp; break; case 3: temp=T[0];T[0]=T[6];T[6]=temp; temp=T[1];T[1]=T[5];T[5]=T[3];T[3]=T[4];T[4]=T[2];T[2]=T[8]; T[8]=T[7];T[7]=T[9];T[9]=temp; break; case 4: temp=T[0];T[0]=T[3];T[3]=T[6];T[6]=T[5];T[5]=T[1];T[1]=T[2]; T[2]=temp; temp=T[4];T[4]=T[8];T[8]=T[7];T[7]=T[9];T[9]=temp; break; case 5: temp=T[0];T[0]=T[6];T[6]=T[7];T[7]=T[3];T[3]=T[1];T[1]=T[2]; T[2]=T[9];T[9]=temp; temp=T[4];T[4]=T[5];T[5]=T[8];T[8]=temp; break; case 6: temp=T[0];T[0]=T[4];T[4]=T[3];T[3]=T[7];T[7]=T[6];T[6]=T[1]; T[1]=T[8];T[8]=T[5];T[5]=temp; temp=T[2];T[2]=T[9];T[9]=temp; break; case 7: temp=T[0];T[0]=T[5];T[5]=T[4];T[4]=temp; temp=T[1];T[1]=T[9];T[9]=T[8];T[8]=T[6];T[6]=T[2];T[2]=T[3]; T[3]=T[7];T[7]=temp; break; case 8: temp=T[0];T[0]=T[8];T[8]=T[9];T[9]=T[5];T[5]=T[3];T[3]=T[2]; T[2]=T[1];T[1]=temp; temp=T[4];T[4]=T[6];T[6]=T[7];T[7]=temp; break; case 9: temp=T[0];T[0]=T[9];T[9]=T[7];T[7]=T[8];T[8]=T[1];T[1]=T[4]; T[4]=T[2];T[2]=T[6];T[6]=temp; temp=T[3];T[3]=T[5];T[5]=temp; break; case 10: temp=T[0];T[0]=T[7];T[7]=T[2];T[2]=T[4];T[4]=T[1];T[1]=T[6]; T[6]=T[5];T[5]=T[9];T[9]=temp; temp=T[3];T[3]=T[8];T[8]=temp; break; case 11: temp=T[0];T[0]=T[1];T[1]=T[4];T[4]=T[7];T[7]=T[5];T[5]=T[2]; T[2]=T[8];T[8]=T[3];T[3]=temp; temp=T[6];T[6]=T[9];T[9]=temp; break; case 12: temp=T[0];T[0]=T[7];T[7]=T[6];T[6]=T[3];T[3]=temp; temp=T[1];T[1]=T[4];T[4]=T[9];T[9]=T[2];T[2]=T[5];T[5]=T[8]; T[8]=temp; break; case 13: temp=T[0];T[0]=T[3];T[3]=T[5];T[5]=T[2];T[2]=temp; temp=T[1];T[1]=T[9];T[9]=T[7];T[7]=T[4];T[4]=T[6];T[6]=T[8]; T[8]=temp; break; case 14: temp=T[0];T[0]=T[8];T[8]=T[4];T[4]=T[2];T[2]=T[1];T[1]=T[9]; T[9]=T[3];T[3]=temp; temp=T[5];T[5]=T[7];T[7]=T[6];T[6]=temp; break; case 15: temp=T[0];T[0]=T[9];T[9]=T[6];T[6]=T[3];T[3]=T[1];T[1]=T[5]; T[5]=temp; temp=T[2];T[2]=T[4];T[4]=T[7];T[7]=T[8];T[8]=temp; break; case 16: temp=T[0];T[0]=T[7];T[7]=T[2];T[2]=T[6];T[6]=T[1];T[1]=T[3]; T[3]=T[9];T[9]=T[8];T[8]=temp; temp=T[4];T[4]=T[5];T[5]=temp; break; case 17: temp=T[0];T[0]=T[4];T[4]=T[1];T[1]=T[7];T[7]=T[8];T[8]=temp; temp=T[2];T[2]=T[9];T[9]=T[3];T[3]=T[5];T[5]=T[6];T[6]=temp; break; case 18: temp=T[0];T[0]=T[2];T[2]=T[3];T[3]=T[8];T[8]=temp; temp=T[1];T[1]=T[7];T[7]=T[5];T[5]=T[6];T[6]=T[4];T[4]=T[9]; T[9]=temp; break; case 19: temp=T[0];T[0]=T[1];T[1]=T[6];T[6]=T[7];T[7]=T[3];T[3]=T[4]; T[4]=temp; temp=T[2];T[2]=T[5];T[5]=T[9];T[9]=T[8];T[8]=temp; break; } d_ = temp_d_; } /*--------------------------------------------------------------------*/ /*-------------------- the core Frogbit algorithm --------------------*/ bit get_PR_bit(ind_t PR_gen_selector,int ik); /* Forward reference: key stream sources */ bit encipher_bit(bit m_i_) { int base; bit k1_i_ = get_PR_bit(d_,0); bit k2_i_ = get_PR_bit(d_,1); bit s_i_ = m_i_^k1_i_; drift_cnt[d_].c++; if (s!=s_i_) if (r_==0) base=0; else base=(acc_d+1)<<1; else if (r_!=0) base=(acc_d+3)<<1; else { acc_d=k2_i_; r_=1; return s_i_^k2_i_; } index_permutation(base+k2_i_); r_= 0; s=s_i_; return s_i_^k2_i_; } bit decipher_bit(bit e_i_) { int base; bit k1_i_ = get_PR_bit(d_,0); bit k2_i_ = get_PR_bit(d_,1); bit s_i_ = e_i_^k2_i_; drift_cnt[d_].c++; if (s!=s_i_) if (r_==0) base=0; else base=(acc_d+1)<<1; else if (r_!=0) base=(acc_d+3)<<1; else { acc_d=k2_i_; r_=1; return s_i_^k1_i_; } index_permutation(base+k2_i_); r_= 0; s=s_i_; return s_i_^k1_i_; } /*--------------------------------------------------------------------*/ /*------------ default initialization of the Frogbit state -----------*/ void start_cipher(void) /* This mechanism may be overridden, and indeed it is when a secret key file includes more than just the PRNG state. */ { ind_t i; d_= s= r_= 0; for (i=0;i<10;i++) { T[i]=i; drift_cnt[i].c=0; drift_cnt[i].i=i; } /* do the processing as if m{i}=0 until one d(i) is drawn, and do it once more */ do encipher_bit(0); while (r_!=0); encipher_bit(0); } /*--------------------------------------------------------------------*/ /**/#include /**/#include /**/#include /**/#include /**/#include /**/#include #if (INT_MAX<=32767) #define L "l" #else #define L #endif /*--------------------------------------------------------------------*/ /*------------------- file encryption/decryption ---------------------*/ int omit_count=0; void encipher(FILE *in, FILE *out) { int i, c, e; int cnext; cnext=getc(in); if (EOF==cnext) return; for (;;) { c=cnext; cnext=getc(in); if (EOF==cnext) break; e=0; for (i=1;i<=(1<<(CHAR_BIT-1));i<<=1) if (encipher_bit(0!=(i&c))) e|=i; fputc(e,out); } e=0; for (i=1;i<=(1<<(CHAR_BIT-omit_count-1));i<<=1) if (encipher_bit(0!=(i&c))) e|=i; fputc(e,out); } void decipher(FILE *in, FILE *out) { int i, c, e; int cnext; cnext=getc(in); if (EOF==cnext) return; for (;;) { e=cnext; cnext=getc(in); if (EOF==cnext) break; c=0; for (i=1;i<=(1<<(CHAR_BIT-1));i<<=1) if (decipher_bit(0!=(i&e))) c|=i; fputc(c,out); } c=0; for (i=1;i<=(1<<(CHAR_BIT-omit_count-1));i<<=1) if (decipher_bit(0!=(i&e))) c|=i; fputc(c,out); } /**********************************************************************/ /*** ***/ /*** read and write the Frogbit state ***/ /*** (minimal and extended secret keys) ***/ /*** ***/ /**********************************************************************/ /*--------------------------------------------------------------------*/ /*---------- the state of the 10 PRNGs (minimal secret key) ----------*/ unsigned long next [10][2]={{1,1},{1,1},{1,1},{1,1},{1,1} ,{1,1},{1,1},{1,1},{1,1},{1,1}}; /*--------------------------------------------------------------------*/ /*---- get the state from the file data, enforce theoretical rules ---*/ void adjust_prng_state(void); /* forward references */ void get_prng_design(int argc, char *argv[]); void get_state(int argc, char *argv[]) { int i; /*{ PRNG state }*/ for (i=0;i<10;i++) { if (argc>(2*i+1)) { next[i][0]=strtoul(argv[2*i+1],NULL,0); } else break; if (argc>(2*i+2)) { next[i][1]=strtoul(argv[2*i+2],NULL,0); } else break; } if (argc>=21) { /*{ key-stream selection state }*/ d_= 0; if (argc>21) d_=strtoul(argv[21],NULL,0)%10; /*RULE*//* 0<=d_<10 */ /*{ index permutation state }*/ for (i=0;i<10;i++) T[i]=i; for (i=0;i<10;i++) if (argc>(i+22)) { int ii; int cand=strtoul(argv[i+22],NULL,0)%10; /*RULE*//* 0<=T[i]<10 */ for (ii=i;ii<10;ii++) if (T[ii]==cand) break; if (ii<10) /*RULE*//* the vector T[10] is a permutation */ { for (;ii>i;ii--) T[ii]=T[ii-1]; T[i]=cand; } } else break; /*{ run length encoding (RLE) state }*/ s= r_= acc_d= 0; if (argc>32) s=strtoul(argv[32],NULL,0)%2; /*RULE*//* s is a single bit */ if (argc>33) r_=strtoul(argv[33],NULL,0)%2; /*RULE*//* 0<=r_<2 */ if ((argc>34)&&(r_>0)) { acc_d=strtoul(argv[34],NULL,0); acc_d%=1<35) /*{ PRNG design parameters }*/ get_prng_design(argc-34,argv+34); /* rules specific to the PRNG */ adjust_prng_state(); /* rules specific to the PRNG */ for (i=0;i<10;i++) { drift_cnt[i].c=0; drift_cnt[i].i=i; } } else { /* secret key limited to PRNG state, use default Frogbit initialization */ adjust_prng_state(); /* rules specific to the PRNG */ start_cipher(); } } /*--------------------------------------------------------------------*/ /*----------- write the state to the final secret key file -----------*/ /**/void print_prng_design(FILE *fp); /* forward reference */ /**/void print_drift_accum(FILE *fp); /* forward reference */ /**/int verbose_flag=0; /**/void print_state(FILE *fp) /**/{ /**/ int i; /**/ adjust_prng_state(); /**/ fprintf(fp,"{ PRNG state }"); /**/ for (i=0;i<10;i++) /**/ { /**/ fprintf(fp," 0x%" L "X 0x%" L "X",next[i][0],next[i][1]); /**/ if (0==((i+2)%3)) fprintf(fp,"\n"); /**/ } /**/ fprintf(fp,"\n"); /**/ if (verbose_flag) /**/ print_drift_accum(fp); /**/ fprintf(fp,"{ key-stream selection state } %d\n",d_); /**/ fprintf(fp,"{ index permutation state }"); /**/ for (i=0;i<10;i++) /**/ fprintf(fp," %d",T[i]); /**/ fprintf(fp,"\n{ run length encoding (RLE) state } %d %d %d\n" /**/ ,s,r_,acc_d%(1<c<((struct cntr *)b)->c) /**/ ?-1 /**/ :(((struct cntr *)a)->c>((struct cntr *)b)->c) /**/ ); /**/} /**/void print_drift_accum(FILE *fp) /**/{ /**/ int i; /**/ qsort(drift_cnt,10,sizeof(drift_cnt[0]),cmp_cntr); /**/ fprintf(fp,"{ keystream drift: %d:%" L "d" /**/ ,drift_cnt[0].i,drift_cnt[0].c); /**/ for(i=1;i<10;i++) /**/ fprintf(fp," %d+%" L "d",drift_cnt[i].i /**/ ,drift_cnt[i].c-drift_cnt[i-1].c); /**/ fprintf(fp," }\n"); /**/} /**********************************************************************/ /*** ***/ /*** housekeeping tasks ***/ /*** ***/ /**********************************************************************/ /*--------------------------------------------------------------------*/ /*-------- housekeeping: lexical analysis of secret key file ---------*/ /**/char file_buf[8*1024]; /**/void parse_state(FILE *fp) /**/{ /**/ int argc; /**/ char *argv[25+11]; /**/ char *s; /**/ file_buf[fread(file_buf,1,sizeof(file_buf)-1,fp)]=0; /**/ fclose(fp); /**/ s=file_buf; /**/ argv[0]="?"; /**/ for(argc=1;argc<(25+11);argc++) /**/ { /**/ for (;;) /**/ { /**/ char *end_comment; /**/ argv[argc]=strtok(s," \n\r\t\v\f"); s=NULL; /**/ if ((NULL==argv[argc])||('{'!=argv[argc][0])) /**/ break; /**/ for(;;) /**/ { /**/ end_comment=strchr(argv[argc],'}'); /**/ if (NULL!=end_comment) break; /**/ argv[argc]=strtok(NULL," \n\r\t\v\f"); /**/ if (NULL==argv[argc]) /**/ break; /**/ } /**/ if (NULL==argv[argc]) /**/ break; /**/ if (0!=*(end_comment+1)) /**/ { /**/ argv[argc]=end_comment+1; /**/ break; /**/ } /**/ } /**/ if (NULL==argv[argc]) /**/ break; /**/ } /**/ get_state(argc,argv); /**/} /*--------------------------------------------------------------------*/ /*---------- housekeeping: help to the user in case of error ---------*/ /**/void usage(char *s) /**/{ /**/ fprintf(stderr, /**/ "usage: %s [flags] [inp [out [final [init]]]]\n" /**/ "\n" /**/ " Frogbit file encryption demo\n" /**/ "\n" /**/ "flags:\n" /**/ " -e encryption operation (default)\n" /**/ " -d decryption operation\n" /**/ " -t cleartext file is text format (default is binary file)\n" /**/ " -f force overwriting existing files\n" /**/ " -v a more verbose final state file\n" /**/ " -o[1-7] omit so many bits at the end of input file\n" /**/ "\n" /**/ "arguments\n" /**/ " inp: input file name (default: standard input)\n" /**/ " out: output file name (default: standard output)\n" /**/ " final: final state file name (default: standard error)\n" /**/ " init: initial state file name (secret key)\n" /**/ ,s); /**/} /*--------------------------------------------------------------------*/ /*- housekeeping: the main program, checking command line parameters -*/ /**/int main (int argc, char *argv[]) /**/{ /**/ FILE *in=stdin; /**/ FILE *out=stdout; /**/ FILE *init_st=NULL; /**/ FILE *final_st=stderr; /**/ int decrypt_flag=0; /**/ int binary_flag=1; /**/ int force_flag=0; /**/ int i; /**/ for (i=1;i='1')&&(argv[i][2]<='7')) /**/ ?(argv[i][2]-'0') /**/ :0; /**/ break; /**/ default: /**/ { /**/ fprintf(stderr,"Error: unknown flag!\n\n"); /**/ usage(argv[0]); /**/ exit(EXIT_FAILURE); /**/ } /**/ } /**/ else /**/ break; /**/ } /**/ if (argc>(i)) /**/ { /**/ in=fopen(argv[i],(binary_flag||decrypt_flag)?"rb":"r"); /**/ if (NULL==in) /**/ fprintf(stderr,"Error: can't open file \"%s\"!\n\n",argv[i]); /**/ } /**/ if (argc>(i+1)) /**/ { /**/ out=fopen(argv[i+1],"r"); if (out) fclose(out); /**/ if ((NULL==out)||force_flag) /**/ { /**/ out=fopen(argv[i+1],(binary_flag||!decrypt_flag)?"wb":"w"); /**/ if (NULL==out) /**/ fprintf(stderr,"Error: can't open file \"%s\"!\n\n",argv[i+1]); /**/ } /**/ else /**/ { /**/ fprintf(stderr,"Error: file \"%s\" already exists!\n\n" ,argv[i+1]); /**/ out=NULL; /**/ } /**/ } /**/ if (argc>(i+2)) /**/ { /**/ final_st=fopen(argv[i+2],"r"); if (final_st) fclose(final_st); /**/ if ((NULL==final_st)||force_flag) /**/ { /**/ final_st=fopen(argv[i+2],"w"); /**/ if (NULL==final_st) /**/ fprintf(stderr,"Error: can't open file \"%s\"!\n\n" ,argv[i+2]); /**/ } /**/ else /**/ { /**/ fprintf(stderr,"Error: file \"%s\" already exists!\n\n" ,argv[i+2]); /**/ final_st=NULL; /**/ } /**/ } /**/ if (argc>(i+3)) /**/ { /**/ init_st=fopen(argv[i+3],"r"); /**/ if (NULL==init_st) /**/ fprintf(stderr,"Error: can't open file \"%s\"!\n\n",argv[i+3]); /**/ } /**/ if ((NULL==in)||(NULL==out)||(NULL==final_st)) /**/ { /**/ usage(argv[0]); /**/ exit(EXIT_FAILURE); /**/ } /**********************************************************************/ /*** ***/ /*** here is what this program really does! ***/ /*** ***/ /**********************************************************************/ if (NULL!=init_st) parse_state(init_st);/* use the initial key file */ else start_cipher(); /* use defaut (secret) key */ if (decrypt_flag) decipher(in,out); else encipher(in,out); print_state(final_st); fclose(in); fclose(out); fclose(final_st); return EXIT_SUCCESS; } /**********************************************************************/ /*** ***/ /*** the PRNG, pseudo-random number generator ***/ /*** ***/ /**********************************************************************/ /* The following criteria were used to select a Pseudo-Random Number Generator: - EASILY cryptanalyzed (when used in a SIMPLE stream cipher), - simple to program, - single bit output, - predictable period, - "key space" close to 2**32 per generator. The rationale for the first criteria is to present a SINGLE challenge to cryptanalysis: the very FROGBIT algorithm. We selected the "Linear Feedback Shift Register" (LFSR) generator (also known as the Tausworthe generator). We use pairs of independent LFSR generators to generate the bit pairs needed by the Frogbit algorithm. For purpose of programming, here are a few simple facts about the LFSR generator: i) the single parameter of a LFSR generator is a binary number representing a "polynomial"; ii) the "degree" of this polynomial is the rank of the highest bit of this number; iii) the polynomial must be "irreductible", a property analogue to the primality of numbers, but based on "polynomial arithmetic", iv) the degree of the polynomial must be a "Marsenne prime number" (p such that 2**p-1 is prime), that is 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, and v) the state of the generator is a number strictly between 0 and 2**degree. Briefly, our design allows any irreductible polynomial of degree up to 31 (the 20 polynomials must be of the same degree). An extra benefit of the LFSR is the ability to let the user customize the generator. This feature is included in this program in order to provide another variable for cryptanalysis purposes. Essentially, we allow the "initial secret key file" to specify the degree, and the 20 polynomials (actually, the program uses the largest polynomial not exceeding the specified value). The default polynomials are the 20 largest irreductible polynomials of degree 31. */ /*--------------------------------------------------------------------*/ /*--------- the design parameters of the 10 LSFR generators ----------*/ int degree=31; unsigned long poly[10][2]= #define DEFAULT_POLYGONS \ {{0xA43F6A87,0x85A308A7},{0x931989F7,0x8370732D} \ /*3.243F6A88 85A308D3 13198A2E 03707344 */ \ ,{0xA4093815,0xA99F31D1},{0x882EFA97,0xEC4E6C63} \ /* A4093822 299F31D0 082EFA98 EC4E6C89 */ \ ,{0xC52821B5,0xB8D0135D},{0xBE54668B,0xB4E90C4B} \ /* 452821E6 38D01377 BE5466CF 34E90C6C */ \ ,{0xC0AC2993,0xC97C50A9},{0xBF84D5A1,0xB54708F7} \ /* C0AC29B7 C97C50DD 3F84D5B5 B5470917 */ \ ,{0x9216D5CF,0x8979FAF1},{0xD1310BA1,0x98DFB581}}; \ /* 9216D5D9 8979FB1B D1310BA6 98DFB5AC */ DEFAULT_POLYGONS /*--------------------------------------------------------------------*/ /*-------------------- the LSFR generator program --------------------*/ bit get_PR_bit(ind_t ind,int ik) { /* parity of each byte value */ static const unsigned char parity[1<>1) |(((unsigned long)return_value)<<(degree-1)); return return_value; } /*--------------------------------------------------------------------*/ /*-- the theoretic rules specific to the state of the LSFR generator -*/ void adjust_prng_state(void) { int i; for (i=0;i<10*2;i++) { next[i/2][i%2]&=(1UL<1) degree=atoi(argv[1]); /*RULE*//* the degree of the polynomials is a Marsenne prime number between 13 and 31 inclusive */ if ((degree!=13)&&(degree!=17)&&(degree!=19)) degree=31; prepare_irreductibles(); cur_poly=(1L<(i+2)) cur_poly=strtoul(argv[i+2],NULL,0); for(;;) { /*RULE*//* the same degree applies to every polynomials */ /*RULE*//* an irreductible polynomial has term x**0 to 1 */ cur_poly &= (1L<=i) break; } cur_poly-=2; /* try another one */ } poly[i/2][i%2]=cur_poly; cur_poly-=2; } } /*--------------------------------------------------------------------*/ /* write the LSFR design to the final file (if not the default design)*/ /**/void print_prng_design(FILE *fp) /**/{ /**/ static const unsigned long def_poly[10][2]=DEFAULT_POLYGONS /**/ int i; /**/ for (i=0;i<10*2;i++) /**/ if (poly[i/2][i%2]!=def_poly[i/2][i%2]) /**/ break; /**/ if ((i<10*2)||(degree!=31)||verbose_flag) /**/ { /**/ fprintf(fp,"{ PRNG design parameters } %d",degree); /**/ for (i=0;i<10;i++) /**/ { /**/ fprintf(fp," 0x%" L "X 0x%" L "X",poly[i][0],poly[i][1]); /**/ if (0==((i+2)%3)) fprintf(fp,"\n"); /**/ } /**/ fprintf(fp,"\n"); /**/ } /**/} /**********************************************************************/ /*** ***/ /*** polynomial arithmetic ***/ /*** ***/ /**********************************************************************/ /*--------------------------------------------------------------------*/ /*-------------------- polynomial multiplication ---------------------*/ /**/unsigned long mult_poly(unsigned long a, unsigned long b) /**/{ /**/ unsigned long r=0; /**/ unsigned long i; /**/ for (i=1;i<=b;i<<=1) /**/ { /**/ if (b&i) /**/ r^=a; /**/ a<<=1; /**/ } /**/ return r; /**/} /*--------------------------------------------------------------------*/ /*----------------------- polynomial division ------------------------*/ /**/unsigned long div_poly( unsigned long div_end /**/ , unsigned long div_or /**/ , unsigned long *remainder) /**/{ /**/ int m_end=-1; /**/ int m_or=-1; /**/ unsigned long r=0; /**/ unsigned long rem=div_end; /**/ int i; /**/ for (i=0;i<(CHAR_BIT*sizeof(unsigned long));i++) /**/ { /**/ if (div_end&(1L<=m_or;m_end--) /**/ { /**/ if (rem&(1<= MAX) /**/ break; /**/ if (ip&1) irreductible[INDICE(ip)] = 0; /**/ } /**/ nb_ushort_irreductibles = 1; /**/ for (i=0;i1) /**/ for (i=0;i= n) /**/ break; /**/ /**/ div_poly(n,all_ushort_irreductibles[i],&rem); /**/ if (0 == rem) /**/ return 0; /**/ } /**/ return 1; /**/} /*--------------------------------------------------------------------*/ /*----------------------------- the end ------------------------------*/