Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to encrypt files using many prime numbers Part 4 of 4 Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
A proposed new algorithm 25-Oct-04
Category
Algorithm
Language
CBuilder All Versions
Views
355
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
Nemitz, Vernon
Reference URL:
			1   // The function processes one byte at a time only because files are
2   // measured in bytes.  Later, this might be modified to handle 32-bit
3   // or even 64-bit quantities, in which case the ModType and ModData
4   // arrays must be adjusted, and some tricky end-of-file stuff will be
5   // needed, too.
6   U_08 PseudoRandomize(U_08 uc)
7   { static U_08 ch, sv, em, mn, kp; // Static variables speed a function
8     static S_32 w, x, y, z;        // up by not needing to be recreated/
9     static U_32 dat;     // destroyed every time the function is called.
10  
11    w = Divide(RandomSkip, 2);            // get a 2-bit number (0 to 3)
12    if(w == 3)        // Prepare to convert 3 to 1  -- want w to be ONLY
13                // for 0, 1 or 2 skips, averaging 1 (makes actually-used
14      w = 1;                       // cryptioning data less predictable)
15    kp = uc;            // Keep the value-to-randomize for the following
16                                                        // do/while loop
17    do     // DO-LOOP PURPOSE: pseudorandomly waste cryptioning-numbers;
18                                     // w is a tiny internal Skip Number
19    { uc = kp;        // Restore initial value of data-to-affect if this
20                                                      // DO-loop repeats
21      x = Divide(ModCounter, 2) + 1;  // Get a 2-bit number (0 to 3) and
22                                           // convert it to range 1 to 4
23      /* Now we reach the heart of the algorithm.  Basically, we will
24      use ModCounter and Divide() to decide how many modifications will
25      be made to the current byte, from two to five.  (If that seems
26      strange because of above x having range 1 to 4, remember that ZERO
27      is a counting value and will be used here, to access the first
28      ModType and ModData array elements.  That is, counting both Zero
29      and One represents two iterations.)  So two-to-five pseudo-random
30      codes will be quantified by ModCounter.  Each of those codes will
31      be generated by sending TypeSetter to Divide() for a 3-bit result,
32      which will represent one of eight possible modifications to the
33      data at uc.  These codes will be saved in the ModType array.
34      Also, of course, more data is required DURING a modification, to
35      actually cause the modification, and so LoadMaster will be sent to
36      Divide() to obtain a 16-bit number.  This number will be used as
37      an index into the main WorkRegion/array of 1K to 64K ScratchPads
38      (65536 fits in 16 bits).  The selected ScratchPad is sent to
39      Divide() for a byte of modification data, which will be saved in
40      the ModData array.  Note that depending on Encryption or
41      Decryption, the data arrays are filled either first-to-last or
42      last-to-first.  Remember, CRYPTION is a NON-COMMUTATIVE process,
43      so each Decryption step must be exactly the reverse of an
44      Encryption step.  Thus the ModType and ModData arrays:  All the
45      info needed to Encrypt or Decrypt a single byte is GATHERED in the
46      same order, but STORED in opposite orders (based on WhichWay
47      info).  Then data can be plucked from the arrays in first-to-last
48      order, but because of the way it was stored, it will be USED in
49      the correct order for the chosen Algorithm.  There is one slight
50      complication, in that different fractions of the arrays are used,
51      depending on ModCounter:  The last-to-first sequence-of-array-
52      access has to be adjusted whenever fewer-than-five Modifications
53      are done. */
54      for(y=x,// Copy number of modifications, zero-based counting (note
55             // comma operator) the adjustment to x is necessary because
56                                     // the arrays start at element zero
57          z=min(WhichWay[0],x);    // Get initial (first or last) access
58                                 // value for ModType and ModData arrays
59             // Note: Since WhichWay[0] will be either 0 or 4, the min()
60              // macro ensures the correct initial z for the ModType and
61              // ModData arrays (range from 0 to 4).  Example: if x is 2
62               // (actually meaning 3 Modifications), then z is set here
63                // to either zero (Encryption value of WhichWay[0]) or 2
64                                             // (when WhichWay[0] is 4).
65          y>=0;         // Check for ending of this gather-mod-data loop
66                                          // (in Example, y starts at 2)
67          z+=WhichWay[1], // modify by +1 or -1, depending on Encryption
68                                              // or Decryption Algorithm
69                       // in Example, z is sequence 0, 1, 2 (Encryption)
70                                              // or 2, 1, 0 (Decryption)
71          y--) // (note comma operator above) Loop countdowner.  Example
72                 // y sequence is 2, 1, zero, and -1 -- which terminates
73                                     // loop due to test for y>=0 above.
74      { ModType[z] = (U_08)Divide(TypeSetter, 3);           // Get 3-bit
75                                     // Modification Type, save in array
76        dat = Divide(LoadMaster, 16); // Get a 16-bit number because max
77                                             // value is 64K ScratchPads
78        if(WorkSize)  // WorkSize is zero during the initial part of the
79                                                  // prep work, remember
80          ch = (U_08)Divide(&(WorkRegion[(dat % WorkSize)]), 8);// The %
81                           // (modulus) operation yields real ScratchPad
82        else        // No ScratchPads available yet; and we still need 8
83                                                    // pseudorandom bits
84          ch = (U_08)(dat & 0x000000FF);    // Keep lowest 8 bits of the
85                                                 // 16-bit ScratchPad ID
86        ModData[z] = ch;    // Save the data that will be used to modify
87                                             // the byte in parameter uc
88      }          // At end of loop we have quantity-x of stored Type and
89                                                    // Modification info
90      for(y=0; y<=x; y++)      // x ranges from 1 to 4 here, but 5 loops
91                               // possible since counting starts at zero
92      { ch = ModData[y];// Get Modification Data from just-filled array,
93                                           // for this Modification Step
94                  // Below, (ch % 7) gets the remainder of division-by-7
95                                               // (modulus: zero to six)
96        sv = (U_08)((ch % 7) + 1);  // Some Modification Types only need
97                                                     // values of 1 to 7
98        em = (U_08)(8 - sv);    // The same Modification Types need this
99                                                      // bit-count, also
100       mn = ModType[y];   // Now get Type for current Modification from
101                                                   // appropriate array
102       if(WhichWay[1] > 0)               // Encryption Algorithm chosen
103       { switch(mn)                   // Type Number ranges from 0 to 7
104         { case 0: // About to do a LEFT ROTATION; only 7 possible mods
105                                                  // to original value.
106           case 1:     // (Eight rotations of a byte is full-circle, no
107                                        // affect on data.  Prevented.)
108             uc = (U_08)((uc << sv) + (uc >> em));    // Move some bits
109             // left; this throws the rest away off the left end of the
110                // byte, so we ALSO move the not-yet-thrown bits right,
111                  // thus letting us combine the two sets of moved bits
112             break;
113           case 2:
114           case 3:
115             uc += ch;                // add; allow byte to odometerize
116             break;
117           case 4:
118           case 5:
119             uc -= ch;  // subtract; byte will odometerize as necessary
120             break;
121           case 6:
122           case 7:
123             uc ^= ch;  // modify using Exclusive-OR (flips a few bits)
124         }
125         if(mn & 1)               // if Modification Type 1, 3, 5, or 7
126           uc = (U_08)(~uc);                      // ALSO FLIP ALL BITS
127       }
128       else                              // Decryption Algorithm chosen
129       { if(mn & 1)               // if Modification Type 1, 3, 5, or 7
130           uc = (U_08)(~uc);                     // FIRST FLIP ALL BITS
131         switch(mn)                   // Type Number ranges from 0 to 7
132         { case 0:// About to do a RIGHT ROTATION; only 7 possible mods
133                                                  // to original value.
134           case 1:        // (Eight rotations of a byte is full-circle,
135                                     // no affect on data.  Prevented.)
136             uc = (U_08)((uc >> sv) + (uc << em));    // Move some bits
137               // right; this throws the rest away off the right end of
138             // the byte, so we ALSO move the not-yet-thrown bits left,
139                  // thus letting us combine the two sets of moved bits
140             break;
141           case 2:
142           case 3:
143             uc -= ch;  // subtract; byte will odometerize as necessary
144             break;
145           case 4:
146           case 5:
147             uc += ch;                // add; allow byte to odometerize
148             break;
149           case 6:
150           case 7:
151             uc ^= ch;  // modify using Exclusive-OR (flips a few bits)
152     } } }
153   } while(--w >= 0); // Immediate exit if w was 0, or repeat loop once
154                                    // or twice (AVERAGE of one repeat)
155   return(uc);  // Original value now scrambled two-to-five times, each
156     // time being one of eight ways, and numbers causing those changes
157 }; // here-and-now were not necessarily obtained as consecutive to the
158                 // numbers that caused changes during the LAST call to
159                                                   // PseudoRandomize()
160 
161 
162 /* About the KeyToPrimes() function
163 Uses the already-loaded KeyFile data in ucMemBlk1, along with
164 "fetched", to gather anywhere from 1K to 64K primes into the work area
165 at ucMemBlk2.  Two groups of primes will be loaded.  The first group
166 consists of only 4 primes, which are used for overall control of the
167 CRYPTION process.  These 4 primes will be pulled using those 90
168 different bytes, located at the start of ucMemBlk1, that were found/
169 saved when giving the key file a minimal test for randomness.  All we
170 need are 16 bytes, for 4 values of N in the Index to the primes -- but
171 we will actually use 32, to increase the randomness of those values.
172 These control primes must pass a special test, to ensure that the
173 reciprocal of each has a "half-period" of at least 100,000 digits.
174 The program will abort if it can't find 4 such primes using those 90
175 "random" bytes.  But that is expected to be a fairly low-probability
176 event, and if it happens, it is simple enough to choose a different
177 key file.  The second group of primes gathered will depend on
178 "fetched", which is basically the size of the key file, up to roughly
179 half of a megabyte (if no duplicate primes then about 524288 bytes
180 would suffice).  Eight bytes at a time will be pulled from the key
181 file, to be used to create an N to obtain one one prime for a
182 scratchpad in ucMemBlk2.  The miminum allowed key file size is 8300
183 bytes, so the "minimum" number of primes used for CRYPTION will be 1K
184 (loads quickly, and weeded-out duplicates will reduce that quantity).
185 The maximum is 64K.  In-between those quantities, the size of the Key
186 File will determine the security of the Message(s).  AND, the tail-end
187 of the Key File data is reserved, to allow ANOTHER replacement of the
188 four Control Primes, after the main prime-key-array has been gathered,
189 and prior to beginning any scrambling operations on the Message(s).
190 The only difference the file size makes, with respect to the actual
191 execution of the CRYPTION process to affect files, is the preparatory
192 time taken to load the primes (which can be minimized if the \PRIMES
193 directory is located on a large RAM disk, although some special
194 sorting is going to be done to more efficiently extract the primes
195 from COMPRESS.PRM).  But that is the only price to pay for greater
196 security.  In addition to specifying a thousand or more N-values for
197 selecting primes, a third group of numbers will be entirely generated
198 by one of the first 4 control primes.  This group will be equal in
199 quantity to the group loaded according to "fetched"; they will be the
200 dividends into which the scratchpad-primes are initially divided (no
201 reciprocals here, unless pseudorandomly happens!).  Finally, in
202 comparison to other and more standard encryption techniques, in which
203 the Key is described as being "56-bit" or "128-bit" or even
204 "2048-bit", the MINIMUM Key here is (if no duplicate primes)
205 65536-bit. */
206 S_32 KeyToPrimes(void)
207 { U_08 uc, *ucp2 = ucMemBlk1; // Want a pointer with which to walk the
208                                                         // data buffer
209   S_32 a, b, c, d, x=-4, y=0, z=1;
210   U_32 test, hold;
211                     // below, this block for first four control-primes
212   is = (U_32 *)ucMemBlk4;//Initialize Sorting and Prime Index pointers
213   status = 200;         // for "Gathering Control Primes" progress bar
214   InvalidateRect(hwnd, &rect, 0);           // make window update-able
215   PostMessage(hwnd, WM_PAINT, 0, 0);        // show blank progress bar
216   if(ProcessMessages())           // process ALL messages in the queue
217     return(CRP_WM_QUIT);                          // assume user abort
218     // Below, if had 90 "random" bytes from ucp2[0] to [89], then last
219                                          // 64-bit data starts at [82]
220   test = 0;
221   while((z == 1) && (y < 83))      // Prepare to walk "random" numbers
222                                            // grouping for values of N
223   { for(a=0; ((a<4)&&(y<83)); a++, y++)
224     { uc = *ucp2++;              // fetch a byte and increment pointer
225       uc = PseudoRandomize(uc);       // "AFFECT" this byte, making it
226                                             // somewhat more "random".
227 #ifdef PROCESSOR_ENDIAN_TYPE_LITTLE
228       ((U_08 *)(&test))[a] = uc;  // Save the byte as part of a 32-bit
229                                                              // number
230 #endif
231 #ifdef PROCESSOR_ENDIAN_TYPE_BIG
232       ((U_08 *)(&test))[(3-a)] = uc;     // save the byte as part of a
233                                                       // 32-bit number
234 #endif
235       uc = *ucp2++;        // fetch another byte and increment pointer
236       uc = PseudoRandomize(uc);       // "AFFECT" this byte, making it
237       // somewhat more "random".  Note that in WorkAreaInit(),
238       // initializations of LoadMaster, ModCounter, TypeSetter, and
239       // RandomSkip ScratchPads were done just so these calls to
240       // PseudoRandomize will work while using the KeyFile here to set
241       // those ScratchPads!  This makes those initializations VERY
242       // temporary!  Below, by taking the address of a variable and
243       // using that address as an array-pointer, we can set any number
244       // of bytes without referencing subunits of the variable (say a
245       // struct).  HOWEVER, the order in which the bytes are put
246       // together, to make a 32-bit number, is a sure sign of a
247       // potential "Big-Endian/Little-Endian" conflict.  BEWARE!
248 #ifdef PROCESSOR_ENDIAN_TYPE_LITTLE
249       ((U_08 *)(&test))[a] |= uc;// OR-combine with last byte, as part
250                                                  // of a 32-bit number
251 #endif
252 #ifdef PROCESSOR_ENDIAN_TYPE_BIG
253       ((U_08 *)(&test))[(3-a)] |= uc; // OR-combine with last byte, as
254                                             // part of a 32-bit number
255 #endif // note using OR to combine bits to reduce chance of zero total
256     }                           // loop for 4 bytes of a 32-bit number
257     IndexToPrime(&test); // use Index to replace random N with a Prime
258       // Next, can't have half-period of 100,000 if Prime is less than
259                                                             // 200,000
260     if(test > 200000)
261     { WorkRegion[0].dvd = WorkRegion[0].dvs = test; // Copy test-Prime
262                                           // to tmp dividend & divisor
263       WorkRegion[0].dvd--;                      // set dividend to P-1
264       if(0xFFFFFFFF != Divide(&WorkRegion[0], 100020)) // Seek 100,020
265                                                   // pseudorandom bits
266       { status += 25;//225, 250, 275, 200
267         if(status == 300)        // if got here then prime passed test
268           status = 299;// ensure Status Message Text remains the same!
269         InvalidateRect(hwnd, &rect, 0);     // make window update-able
270         PostMessage(hwnd, WM_PAINT, 0, 0);// Increment progress bar in
271                                                       // four sections
272         if(ProcessMessages())     // process ALL messages in the queue
273           return(CRP_WM_QUIT);                    // assume user abort
274         WorkRegion[x] = WorkRegion[0];  // Copy both Prime/Divisor and
275                                          // current Remainder/Dividend
276         // Note: Above test done with WorkRegion[0] to avoid affecting
277         // default values of LoadMaster, ModCounter, TypeSetter, and
278         // RandomSkip until we know that the new values pass the test
279         x++; // LoadMaster is set when x=-4; increment for ModCounter,
280                                           // TypeSetter and RandomSkip
281         if(x == 0) // When finished replacing the defaults of all four
282                                            // critical Control Primes,
283           z = 0;      // set flag loop-exit; only other way is to fail
284                                    // 80-odd attempts to set the four.
285       }
286       else   // bad prime! Had half-PERIOD of less than 100,000 digits
287                                                         // in Base Two
288       { y -= 7;     // Back up to re-use last 7 of 8 "random" bytes of
289                  // those 90 (NOTE that when these are again passed to
290         ucp2 -= 7;    // PseudoRandomize(), very different results are
291     } }                                                     // likely.
292     else         // bad prime!  (must be larger than 200,000 to have a
293                                              // half-PERIOD of 100,000
294     { y -= 7; // Back up to re-use last 7 of 8 "random" bytes of those
295     // 90 (NOTE that when these are again passed to PseudoRandomize(),
296       ucp2 -= 7;                 // very different results are likely.
297     }
298   }
299   if(z == 1)                   // did not find four acceptable primes?
300   { MessageBox(NULL, "QUITTING! Key File (randomly!) didn't contain "
301                      "suitable data for picking one or\nmore of 4 "
302                      "critical Control Primes.  (Very rare error -- "
303                      "use another Key File)",
304                      "ERROR", MB_OK | MB_ICONSTOP);
305                         // This is indeed expected to be VERY rare....
306     return(CRP_ERR_BD);                // using 6 as code for Bad Data
307   }                         // NEXT UP: Fill the main WorkRegion area!
308   lim = (S_32 *)(ucMemBlk1 + fetched - 108);
309   z = (fetched - 108) >> 3;                // Key File size divided by
310                                                   // 8-bytes-per-prime
311   if(z > 65536)
312     z = 65536;   // Fix upper limit.  This is kind of arbitrary.  Just
313     // need more allocated memory for processing the Key File, and for
314      // scratchpads, to allow an even bigger Key.  Of course, a bigger
315                               // Key will also take longer to load....
316   y = z / 50;           // number of primes per progress-bar increment
317   b = y;              // set so initial display of progress bar occurs
318   c = prmbar = 0;                        // initialize the bar counter
319   for(status=300, x=0; ((x<z)&&(ucp1<(U_08*)lim)); x++) // For desired
320                                  // primes, depending on Key File size
321   { if(b == y)                 // if time for a progress bar increment
322     { InvalidateRect(hwnd, &rect, 0);       // make window update-able
323       PostMessage(hwnd, WM_PAINT, 0, 0);  // Progress bar grows, based
324                                                           // on status
325       if(ProcessMessages())       // process ALL messages in the queue
326         return(CRP_WM_QUIT); // Assume user abort if ProcessMessages()
327                                                    // returned nonzero
328       b = 0;       // reset counter for next increment of progress bar
329       status += 2;          // this is what the next increment will be
330       if(status >= 400)   // ensure progress bar doesn't grow too much
331         status = 399;
332     }
333     // Below, as previously indicated elsewhere, we are about to
334     // SCRAMBLE bytes taken from the Key File, before using them to
335     // select prime numbers from COMPRESS.PRM.  Here is a bit of extra
336     // sneakiness, where we semirandomly specify either Encryption or
337     // Decryption scrambling.
338     uc = (U_08)Divide(TypeSetter, 1);    // Get one bit as Encryption/
339                                                      //Decryption flag
340     if(uc == 1)
341     { WhichWay[0] = 0;                 // Set for Encryption Algorithm
342       WhichWay[1] = 1;                 // Set for Encryption Algorithm
343     }
344     else
345     { WhichWay[0] = 4;                 // Set for Decryption Algorithm
346       WhichWay[1] = -1;                // Set for Decryption Algorithm
347     }
348     for(a=0; (a<4); a++)    // For 4 pairs of bytes per 32-bit number,
349                                         // using current E/D algorithm
350     { uc = *ucp1++;                  // fetch a byte from the Key File
351       uc = PseudoRandomize(uc); // Make it more "random".  Notice that
352       // inside the PseudoRandomize() function is:
353       // WorkRegion[(dat %= WorkSize)]  --which lets us start using
354       // the main ScratchPad array to scramble numbers as soon as even
355       // one ScratchPad has been prepared.
356   // Below, assemble the value  N  that will be used to fetch a prime;
357                                            // also initialize dividend
358 #ifdef PROCESSOR_ENDIAN_TYPE_LITTLE
359       ((U_08 *)(&WorkRegion[x].dvs))[a] = uc;//Save as part of divisor
360                                                 // for this ScratchPad
361       uc = (U_08)Divide(ModCounter, 8);             // get 8 more bits
362       ((U_08 *)(&WorkRegion[x].dvd))[a] = uc;       // Save as part of
363                                        // dividend for this ScratchPad
364 #endif
365 #ifdef PROCESSOR_ENDIAN_TYPE_BIG
366       ((U_08 *)(&WorkRegion[x].dvs))[(3-a)] = uc;   // Save as part of
367                                         // divisor for this ScratchPad
368       uc = (U_08)Divide(ModCounter, 8);             // get 8 more bits
369       ((U_08 *)(&WorkRegion[x].dvd))[(3-a)] = uc;   // Save as part of
370                                        // dividend for this ScratchPad
371 #endif
372       uc = *ucp1++;            // fetch another byte from the Key File
373       uc = PseudoRandomize(uc);              // Make it more "random".
374       // Below, finish assembling the value  N  and dividend, using OR
375 #ifdef PROCESSOR_ENDIAN_TYPE_LITTLE
376       ((U_08 *)(&WorkRegion[x].dvs))[a] |= uc;      // Save as part of
377                                         // divisor for this ScratchPad
378       uc = (U_08)Divide(ModCounter, 8);             // get 8 more bits
379       ((U_08 *)(&WorkRegion[x].dvd))[a] |= uc;      // Save as part of
380                                        // dividend for this ScratchPad
381 #endif // note using OR to combine bits to reduce chance of zero total
382 #ifdef PROCESSOR_ENDIAN_TYPE_BIG
383       ((U_08 *)(&WorkRegion[x].dvs))[(3-a)] |= uc;  // Save as part of
384                                         // divisor for this ScratchPad
385       uc = (U_08)Divide(ModCounter, 8);             // get 8 more bits
386       ((U_08 *)(&WorkRegion[x].dvd))[(3-a)] |= uc;  // Save as part of
387                                        // dividend for this ScratchPad
388 #endif // note using OR to combine bits to reduce chance of zero total
389     }
390     big = WorkRegion[x].dvs;                                  // get N
391     if(big < 256)
392       big += 257;      // Ignore the lowest primes as having too-short
393                                                             // periods
394     while(big > 203280221)   // too big a value for finding Nth prime?
395       big >>= 1;     // HALVE the value (ignore any odd-bit remainder)
396     WorkRegion[x].dvs = big;           // put possibly-modified N back
397     if(status <= 302)// For first 1/50 of scratchpads only, duplicates
398                                                             // allowed
399     { IndexToPrime(&WorkRegion[x].dvs); // Use Index to convert random
400                                    // 32-bit number to a Prime divisor
401       prmbar = WorkSize++;    // This ScratchPad is now ready for use!
402          // Note that the first Divide() that is called to use it will
403       b++; // cause its .dvd value to be repeatedly halved until it is
404     }            // smaller than the .dvs value (the random .dvd value
405                              // essentially becomes even more random).
406     else     // SAVE IN ucMemBlk4 for sorting!  Two mutually exclusive
407     {   // goals are (1) to access 49/50 of all the desired primes, in
408         // COMPRESS.PRM as fast as possible (in order), and (2) retain
409          // ALL the randomness associated with the first 1/50.  It can
410                                                            // be done!
411       if(!c)                                           // not yet set?
412         c = x;                                  // SAVE THIS FOR LATER
413       test = big / 194;            // compute a proportionate position
414                                     // (203,280,221/1,050,000 = 193.6)
415       if(!is[++test]) // Bump to avoid Slot Zero in ucMemBlk4 array of
416                                         // 4,200,000 bytes; available?
417       { is[test] = big;                                      // save N
418         goto bmp;    // Despite being reviled,  goto  is sometimes the
419       }  // best tool available.  GO TO incrementation of progress bar
420               // ONLY when NO duplicate N is involved.  BASIC IDEA IS:
421           // ucMemBlk4 HAS 1,050,000 SLOTS FOR < 65,000 RANDOM VALUES;
422         //  NOTE THE ABOVE COMBINING  |=  PUSHES AVERAGE RANDOM NUMBER
423                                                       // TO UPPER HALF
424       else // slot full!
425       { for(a=d=(S_32)test; (is[a]&&(a>1)); a--);    // Find open slot
426                                    // preceding proportionate location
427         for(; (is[d]&&(d<1049999)); d++);  // Find open slot following
428                                              // proportionate location
429         for(ip=&is[a]; ((big!=*ip)&&(ip<&is[d])); ip++);
430                                // seek duplicate N if previously saved
431         if(big != *ip)                      // for nonduplicate N only
432         { if(is[a] ||        // if no open slot here, OR "here" is the
433              ((((S_32)test - a) >= (d - (S_32)test)) &&// farther slot
434                                      // from proportional position AND
435               !is[d]))                       // the other slot is open
436           { while(big < (hold = is[--d]))       // compare current and
437                                                  // previously-saved N
438               is[(d+1)] = hold;  // Move higher values upward in array
439                                                            // of slots
440             is[++d] = big;      // save current value in correct place
441           }         // Since slots always outnumber the random values,
442                                  // guaranteed to find one unoccupied,
443           else //  and in this case the other side of the proportional
444                                               // position is available
445           { while((big > (hold = is[++a])) && hold) // compare current
446                                                     // & prior-saved N
447               is[(a-1)] = hold;  // move lower values (NOT 0) downward
448                                                   // in array of slots
449             is[--a] = big;      // save current value in correct place
450           } // now the ucMemBlk4 buffer is becoming an array of sorted
451                                      // values interspersed with Zeros
452 bmp:      if((x & 1) == 0)           // One bump of prmbar counter for
453                                                 // every-other N-value
454           { prmbar++;            // bump count of loaded primes (LIE!)
455             b++;          // bump counter responsible for progress bar
456         } }
457         else
458           x--;                           // don't count this duplicate
459   } } }
460   a = big = 0;                  // set some counters to start of array
461   while(a < 1050000)                        // walk the array of slots
462   { if(0 < (hold = is[a++]))                    // get/test each value
463     { is[(a-1)] = 0;      // erase the slot from which value was taken
464       is[big++] = hold;    // Condense values so no interspersed Zeros
465                                                              // remain
466   } }       // now all the Zeros in the array FOLLOW the sorted values
467   ip = (U_32 *)(ucMemBlk4 + 700000);      // This section of the array
468                                              // guaranteed to be empty
469   for(a=0; a<(S_32)big; a++)             // walk the sorted  N  values
470   { test = is[a];                                           // get one
471     IndexToPrime(&test);   // Find Nth prime, steadily forward through
472                                                        // COMPRESS.PRM
473     ip[a] = test;                                    // save the prime
474     if((a & 1) == 1)                          // for every-other value
475     { prmbar++;          // one bump of prmbar counter (lie some more)
476       if(++b == y)             // if time for a progress bar increment
477       { InvalidateRect(hwnd, &rect, 0);     // make window update-able
478         PostMessage(hwnd, WM_PAINT, 0, 0);      // Progress bar grows,
479                                                     // based on status
480         if(ProcessMessages())     // process ALL messages in the queue
481           return(CRP_WM_QUIT);                 // Assume user abort if
482                                  // ProcessMessages() returned nonzero
483         b = 0;     // reset counter for next increment of progress bar
484         status += 2;        // this is what the next increment will be
485         if(status >= 400) // ensure progress bar doesn't grow too much
486           status = 399;
487   } } }
488       // LAST STEP: Put the primes into the WorkRegion[].dvs variables
489                                               // AS IF NO SORTING DONE
490   big--;        // decrement to highest-used slot in array of N-values
491   for(WorkSize=c; WorkSize<x; WorkSize++)
492   { test = WorkRegion[WorkSize].dvs;
493     a = 0;                            // location of lowest N in array
494     d = (S_32)big;                   // location of highest N in array
495     c = d >> 1;    // Prepare to do a binary search from middle of the
496                                                               // array
497     while (a < d)
498     { if(test < is[c])
499         d = c - 1;    // Set new upper bound to possible correct array
500                                                                // item
501       else if(test > is[c])
502         a = c + 1;//set new lower bound to possible correct array item
503       else
504         break; // Well, well,  test  just happened to exactly match an
505                                                               // item!
506       c = ((d - a) >> 1) + a;  // Get new middle between a and d; (may
507           // equal untested a if d-a=1, but next loop then finds it or
508     }                                                  // makes a=c=d)
509     WorkRegion[WorkSize].dvs = ip[c];    // Use the array of primes to
510                                                           // replace N
511   }
512   x=-4, y=0, z=1; // AND NOW TO REPLACE THE CONTROL PRIMES AGAIN!
513   // This code block works with 108 BYTES reserved at the end of the
514   // block of Key File data associated with the  fetched  variable,
515   // much like the 90 bytes previously used.
516   test = 0;
517   { struct scratchpad sp;   // One cool thing about C is that wherever
518           // there is a Left Brace, it is allowed to place a variable-
519      // declaration there.  This can be handy to ensure that variables
520     // needed for a particular block of code (until the matching Right
521      // Brace) are available.  BUT doing this also has a price.  These
522      // variables are always placed in an area known as The Stack, and
523      // not only does it take extra time to put them there (and remove
524             // them when done), accessing them can also be slower than
525            // accessing global memory variables.  More, such variable-
526     //declarations surrounded by code are not so obvious to the casual
527        // eye as declarations at the start of a function (or at top of
528       // prgram, global).  It can sometimes be annoying to try to find
529         // them.  THIS declaration is the only one of its kind in this
530            // program, partly so this comment could be written for the
531      // benefit of a novice, and partly because this block of code was
532       // copied from above, where  WorkRegion[0]  was specified.  THEN
533      // WorkRegion[0]  was unoccupied and available for temporary use;
534      // NOW it has been assigned a value that we want to retain.  So a
535                            // new scratchpad is needed -- so declared!
536     while((z == 1) && (y < 101))   // Prepare to walk "random" numbers
537                                            // grouping for values of N
538     {     // Below, as previously indicated elsewhere, we are about to
539        // SCRAMBLE bytes taken from the Key File, before using them to
540           // select prime numbers from COMPRESS.PRM.  Here is a bit of
541              // extra sneakiness, where we semirandomly specify either
542                                // Encryption or Decryption scrambling.
543       uc = (U_08)Divide(TypeSetter, 1);  // Get one bit as Encryption/
544                                                      //Decryption flag
545       if(uc == 1)
546       { WhichWay[0] = 0;               // Set for Encryption Algorithm
547         WhichWay[1] = 1;               // Set for Encryption Algorithm
548       }
549       else
550       { WhichWay[0] = 4;               // Set for Decryption Algorithm
551         WhichWay[1] = -1;              // Set for Decryption Algorithm
552       }
553       for(a=0; ((a<4)&&(y<83)); a++, y++)
554       { uc = *ucp1++;  // Fetch a byte from the Key File and increment
555                                                             // pointer
556         uc = PseudoRandomize(uc);     // "AFFECT" this byte, making it
557                                             // somewhat more "random".
558 #ifdef PROCESSOR_ENDIAN_TYPE_LITTLE
559         ((U_08 *)(&test))[a] = uc;// Save the byte as part of a 32-bit
560                                                              // number
561 #endif
562 #ifdef PROCESSOR_ENDIAN_TYPE_BIG
563         ((U_08 *)(&test))[(3-a)] = uc;   // save the byte as part of a
564                                                       // 32-bit number
565 #endif
566         uc = *ucp1++;     // Fetch another Key File byte and increment
567                                                             // pointer
568         uc = PseudoRandomize(uc);     // "AFFECT" this byte, making it
569                                             // somewhat more "random".
570           // Below, by taking the address of a variable and using that
571         // address as an array-pointer, we can set any number of bytes
572        // without referencing subunits of the variable (say a struct).
573          // HOWEVER, the order in which the bytes are put together, to
574                 // make a 32-bit number, is a sure sign of a potential
575                       // "Big-Endian/Little-Endian" conflict.  BEWARE!
576 #ifdef PROCESSOR_ENDIAN_TYPE_LITTLE
577         ((U_08 *)(&test))[a] |= uc;   // OR-combine with last byte, as
578                                             // part of a 32-bit number
579 #endif
580 #ifdef PROCESSOR_ENDIAN_TYPE_BIG
581         ((U_08 *)(&test))[(3-a)] |= uc;  // OR-combine with last byte,
582                                          // as part of a 32-bit number
583 #endif // note using OR to combine bits to reduce chance of zero total
584       }                         // loop for 4 bytes of a 32-bit number
585       IndexToPrime(&test);//use Index to replace random N with a Prime
586       // Next, can't have half-period of 100,000 if Prime is less than
587       if(test > 200000)                                     // 200,000
588       { sp.dvd = sp.dvs = test;   // copy test-Prime to tmp dividend &
589                                                             // divisor
590         sp.dvd--;                               // set dividend to P-1
591         if(0xFFFFFFFF != Divide(&sp, 100020))          // Seek 100,020
592                                                   // pseudorandom bits
593         { WorkRegion[x] = sp;   // Copy both Prime/Divisor and current
594                                                  // Remainder/Dividend
595                  // Note: Above test done with temporary  sp  to avoid
596                 // affecting default values of LoadMaster, ModCounter,
597               // TypeSetter, and RandomSkip until we know that the new
598                                                // values pass the test
599           x++;//LoadMaster is set when x=-4; increment for ModCounter,
600                                           // TypeSetter and RandomSkip
601           if(x == 0)//When finished replacing the defaults of all four
602                                            // critical Control Primes,
603             z = 0;// set flag loop-exit; only other way is to fail 100
604         }                                 // attempts to set the four.
605         else // bad prime! Had half-PERIOD of less than 100,000 digits
606                                                         // in Base Two
607         { y -= 7;  // Back up to re-use last 7 of 8 bytes of those 108
608           ucp1 -= 7;      // (NOTE that when these are again passed to
609       } }     // PseudoRandomize(), very different results are likely.
610       else       // bad prime!  (must be larger than 200,000 to have a
611                                              // half-PERIOD of 100,000
612       { y -= 7;    // Back up to re-use last 7 of 8 bytes of those 108
613         ucp1 -= 7;        // (NOTE that when these are again passed to
614       }       // PseudoRandomize(), very different results are likely.
615     }
616     if(z == 1)                 // did not find four acceptable primes?
617     { MessageBox(NULL, "QUITTING! Key File didn't contain suitable "
618                        "data for picking one or\nmore of 4 critical "
619                        "Control Primes.  (Very rare error -- use "
620                        "another Key File)",
621                        "ERROR", MB_OK | MB_ICONSTOP);
622                         // This is indeed expected to be VERY rare....
623       return(CRP_ERR_BD);     // using 6 as code for Bad Data
624   } }
625   InvalidateRect(hwnd, &rect, 0);           // make window update-able
626   PostMessage(hwnd, WM_PAINT, 0, 0);  // Progress bar ends (show final
627                                             // count of loaded primes)
628   if(ProcessMessages())           // process ALL messages in the queue
629     return(CRP_WM_QUIT);     // Sssume user abort if ProcessMessages()
630                                                    // returned nonzero
631   return(0);                                              // no error!
632 };
633 /*SPECIAL NOTE REGARDING THE LITTLE-ENDIAN AND BIG-ENDIAN CONTROVERSY:
634   The smallest unit of information is the bit, and the commonest next-
635        small unit is the byte (a group of 8 bits).  Computer memory is
636    typically organized as a huge array of bytes; for example, a 32-bit
637 processor can "address" an array of 4,294,967,296 memory locations.  A
638     minor dilemma arises in that to GIVE a 32-bit processor 32 bits of
639     data, four separate 8-bit bytes are required.  The original author
640  of this document personally thinks that every memory address accessed
641       by a 32-bit processor should have 32 bits of data sitting there,
642   instead of 8, but that's a simplistic and controversial way to solve
643    the "endian" controversy.  So, with the standard of only 8 bits per
644         address, the needed four bytes typically come from 4 adjacent/
645         consecutive addresses in the memory.  One will hold the "Least
646  Significant" 8 bits -- values that can only range from 0 to 255.  And
647  one byte will hold the "Most Significant" 8 bits -- values that range
648   from 16,777,216 to 1,073,741,824 (not counting the possibly negative
649     biggest bit) -- but which?  More specifically, imagine four memory
650 address numbers 10,000 through 10,003 (computers always start counting
651  from Zero).  Will address 10,000 hold the Least Significant Byte, and
652   10,003 hold the Most Significant Byte -- the Little-Endian way -- or
653     vice-versa, the Big-Endian way?  Because both ways have some logic
654 behind them, both ways have been implemented in the computer industry,
655                                   despite being mutually incompatible.
656        What are those logical arguments, you ask?  Well, Little-Endian
657 supporters like the simple match-up between data-magnitude and memory-
658  address.  Memory address 10,000, the first and least-magnitude of the
659   four addresses, would hold the Least Significant Byte, as previously
660   described.  On the other hand, the Big-Endian supporters look at the
661  CONTENTS of the memory in sequence, and for them, it makes more sense
662      for the Most Significant Byte to be first.  Here is an example of
663               that; consider the number 1 Billion in 32 binary digits:
664     00111011100110101100101000000000.  This is the conventional way to
665     represent a large-ish number in Base Two.  Broken into a series of
666  bytes, the same data is 00111011 10011010 11001010 00000000.  Suppose
667       these bytes were placed into the memory in Little Endian format.
668   Well, if you decided to "read" the contents of that memory in order,
669   then you would end up with the following sequence: 00000000 11001010
670   10011010 00111011.  It's bad enough that binary is not easy to read,
671   but now sections of our 1 Billion are backwards (even while the bits
672  in the individual bytes are still "forwards"!)!  Thus the Big-Endians
673       choose to put the Most Significant Byte in the Least Significant
674                                                        memory address.
675       Heh, if "the convential way to represent a number" was REVERSED,
676           then in common ordinary Base Ten we would write 1 Billion as
677                   000,000,000,1 -- and in binary a similar reversal is
678         00000000010100110101100111011100 -- so that is also a possible
679 solution to the controversy (the Little Endian way of putting sections
680     of the number into memory would be completely consistent).  But is
681      such a change of Convention likely?  NOT, any time soon!  Anyway,
682   regardless of anyone's preferences, certain parts of this program do
683       need to be able to work properly, so that a Message encoded by a
684       Little Endian processor can be correctly decoded by a Big Endian
685        processor (or vice-versa).  And that's the purpose for  #define
686  PROCESSOR_ENDIAN_TYPE_LITTLE  earlier in this program; it lets us use
687  #ifdef  blocks to tell the compiler which sections of code need to be
688     compiled, to ensure that any Message data gets processed properly.
689        Should this program be compiled on a big-endian processor, that
690   #define statement is the ONLY thing in this entire program that must
691 be edited.  (CAUTION -- that claim has not been tested!  Other editing
692                       may be needed if some mistake has been made!) */
693 
694 
695 
696 
697 
698 // HERE is the main function that handles file extensions (including
699 // .CRP), opens files, works with the "Snoopercomputer/Cryptionite"
700 // strings, applies Encrypt/Decrypt algorithms via PseudoRandomize(),
701 // and deletes specified files (including old .CRP files) when done.
702 // Nonzero return values are error codes.
703 // Uses global    struct affect *afflist   --so no parameter needed
704 S_32 AffectFiles(void)
705 { FILE *outfil;          // In order to not delete any files until all
706              // processing is successful, need two FILE pointers here.
707                      // Global dskfil will be used for the input-file.
708   S_32 a, b;
709   U_32 x=0, y, z;
710   char work[60], ext[50];
711 
712   for(y=0, affitem=afflist, affnum=1;   affnum<=affcou;
713       affnum++, affitem=affitem->next)
714   { if(affitem == NULL)
715     { sprintf(tmpstr, "QUITTING! Could not access internal "
716                       "Files-to-Affect List!");
717       MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
718       return(CRP_ERR_LL);   // using 4 as code for Linked-List failure
719     }
720     z = y;                                      // save for comparison
721     y += affitem->length;    // accumulate lengths of files to process
722     if(z > y)                        // total rolled over 4 gigabytes?
723       x++;                                         // carry to 64 bits
724     z = y;
725     y += affitem->skipno;//Also accumulate total wasted randomizations
726                                             // (large skips take time)
727     if(z > y)
728       x++;                         // Carry any rollover to 64 bits --
729                                      // TRY TO KEEP TOTAL WITHIN 100GB
730   }   // Note minor flaw: Total does NOT account for "Snoopercomputer/
731   // Cryptionite" recognition strings.  If completed loop then we know
732      // afflist is in good shape and we can walk it again without fear
733 
734   // Now to divide a 64-bit number by 50, for the progress bar -- we
735   // want result to fit in 32 bits!  (Perhaps I'm just being lazy
736   // here, and should change all the (++x == y) below to 64-bit stuff)
737   // BEST divide in Assembly Language, but cheap compilers often don't
738   // support   asm   stuff, so....
739   if(x >= 50)     // if exceeded 200GB (how likely is this, anyway???)
740     y = 0xFFFFFFFF; // Set one Progress Bar increment after processing
741        // every 4GB, but program will keep running even after Progress
742       // Bar reaches its endpoint, because CRYPTION will try to finish
743                                                   // all assigned work
744   else
745   { y = (y >> 1) + ((x & 1) << 31);        // First divide by two, via
746                                                          // bit-shifts
747     x >>= 1;                   // below, only need to divide by 25 now
748     z = y;                                       // save, just in case
749     y /= 25;
750     if(x > 0)  // most of the time probably won't go farther than this
751     {   // NOTE prior 200GB test, and bit-shift, ensures that x is its
752                                     // own remainder-of-division-by-25
753       x <<= 16;                       // shift to High Half of 32 bits
754       x += (z >> 16);            // Combine with High Half of former y
755                                            // (but make Low Half here)
756       y = (x / 25) << 16; // Get integer quotient and shift it to High
757                                                     // Half of 32 bits
758       x = (x % 25) << 16;  // Get remainder of division-by-25; move to
759                                                // High Half of 32 bits
760       x += (z & 0x0000FFFF);  // Combine remainder with Low Quarter of
761                                               // original 64-bit value
762       y += (x / 25); // Combine shifted quotient with rest of computed
763                                                            // quotient
764   } }
765   for(x=0, status = 400, affitem=afflist, affnum=1;
766       (affnum<=affcou);   affnum++, affitem=affitem->next)
767   { InvalidateRect(hwnd, &rect, 0);         // make window update-able
768     PostMessage(hwnd, WM_PAINT, 0, 0);  // Show progress bar and File-
769                                               // to-Affect Number info
770     if(ProcessMessages())         // process ALL messages in the queue
771       return(CRP_WM_QUIT);                        // assume user abort
772     for(a=affitem->skipno; a>0; a--) // Since skipno is supposed to be
773             // an irregular value, we gain some security by wasting an
774     { PseudoRandomize(0);// irregular quantity of pseudorandomizations
775       if(++x == y)     // NOTE x is NOT reset to zero at start of each
776                                                      // File-to-Affect
777       { status += 2;    // Progress-bar-incrementation could occur any
778                                         // time, since x is constantly
779         if(status >= 500) // incremented with each pseudorandomization
780           status = 499; // make sure status stays within allowed range
781         InvalidateRect(hwnd, &rect, 0);     // make window update-able
782         PostMessage(hwnd, WM_PAINT, 0, 0);   // increment progress bar
783         if(ProcessMessages())     // process ALL messages in the queue
784           return(CRP_WM_QUIT);                    // assume user abort
785         x = 0;        // reset counter for next progress bar increment
786     } }
787     if(affitem->algo == 'E')      // check the Algorithm code for this
788                                                     // particular file
789     { WhichWay[0] = 0;                 // Set for Encryption Algorithm
790       WhichWay[1] = 1;                 // Set for Encryption Algorithm
791     }
792     else
793     { WhichWay[0] = 4;                 // Set for Decryption Algorithm
794       WhichWay[1] = -1;                // Set for Decryption Algorithm
795     }
796     dskfil = fopen(affitem->pathname, "rb");            // Read Binary
797     if(dskfil == NULL)
798     { sprintf(tmpstr, "QUITTING! Could not open File-to-Affect:\n%s",
799               affitem->pathname);
800       MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
801       return(CRP_ERR_OF);    // using 2 as code for Opening File error
802     }
803     sprintf(work, ".\\TMP%d.CRP", affnum); // Create temporary file in
804                                              // executable's directory
805     outfil = fopen(work, "wb");                        // Write Binary
806     if(outfil == NULL)
807     { fclose(dskfil);
808       sprintf(tmpstr,
809               "QUITTING! Could not open Temporary Work File:\n%s",
810               work);
811       MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
812       return(CRP_ERR_OF);    // using 2 as code for Opening File error
813     }
814     ext[0] = '\0';                // initialize a blank file extension
815     ucp1 = ucMemBlk1;    // reset this pointer to start of file buffer
816     z = min(200, affitem->length);  // Set z appropriately, in case of
817                                                     // very short file
818     if(z != fread(ucp1, 1, z, dskfil))    // Get file's start, perhaps
819                                // only a Previously-Affected indicator
820     { sprintf(tmpstr,
821               "QUITTING! Could Not Load Initial Part of File:\n%s",
822               affitem->pathname);
823       MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
824       fclose(dskfil);
825       fclose(outfil);
826       return(CRP_ERR_FR);       // using 3 as code for File Read error
827     }
828       // Below, check to see if file has previously been Affected, and
829                                                  // do stuff if HASN'T
830     if(strncmp((char *)ucp1, "DATA PROTECTED FROM SNOOPERCOMPUTERS "
831                              "WITH CRYPTIONITE:  ", 56))
832     { if(affitem->dotloc > -1)        // Did the file actually have an
833                                    // Extension?  Below, copy it if so
834         strcpy(ext, &(affitem->pathname[(affitem->dotloc + 1)]));
835       sprintf(tmpstr, "DATA PROTECTED FROM SNOOPERCOMPUTERS WITH CRYP"
836                       "TIONITE:  Data Protected From Snoopercomputers"
837                       " With Cryptionite:  The Original File Extensio"
838                       "n is %s.  ", ext);
839                                  // put in main ID string (replace %s)
840       // Purpose of the period after %s is to be a marker indicating
841       // END of File Extension.  The original dotloc identification of
842       // a file extension never includes a period.
843       a = strlen(tmpstr);     // get length of just-constructed string
844       memmove((ucp1 + a), ucp1, z);      // Move the initial file data
845                                               // deeper into ucMemBlk1
846       strncpy((char *)ucp1, tmpstr, a);      // Insert with no string-
847                                                          // terminator
848       z += a;  // get total length to put in outfil after Affecting it
849     }  // Whether had it already, or just added the identifier string,
850                                        // Affecting starts at ucp1[56]
851     strcpy(ext, ".CRP");    // Set to CRYPTION-file extension, even if
852                                                    // already was .CRP
853     ucp1 += 56;       // Pointer arithmetic: skip   DATA PROTECTED ...
854                                                  // (capitalized text)
855     for(a=56; a<(int)z; a++)      // From   Data Protected   to end of
856                                                // loaded start-of-file
857     { *ucp1++ = PseudoRandomize(*ucp1);  // Affect appropriate part of
858                                                  // this block of data
859       if(y < 10000)
860         y = 12000;
861       if(++x == y)     // NOTE x is NOT reset to zero at start of each
862                                                      // File-to-Affect
863       { status += 2; // Since x increments across files, progress-bar-
864                                // incrementation could occur any time.
865         if(status >= 500)
866           status = 499; // make sure status stays within allowed range
867         InvalidateRect(hwnd, &rect, 0);     // make window update-able
868         PostMessage(hwnd, WM_PAINT, 0, 0);   // increment progress bar
869         if(ProcessMessages())     // process ALL messages in the queue
870         { fclose(dskfil);
871           fclose(outfil);
872           return(CRP_WM_QUIT);                    // assume user abort
873         }
874         x = 0;        // reset counter for next progress bar increment
875     } }
876        // Below, check for RESTORED file (well, first part of it might
877                                                    // now be restored)
878     if(!strncmp((char *)ucMemBlk1, "DATA PROTECTED FROM SNOOPERCOMPUT"
879                                    "ERS WITH CRYPTIONITE:  Data Prote"
880                                    "cted From Snoopercomputers With C"
881                                    "ryptionite:  The Original File Ex"
882                                    "tension is ", 143))   // Remember,
883     // Extension in text is followed by a marker-period and two spaces
884     { for(a=143, b=1; ('.'!=(ext[b]=ucMemBlk1[a])); a++, b++);// Fetch
885                                                  // Original Extension
886       // Prior line is self-contained loop, exits after copying period
887                                              // that follows Extension
888       ext[b] = '\0';     // replace marker-period with null terminator
889       ext[0] = '.';//prepend Extension-separator (note b started at 1)
890       if(affitem->dotloc == -1)   // if no Extension in given filename
891         affitem->dotloc = (S_16)strlen(affitem->pathname); // Set this
892                                         // to where it would have been
893       ucp1 = ucMemBlk1 + 145 + strlen(ext);  // Get buffer location of
894                                         // start of original file data
895       // Note about above 145: length up to Original File Extension is
896       // 143, and 3 characters follow it (a period and two spaces), so
897      // one might at first think that the 145 should be 146.  However,
898       // variable ext includes an initial dot that was not part of the
899      // stored Extension and so we have to account for it in the total
900                             // length (most easily by specifying 145).
901       z -= (ucp1 - ucMemBlk1);    // Get length of original data after
902                                         // CRYPTION identifier removed
903       memmove(ucMemBlk1, ucp1, z);  // Remove the CRYPTION identifier;
904         // this is why we sought to load 200 bytes from start of file;
905                                           // whole identifier is there
906     }  // Next line either restores original file extension or sets it
907                                                             // to .CRP
908     strcpy(affitem->newname, affitem->pathname);  // copy current name
909     strcpy(&(affitem->newname[affitem->dotloc]), ext); // Overwrite or
910                                                    // append Extension
911     if(z != fwrite(ucMemBlk1, 1, z, outfil))  // Save the initial data
912                                             // to new (temporary) file
913     { sprintf(tmpstr,
914             "QUITTING! Could Not Save Initial Part of Work-File:\n%s",
915               work);
916       MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
917       fclose(dskfil);
918       fclose(outfil);
919       return(CRP_ERR_FW);      // using 7 as code for File Write error
920     } // Below, check to see if file has previously been Affected, and
921                                                  // do stuff if HASN'T
922     while(!feof(dskfil)) // Main loop to Affect data until end-of-file
923                                                             // reached
924     { z = fread(ucMemBlk1, 1, 524288, dskfil);    // Get huge chunk of
925                                        // file, several whole clusters
926       if((z != 524288) && !feof(dskfil))      // If file not ended and
927                                         // didn't fetch what we wanted
928       { sprintf(tmpstr, "QUITTING! Could Not Load Part of File:\n%s",
929                 affitem->pathname);
930         MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
931         fclose(dskfil);
932         fclose(outfil);
933         return(CRP_ERR_FR);     // using 3 as code for File Read error
934       }
935       ucp1 = ucMemBlk1;                        // reset moving pointer
936       for(a=0; a<(int)z; a++)// From start to end of however-much data
937                                                     // is in ucMemBlk1
938       { *ucp1++ = PseudoRandomize(*ucp1);// Affect appropriate part of
939                                                  // this block of data
940         if(++x == y)   // NOTE x is NOT reset to zero at start of each
941                                                      // File-to-Affect
942         { status += 2;   // Since x increments across files, progress-
943                             // bar-incrementation could occur any time
944           if(status >= 500)
945             status = 499;//make sure status stays within allowed range
946           InvalidateRect(hwnd, &rect, 0);   // make window update-able
947           PostMessage(hwnd, WM_PAINT, 0, 0); // increment progress bar
948           if(ProcessMessages())   // process ALL messages in the queue
949           { fclose(dskfil);
950             fclose(outfil);
951             return(CRP_WM_QUIT);                  // assume user abort
952           }
953           x = 0;      // reset counter for next progress bar increment
954       } }   // loop til half-a-megabyte processed, or tail end of file
955       if(z != fwrite(ucMemBlk1, 1, z, outfil))   // Save the processed
956                                                               // block
957       { sprintf(tmpstr,
958                 "QUITTING! Could Not Save Part of Work-File:\n%s",
959                 work);
960         MessageBox(NULL, tmpstr, "ERROR", MB_OK | MB_ICONSTOP);
961         fclose(dskfil);
962         fclose(outfil);
963         return(CRP_ERR_FW);    // using 7 as code for File Write error
964     } }                           // loop til done Affecting this file
965     fclose(dskfil);                         // Close the current files
966     fclose(outfil);                    // in preparation for next loop
967     rename(work, affitem->newname);  // MUST MOVE/RENAME TMP#.CRP FILE
968    // TO ORIGINAL DIRECTORY NOW.  MUST BE AVAILABLE IN CASE ADDITIONAL
969      // PROCESSING OF THE FILE IS SPECIFIED IN ONE OF THE NEXT LINKED-
970    // LIST ITEMS.  THIS WILL OVERWRITE A PRIOR .CRP FILE IF CURRENT IS
971        // STILL SCRAMBLED.  (But overwriting was described long ago in
972                                                     // this Document.)
973   }            // loop til done walking linked list, and Affecting all
974                                                     // specified files
975   // NOW DELETE SPECIFIED ORIGINAL FILES
976   if(del1 == 'Y')
977     remove(keyfile);
978   for(affitem=afflist, affnum = 1;   affnum<=affcou;
979       affnum++, affitem=affitem->next)
980   { if((affitem->kill == 'Y') &&
981        strcmp(affitem->pathname, affitem->newname))   // If both names
982             // are the same, then they WILL both have .CRP extensions.
983            // Above, the rename() has already overwritten the old .CRP
984           //  file, and we certainly don't want to delete the new one.
985       remove(affitem->pathname);    // DO remove() old file if 'Y' and
986         // filename has changed.  In this case either new file is .CRP
987   }                                        // or old file is restored.
988   return(0);                                              // no error!
989 };
990 
991 
992 // END OF SOURCE CODE FOR CRYPTION.C,
993 // THE ORIGINAL WORK DONE BY VERNON NEMITZ
994 
995 /* Final Remarks:
996 Some people may think a powerful encryption program to be too valuable
997 to give away, even if only in the shared manner as is described at the
998  start of this program source file.  But -- is this really and truly a
999     powerful encryption program?  The algorithms MUST be published, in
1000order for experts to make that determination.  Well, that means anyone
1001who learns the algorithms will be in a position to write an equivalent
1002     competing program.  It really isn't a terribly complicated thing,
1003after all.  OK, well, certainly algorithms are allowed to be patented,
1004     which would secure some protection against such competition for a
1005      reasonable time (think about the well-known RSA algorithm, which
1006       allowed one company to grow into prominence while enjoying such
1007  protection).  However, recall again that this algorithm has not been
1008proved! -- and patents can be expensive.  It would be kind of silly to
1009      invest all that money in something that could turn out to have a
1010   fundamental flaw.  So why not give it away, with no warranty of any
1011 kind?  Risk-takers who gamble on its security can at least be assured
1012  that their data will be protected UNTIL such a flaw is discovered --
1013 which may take a while.   Perhaps even a very long while...especially
1014                after others have a chance of improving the algorighm.
1015        -- Vernon Nemitz -- http://www.nemitz.net/vernon/vernon.htm */


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC