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 */
|