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 3 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
377
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
Nemitz, Vernon
Reference URL:
			1   //////////////////////////////////////////////////////////////////////
2   // Critical Window Procedure: Windows passes User-Activity messages to
3   // it, for processing
4   LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam,
5                            LPARAM lParam)
6   { // A function that uses a lot of local variables is often a function
7     // that is taking a performance hit.  The computer has a special
8     // place in its memory called the "stack" to which local variables
9     // are typically added and removed as needed -- which is EVERY time
10    // a function begins or ends.  Adding or removing a lot of local
11    // variables, when a function is called many many times, can be
12    // called a "stack-thrashing" time-wasting event.  What is an
13    // alternative, when global variables are frowned-upon these days?
14    // Well, a special type of local variable is called "static", which
15    // is stored outside the stack, in a kind-of-global way, and
16    // persists for as long as the overall program runs -- but it is
17    // still accessed only by the function that declares it.  Static
18    // variables are useful for remembering data in-between calls to the
19    // function.  While some of that remembrance is needed here, in just
20    // a few variables, what is needed more is the time savings that
21    // comes with zero stack-thrashing.  So here all the local variables
22    // are declared as static.
23    static HDC         hdc;
24    static PAINTSTRUCT ps;
25    static COLORREF    oldcolr;
26    static struct      affect *afftmp;
27    static S_32        painting = 0, gathlen = 0, skip = -1, gotdat = 0;
28    static S_32        dot, repaint, juset = 0, working = 0, ret;
29    static char        algo = ' ', del2 = 'N', gather[50] = {' ','\0'},
30                       dofile[50] = {'\0'}, sd1 = ' ',
31                       savskp[50] = {'\0'}, savalg = ' ',
32                       savdo[50] = {'\0'},
33                       sd2 = ' ', d1 = ' ', alg = ' ', d2 = ' ';
34  
35    // The 'working' variable is set when all data entry has been
36    // accepted and the program is beginning to do its CRYPTIONing.  It
37    // is used to ignore all code associated with the data-entry
38    // process, and to limit screen-displays to such things as a
39    // progress bar.
40    if(!working && (affitem == NULL))
41    { *affwalk = malloc(sizeof(struct affect));   // Reserve some memory
42                                                    // (sets 2 pointers)
43      affitem = *affwalk;                           // set third pointer
44      if(!affitem)         // if failed to allocate new linked-list item
45      { MessageBox(NULL, "NOT ENOUGH MEMORY!", "ERROR",
46                   MB_OK | MB_ICONSTOP);
47        PostQuitMessage(CRP_ERR_OM);       // exit code 1: Out of Memory
48        return(0);        // exit program in a way that cleans up memory
49      }   // Below, set ->prev links to go backwards from latest item to
50                                      // first -- which points to latest
51      affitem->prev = affprev;     // Link to prior item (initially sets
52                                             // FIRST list item to NULL)
53      afflist->prev = affitem;      // Set FIRST item prior-link to last
54                                                  // (current) list item
55      affprev = affitem->prev;      // Refetch pointer, except at FIRST,
56                                               // where sets to NON-NULL
57      affitem->next = NULL;
58      affwalk = &(affitem->next);//Get address in case another list-item
59                                                       // needs creating
60      affitem->skipno = -1;     // Now initialize the ordinary variables
61                                                     // in the structure
62      affitem->algo = ' ';
63      affitem->pathname[0] = '\0';
64      affitem->dotloc = -1;
65      affitem->length = 0;
66      affitem->kill = ' ';
67      affcou++;      // increment total count of these linked-list items
68    }           // Later on, the Up-Arrow and Enter keys let the user to
69           // sort-of-scroll through many data items, and this next code
70       // fetches a small group that have been saved on the linked list.
71    if(!working && (gotdat == 0))   // Pull file-to-affect data saved in
72                                            // current linked-list item?
73    { skip = affitem->skipno;
74      algo = affitem->algo;
75      strcpy(dofile, affitem->pathname);
76      sd2 = del2 = affitem->kill;
77      gather[0] = d2 = alg = savalg = ' ';    // erase other remembrance
78                                                            // variables
79      savskp[0] = savdo[0] = gather[1] = '\0';
80      gathlen = 0;
81      gotdat = 1;     // no need to repeat these assignments for a while
82      if(huminp)                       // force stoppages if human input
83      { if(skip > -1)
84        { sprintf(gather, "%d", skip);
85          gathlen = strlen(gather);
86          strcat(gather, " ");
87          skip = -1;
88        }
89        strcpy(savskp, gather);
90        savalg = algo;
91        algo = ' ';
92        strcpy(gather, dofile);
93        gathlen = strlen(gather);
94        strcat(gather, " ");
95        dofile[0] = '\0';
96        strcpy(savdo, gather);
97        del2 = ' ';
98    } }
99  
100   GetClientRect(hwnd, &rect);    // Get rectangular screen region upon
101                                        // which text will be displayed
102   switch(iMsg)
103   {/* case WM_CREATE:             // All initializations already done;
104       return(0);                          // ignore WM_CREATE messages
105   */
106 
107 
108 ////
109     case WM_KEYUP:     // Using this Message only to let us handle the
110                                                        // up-arrow key
111     case WM_CHAR:
112       GetKeyNameText(lParam, keynam, 32);
113       if(!strcmp(keynam, "Esc")) // quit
114       { PostQuitMessage(0);
115         return(0);
116       } // Next line: Since every keystroke generates both WM_CHAR and
117                                                // WM_KEYUP messages...
118       if(strcmp(keynam, "Up") && (iMsg == WM_KEYUP))
119         return(0);        // Need this to prevent duplicate-display of
120                                                  // non-up-arrow keys!
121       ch = (char)toupper((int)wParam);
122       huminp = 1;      // For whatever reason, a keystroke means human
123                                                  // input has occurred
124       if(!working && !strcmp(keynam, "Up"))
125       { for(i=1; i<64; i<<=1)    // Prepare to walk through six lowest
126                                           // bits of NeedInfo variable
127           if(!(NeedInfo & i)) // Each accepted data item is a zero-bit
128                                                         // in NeedInfo
129           { NeedInfo |= i;   // Setting that bit forces the item to be
130                                                       // human-handled
131             break;        // If any bit was set, must be last-accepted
132                                                           // data item
133           }
134         juset = 1;  // Have just set some data (flag controls coloring
135                                                  // of displayed text)
136         if((i == 16) && (affprev != afflist->prev))   // DO WE NEED TO
137                                              // CYCLE TO A PRIOR ITEM?
138         { NeedInfo &= 239;      // clear that just-set bit-value of 16
139           affitem = affprev;     // point at prior item on linked list
140           affprev = affitem->prev;
141           affnum--;              // indicate prior list-element number
142           gotdat = 0;               // set flag to gather up that data
143           SendMessage(hwnd, WM_CHAR, 0x0000000D, 0x001C0001);
144                              // above, send an ENTER (go to algorithm)
145           SendMessage(hwnd, WM_CHAR, 0x0000000D, 0x001C0001);
146                             // above, send another (go to affect-file)
147           SendMessage(hwnd, WM_CHAR, 0x0000000D, 0x001C0001);
148                         // above, send another (highlights DeleteFile)
149 //        SendMessage(hwnd, WM_CHAR, 0x00000026, 0xC1480001);
150                                // above, codes for UP-ARROW, if needed
151           return(0);                 // exit current call to WndProc()
152         }
153         switch(i)
154         { case 32:
155             strcpy(gather, keyfile);     // Remember stuff when moving
156                                           // up to prior editable item
157             gathlen = strlen(gather);
158             strcat(gather, " ");
159             keyfile[0] = '\0';
160             break;
161           case 16:
162             sd1 = del1;
163             del1 = ' ';
164             strcpy(savskp, gather);
165             break;
166           case 8:
167             sprintf(gather, "%d", skip);
168             gathlen = strlen(gather);
169             strcat(gather, " ");
170             skip = -1;
171             break;
172           case  4:
173             savalg = algo;
174             algo = ' ';
175             strcpy(savdo, gather);
176             break;
177           case  2:
178             strcpy(gather, dofile);
179             gathlen = strlen(gather);
180             strcat(gather, " ");
181             dofile[0] = '\0';
182             break;
183           case  1:
184             sd2 = del2;
185             del2 = ' ';
186         }
187       }
188       if(!strcmp(keynam, "Space"))
189         L = 1;
190       else
191         L = strlen(keynam);
192       if(((L == 1) || !strstr("Enter Up", keynam)) &&
193               ((NeedInfo & 32) || ((NeedInfo & 8) &&
194                                    !(NeedInfo & 16))
195                                            // 32: bitflag for key file
196                                || ((NeedInfo & 2) &&
197                                   !(NeedInfo & 28))))
198                                          // 8: bitflag for skip number
199       { if(!strcmp(keynam, "Backspace") ||//2: bitflag, file to affect
200            ((L == 1) && (strchr("1234567890", ch) ||
201                          (((NeedInfo & 32) || !(NeedInfo & 8)) &&
202                           strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ ;:\'`~!@"
203                                  "#$%^&()_+-=.,[]{}_\\", ch)))))
204         { if(gathlen && !strcmp(keynam, "Backspace"))
205           { gather[gathlen--] = '\0';
206             gather[gathlen] = ' ';
207           }
208           else if((L == 1) && ((gathlen < 7) ||
209                                ((NeedInfo & 34) && (gathlen < 48))))
210           { gather[gathlen++] = ch;
211             gather[gathlen++] = ' ';
212             gather[gathlen--] = '\0'; // Terminate string after space,
213                                       // backup to replace space later
214       } } }
215       else if((L == 1) && ((NeedInfo & 16) ||
216                            ((NeedInfo & 1) && !(NeedInfo & 14))))
217                                        // 16: bitflag: delete key file
218       { if((ch == 'Y') || (ch == 'N'))   // 1: bitflag for deletion of
219                                                       // affected file
220          if(NeedInfo & 16)
221            d1 = ch;
222          else
223            d2 = ch;
224       }
225       else if((NeedInfo & 4) && (L == 1))            // 4: bitflag for
226                                                      // De/En-cryption
227       { if((ch == 'D') || (ch == 'E'))
228           alg = ch;
229       }
230       else if(!working)
231       { if(!NeedInfo)      // this is for the Accept/More question
232         { if((doit == ' ') && (L == 1) &&
233              ((ch == 'M') || ((ch == 'A') &&         // Accept or More
234                               (affitem->next == NULL))))
235             doit = ch;  // "More" will mean Continue to gather info on
236                                              // another file-to-affect
237         }
238         else if(!strcmp("Enter", keynam))   // Everything else, except
239                                                        // ENTER and UP
240         { if(NeedInfo & 32)
241           { strncpy(keyfile, gather, gathlen);
242             keyfile[gathlen] = '\0';
243           }
244           else if((NeedInfo & 2) && !(NeedInfo & 60))
245           { strncpy(dofile, gather, gathlen);
246             dofile[gathlen] = '\0';
247         } }
248         else if(strcmp("Up", keynam))    // everything else, except UP
249           break; // let default processing handle all other keystrokes
250       }
251       else
252         break; // if CRYPTION is "working" then also ignore keystrokes
253       InvalidateRect(hwnd, &rect, 0);   // Ensure when have a key, the
254                                                   // window is updated
255 //    return(0);        // Every WndProc() "case" that is processed is
256           // expected to return(0).  HOWEVER, this program gets better
257             // results for Up-Arrow handling by letting each keystroke
258                               // directly flow to the WM_Paint section
259 
260 ////
261     case WM_PAINT:
262       if(painting)
263         return(0);
264       painting = 1;            // multiple calls here will be rejected
265       repaint = 0;      // this will be set only if we WANT to repaint
266       hdc = BeginPaint (hwnd, &ps);
267       SetBkColor(hdc, 0x00C0C0C0);            // reasonably light gray
268       oldcolr = SetTextColor(hdc, 0x00000000); // black; DOING ONLY TO
269                                                         // SET oldcolr
270       hPriorF = SelectObject(hdc, hfont1);          // Fixed font, not
271                                                          // underlined
272       SetTextColor(hdc, 0x00008000);          // moderately dark green
273       TextOut(hdc,                                   // device context
274               1, 2,         // LOGICAL (not pixel) X and Y coordinates
275               "THANK YOU, for choosing this data protection tool.",
276               50);                // length of above string-to-display
277       SetTextColor(hdc, oldcolr);                             // black
278 /*
279 NOTE: Because this CRYPTION program is a "lower level" program, it
280 does not have fancy Windows controls like edit boxes, nor does it call
281 the Windows Choose File dialog.  Here the user is expected to know the
282 standard DOS/Windows syntax for a file name, which is:  Drive letter
283 followed by a colon  :  followed by a backslash  \  followed by a
284 directory name OR by a file name.  If a directory name follows the
285 backslash, then another backslash must follow the directory name.
286 THAT backslash is followed by either another directory name (name of a
287 subdirectory, actually) or a file name.  Eventually, possibly after
288 several sub-subdirectory names and backslashes, the file name is
289 finally included.  Note that the filename itself is frequently in two
290 parts, with a period  .  separating the two parts.  The first part is
291 usually called the file name and the second part is called the
292 extension, but the combination of name and period and extension is
293 also often called the file name.  Fancy stuff like Windows dialogs
294 belongs to fancier programs, such as the future Controller Program
295 that will keep track of encryption keys and call this one with a
296 bunch of parameters.                     */
297       SelectObject(hdc, hfont1);
298       if(!*keyfile)
299         SetTextColor(hdc, 0x0000FFFF);                       // yellow
300       TextOut(hdc, 1, 30, "Drv:\\Pth\\KeyFile (any 8K+)?", 27);
301       SetTextColor(hdc, oldcolr);       // Reset regardless of whether
302                                                         // was changed
303       TextOut(hdc, 205, 30, eraser, 49);   // Erase and reprint below;
304                                                  // handles backspaces
305       SelectObject(hdc, hfont2);
306       if(NeedInfo & 32)
307       { if(*keyfile)
308         { strcpy(gather, keyfile);
309           gathlen = strlen(gather);
310           strcat(gather, " ");
311         }
312         else
313           del1 = ' ';
314         TextOut(hdc, 205, 30, gather, strlen(gather));
315       }
316       else if(*keyfile)
317         TextOut(hdc, 205, 30, keyfile, strlen(keyfile));
318       if(NeedInfo & 32)                 // begin gathering wanted data
319       { if((!strcmp(keynam, "Enter")) || *keyfile)
320         { strncpy(keyfile, gather, gathlen);
321           keyfile[gathlen] = '\0';
322           dskfil = fopen(keyfile, "rb");
323           ucp1 = &ucMemBlk1[15000];   // Skip space big enough for any
324                                                           // .PRM file
325           if(dskfil &&                // if to-be-affected file exists
326              (8300 <= (fetched = fread(ucp1, 1, 1080000, dskfil))) &&
327                                                   // and is big enough
328              (0 == keycheck())) // and has some moderately random data
329           { fclose(dskfil);    // (to be reopened if actually PROCEED)
330             NeedInfo &= 223;       // Clear Bit Five (6th from right),
331                                                            // value 32
332             gather[0] = ' ';  // Prepare these variables for next data
333                                                      // to be gathered
334             gather[1] = '\0';
335             gathlen = 0;
336             juset = 1;
337           }
338           else
339           { if(dskfil)
340               fclose(dskfil);
341             sprintf(tmpstr, "This key file either cannot be found,\n"
342                             "or is smaller than 8300 bytes, or\n"
343                             "hasn't enough random data in it:\n%s",
344                             keyfile);
345             MessageBox(NULL, tmpstr, "ERROR",
346                        MB_OK | MB_ICONEXCLAMATION);
347             keyfile[0] = '\0';
348             doit = ' ';
349             huminp = 1;
350             repaint = 1;
351           }
352           keynam[0] = '\0';
353       } }
354       if(!(NeedInfo & 32)) // Only do next data entry after prior line
355                                                         // is accepted
356       { SelectObject(hdc, hfont1);
357         if(NeedInfo & 16)// Only want yellow question text when asking
358                                                       // this question
359           if((((del1 == ' ') && (d1 == ' ') && (sd1 == ' ')) ||
360               !strcmp(keynam, "Up")) ||
361              ((huminp == 1) && (juset == 1)))
362             SetTextColor(hdc, 0x0000FFFF);                   // yellow
363         TextOut(hdc, 1, 46,
364                 "Delete that file after successful processing (Y/N)?",
365                 51);
366         SetTextColor(hdc, oldcolr);     // Reset regardless of whether
367                                                         // was changed
368         SelectObject(hdc, hfont2);
369         if(sd1 != ' ')
370           del1 = sd1;
371         if(d1 != ' ')
372           del1 = d1;
373         sprintf(tmpstr, "%c", del1);
374         TextOut(hdc, 373, 46, tmpstr, 1);
375         if(NeedInfo & 16)              // ok to begin gathering data ?
376         { if((del1 != ' ') && (((huminp == 0) || (juset == 0)) ||
377                                !strcmp(keynam, "Enter")))
378           { NeedInfo &= 239;       // Clear Bit Four (5th from right),
379                                                            // value 16
380             sd1 = ' ';
381           }
382           else
383             juset = 0;
384           d1 = ' ';
385           keynam[0] = '\0';
386       } }
387       if(NeedInfo & 32)
388       { SelectObject(hdc, hfont1);
389         TextOut(hdc, 1, 46, eraser, 80); // Hide this line while prior
390                                                         // line edited
391       }
392       if(!(NeedInfo & 48)) // Only display this data entry after prior
393                                                  // lines are accepted
394       { SelectObject(hdc, hfont1);
395         sprintf(tmpstr,
396                 "======= INFO FOR FILE TO AFFECT:  #%d OF %d =======",
397                 affnum, affcou);
398         SetTextColor(hdc, 0x00008000);        // moderately dark green
399         TextOut(hdc, 1, 78, tmpstr, strlen(tmpstr));
400         SetTextColor(hdc, oldcolr);
401         if(NeedInfo & 8) // Only want yellow question text when asking
402                                                       // this question
403           if((skip == -1) &&
404              (strcmp(keynam, "Enter") || (gathlen == 0)))
405             SetTextColor(hdc, 0x0000FFFF);                   // yellow
406         TextOut(hdc, 1, 94, "Extra randomizer 0-9999999:", 27);
407         SetTextColor(hdc, oldcolr);     // Reset regardless of whether
408                                                         // was changed
409         TextOut(hdc, 205, 94, eraser, 80);  // Erase & reprint; cleans
410                                         // up after Automatic displays
411         SelectObject(hdc, hfont2);
412         if(NeedInfo & 8)
413         { if(skip > -1)
414           { sprintf(gather, "%d", skip);
415             gathlen = strlen(gather);
416             strcat(gather, " ");
417           }
418           else
419           { if(*savskp)
420             { strcpy(gather, savskp);
421               gathlen = strlen(gather) - 1;
422               savskp[0] = '\0';
423           } }
424           TextOut(hdc, 205, 94, gather, strlen(gather));
425         }
426         else if(skip > -1)
427         { sprintf(tmpstr, "%d", skip);
428           TextOut(hdc, 205, 94, tmpstr, strlen(tmpstr));
429         }
430         if(NeedInfo & 8)               // ok to begin gathering data ?
431         { i = strtol(gather, NULL, 10);// Get not-necessarily-finished
432                                                       // numeric value
433           affitem->skipno = i;               // save it on linked list
434           if((!strcmp(keynam, "Enter") && (gathlen > 0)) ||
435              (skip > -1))
436           { skip = i;
437             NeedInfo &= 247;      // Clear Bit Three (4th from right),
438                                                             // value 8
439             gather[0] = ' ';  // Prepare these variables for next data
440                                                      // to be gathered
441             gather[1] = '\0';
442             gathlen = 0;
443             juset = 1;
444             keynam[0] = '\0';
445       } } }
446       if(NeedInfo & 16)
447       { SelectObject(hdc, hfont1);
448         TextOut(hdc, 1, 78, eraser, 69); // Hide this line while prior
449                                                         // line edited
450         TextOut(hdc, 1, 94, eraser, 80); // Hide this line while prior
451                                                         // line edited
452       }
453       if(!(NeedInfo & 56)) // Only display this data entry after prior
454                                                  // lines are accepted
455       { SelectObject(hdc, hfont1);
456         if(NeedInfo & 4) // Only want yellow question text when asking
457                                                       // this question
458         if((((algo == ' ') && (alg == ' ') && (savalg == ' ')) ||
459                                          !strcmp(keynam, "Up")) ||
460            ((huminp == 1) && (juset == 1)))
461           SetTextColor(hdc, 0x0000FFFF);                     // yellow
462         TextOut(hdc, 1, 110,
463                 "Use \"Encrypt\" or \"Decrypt\" algorithm (E/D)?",
464                 43);
465         SetTextColor(hdc, oldcolr);     // Reset regardless of whether
466                                                         // was changed
467         SelectObject(hdc, hfont2);      // same fixed font, underlined
468         if(savalg != ' ')
469           algo = savalg;
470         if(alg != ' ')                  //(alg == 'E') || (alg == 'D')
471           algo = alg;
472         sprintf(tmpstr, "%c", algo);
473         TextOut(hdc, 317, 110, tmpstr, 1);
474         if(NeedInfo & 4)
475         { if((algo != ' ') && (((huminp == 0) || (juset == 0)) ||
476                                      !strcmp(keynam, "Enter")))
477           { NeedInfo &= 251;        // Clear Bit Two (3rd from right),
478                                                             // value 4
479             savalg = ' ';
480             keynam[0] = '\0';
481           }
482           else
483             juset = 0;
484           alg = ' ';
485           keynam[0] = '\0';
486           affitem->algo = algo;                 // save on linked list
487       } }
488       if(NeedInfo & 8)
489       { SelectObject(hdc, hfont1);
490         TextOut(hdc, 1, 110, eraser, 80);// Hide this line while prior
491                                                         // line edited
492       }
493       if(!(NeedInfo & 60)) // Only display this data entry after prior
494                                                  // lines are accepted
495       { SelectObject(hdc, hfont1);
496         if(!*dofile)
497           SetTextColor(hdc, 0x0000FFFF); // yellow
498         TextOut(hdc, 1, 126, "Drive:\\Path\\File to affect?", 27);
499         SetTextColor(hdc, oldcolr);     // Reset regardless of whether
500                                                         // was changed
501         TextOut(hdc, 205, 126, eraser, 49); // Erase & reprint; cleans
502                                         // up after Automatic displays
503         SelectObject(hdc, hfont2);
504         if(*dofile)
505         { strcpy(gather, dofile);
506           gathlen = strlen(gather);
507           strcat(gather, " ");
508         }
509         else
510         { del2 = ' ';
511           if(*savdo)
512           { strcpy(gather, savdo);
513             gathlen = strlen(gather) - 1;
514             savdo[0] = '\0';
515         } }
516         if(!working && gathlen)
517         { strncpy(affitem->pathname, gather, gathlen);    // Save even
518                                         // partial name on linked list
519           affitem->pathname[gathlen] = '\0';   // Terminate the copied
520                                                              // string
521         }
522         TextOut(hdc, 205, 126, gather, strlen(gather));
523         if(NeedInfo & 2)          // see if ok to begin gathering data
524         { if((!strcmp(keynam, "Enter")) || *dofile)
525           { strncpy(dofile, gather, gathlen);
526             dofile[gathlen] = '\0';
527             for(dot=-1, i=gathlen-1; i>=0; i--)//Walk backward through
528                                                        // the filename
529             { ch = dofile[i];
530               if((ch == '\\') || (ch == ':'))
531                 break;   // found marker before filename; quit looping
532               if((ch == '.') && (dot == -1))
533               { dot = i;               // Save location of first-found
534                                                    // extension-marker
535                 break;               // no need to continue for() loop
536             } }
537             if(((i == -1) && (gathlen > 44)) ||   // MUST HAVE ROOM IN
538                                          // FILE NAME STRING TO EITHER
539                ((48 - i) < 4)) // REPLACE EXTENSION WITH, OR ADD, .CRP
540             { sprintf(tmpstr,
541                     "This File-to-affect has too long a name:\n  %s\n"
542              "There must be space to set the File Extension to .CRP\n"
543                "-- AND that modified name must be acceptably short,\n"
544                  "or it can't be specified as a file to unscramble!\n"
545               "Try renaming file, or moving it to another directory.",
546                       dofile);
547               MessageBox(NULL, tmpstr, "ERROR",
548                          MB_OK | MB_ICONEXCLAMATION);
549               dofile[0] = '\0';
550               doit = ' ';
551               huminp = 1;
552             }
553             else       // Below, using FindFirstFile() and not fopen()
554                                            // because want file length
555             { j = 1;              // initialize this as a failure flag
556               fil1 = FindFirstFile(dofile, (LPWIN32_FIND_DATA)&wfd);
557                                                 // seek file-to-affect
558               i = GetLastError(); // double-check to be sure it exists
559               if((fil1 != INVALID_HANDLE_VALUE) &&
560                  (i != ERROR_PATH_NOT_FOUND))
561               { affitem->length = wfd.FileSzLo;  // Save length of the
562                                                       // file, 4GB max
563                 j = 0;
564               }                      // Below, failed to open file, so
565               else if((dot > -1) && !strcmp(".CRP", &(dofile[dot])))
566                                      // if specified extension is .CRP
567               { afftmp = afflist;           // Prepare to walk list of
568                                                     // files-to-affect
569                 i = dot - 1;// Get length of drive\path\name up to the
570                                                    // extension-marker
571                 while(afftmp != affitem)         // As long as current
572                                        // linked-list-item not reached
573                 { j = strncmp(dofile, afftmp->pathname, i); // Compare
574                                           // prior ACCEPTED file names
575                   if(!j)   // A matching file was specified previously
576                                                          // and saved?
577                   { affitem->length = afftmp->length + 87;     // Copy
578                       // length of the file, 4GB max, because that one
579                     break;  // passed, and here-desired .CRP file will
580                   }// be created from it (so end loop).  Note original
581                    // file's length + 87 ("Cryptionite" identifier) is
582                     // roughly the number of scrambled bytes, for that
583                                    // currently-nonexistent .CRP file.
584                   afftmp = afftmp->next;        // Else see about next
585                                      // file-data saved on linked list
586               } }
587               FindClose(fil1);       // Release memory associated with
588                                                     // FindFirstFile()
589               if(!j)                        // if this file name is OK
590               { NeedInfo &= 253;    // Clear Bit One (2nd from right),
591                                                             // value 2
592                 gather[0] = ' ';   // Prepare these variables for next
593                                                 // data to be gathered
594                 gather[1] = '\0';
595                 gathlen = 0;
596                 affitem->dotloc = (S_16)dot;
597                 juset = 1;
598               }
599               else
600               { sprintf(tmpstr,
601                         "This file-to-affect cannot be found:\n%s",
602                         dofile);
603                 MessageBox(NULL, tmpstr, "ERROR",
604                            MB_OK | MB_ICONEXCLAMATION);
605                 dofile[0] = '\0';
606                 doit = ' ';
607                 huminp = 1;
608             } }
609             keynam[0] = '\0';
610       } } }
611       if(NeedInfo & 4)
612       { SelectObject(hdc, hfont1);
613         TextOut(hdc, 1, 126, eraser, 80);// Hide this line while prior
614                                                         // line edited
615       }
616       if(!(NeedInfo & 62)) // Only display this data entry after prior
617                                                  // lines are accepted
618       { SelectObject(hdc, hfont1);
619         if(NeedInfo & 1) // Only want yellow question text when asking
620                                                       // this question
621           if((((del2 == ' ') && (d2 == ' ') && (sd2 == ' ')) ||
622                                        !strcmp(keynam, "Up")) ||
623              ((huminp == 1) && (juset == 1)))
624             SetTextColor(hdc, 0x0000FFFF);                   // yellow
625         if((dot > -1) && !strcmp(".CRP", &(dofile[dot])))
626                                      // if specified extension is .CRP
627         { TextOut(hdc, 1, 142, eraser, 99);
628           TextOut(hdc, 1, 142,
629                  "Every specified .CRP file will always be replaced.",
630                   50);
631           SetTextColor(hdc, oldcolr);
632           del2 = 'Y';           // ALWAYS delete "original" .CRP files
633         }
634         else
635         { TextOut(hdc, 1, 142,
636                 "Delete that file after successful processing (Y/N)?",
637                   51);
638           SetTextColor(hdc, oldcolr);                         // black
639           SelectObject(hdc, hfont2);
640           if(sd2 != ' ')
641             del2 = sd2;
642           if(d2 != ' ')
643             del2 = d2;
644         }
645         sprintf(tmpstr, "%c", del2);
646         TextOut(hdc, 368, 142, tmpstr, 1);
647         if(NeedInfo & 1)
648         { if((del2 != ' ') && (((huminp == 0) || (juset == 0)) ||
649                                       !strcmp(keynam, "Enter")))
650           { NeedInfo &= 254;       // Clear Bit Four (5th from right),
651                                                            // value 16
652             sd2 = ' ';
653           }
654           else
655             juset = 0;
656           d2 = ' ';
657           keynam[0] = '\0';
658           affitem->kill = del2;                 // save on linked list
659       } }
660       if(NeedInfo & 2)
661       { SelectObject(hdc, hfont1);
662         TextOut(hdc, 1, 142, eraser, 80);// Hide this line while prior
663                                                         // line edited
664       }
665       SelectObject(hdc, hfont1);
666       if(!NeedInfo)                    // no other file info required?
667       { if(!working && (affitem->next != NULL))
668         { strcpy(tmpstr, "MORE TO SEE; PRESS M");
669           doit = 'M';
670         }
671         else
672         { strcpy(tmpstr, "ACCEPT / MORE (A/M)?");
673           if(!huminp)                   // if automatically continuing
674             doit = 'A';//for when all data has been presented/accepted
675         }
676         if(working || (proceed == ' '))
677         { if(!working && (doit == ' '))
678             SetTextColor(hdc, 0x0000FFFF);                   // yellow
679           TextOut(hdc, 1, 174, tmpstr, 20);  // Display MORE TO SEE or
680                                                      //  ACCEPT / MORE
681           SetTextColor(hdc, oldcolr);
682           SelectObject(hdc, hfont2);
683           sprintf(tmpstr, "%c", doit);
684           TextOut(hdc, 155, 174, tmpstr, 1);
685           if(!working && (doit != ' '))// check for a previously-saved
686                                                              // A or M
687             proceed = doit;
688       } }
689       else
690       { SelectObject(hdc, hfont1);
691         TextOut(hdc, 1, 174, eraser, 25);     // Hide while prior line
692                                                              // edited
693       }
694       SelectObject(hdc, hfont1);
695       tmpstr[0] = '\0';
696       strcpy(tadone, "Press");
697       if(proceed != 'A')
698       { if(proceed == 'M')
699         { affnum++;                         // prepare new item number
700           affprev = affitem; // Save current item as previous (becomes
701                                        // previous, next line of code)
702           affitem = affitem->next;
703         }
704         if(huminp)
705         { if(!(NeedInfo & 32))
706           { strcat(tadone, " up-arrow to edit prior entry,");
707             doit = ' ';     // no auto-proceed if human entry required
708           }
709           sprintf(tmpstr, "%s ESC to exit program.", tadone);
710         }
711         else
712           TextOut(hdc, 165, 174,
713                   "  (autoproceeding with good-looking parameters)",
714                   47);
715       }
716       else                                         // We are proceding
717       { if(huminp)
718           TextOut(hdc, 165, 174,
719                   "-- OK, accepted inputs now being applied...", 43);
720         else // Automatically proceeding ("autoproceeding" duplication
721                                             // is for Window re-draws)
722           TextOut(hdc, 165, 174,
723                   "  (autoproceeding with good-looking parameters)",
724                   47);
725         strcpy(tmpstr,
726          "Program automatically ends when done; Press ESC to abort.");
727       }
728       TextOut(hdc, 100, 238, eraser, 49);
729       SetTextColor(hdc, 0x00FFFFFF);                          // white
730       TextOut(hdc, 1, 238, tmpstr, strlen(tmpstr));
731                           // tmpstr is one of 3 possible strings here:
732                                          // Press ESC to exit program.
733            // Press up-arrow to edit prior entry, ESC to exit program.
734           // Program automatically ends when done; Press ESC to abort.
735       if(!NeedInfo && (proceed == 'A') && (status > 0))
736       { i = status / 100;            // extract type of status message
737         j = ((status % 100) >> 1) + 1;     // Extract progress report:
738                                                             // 1 to 50
739         strcpy(tadone,
740                "                                                   ");
741                                                  // reset to 51 spaces
742         strnset(tadone, '=', j);  // Create progress bar (overwrite up
743                                                       // to 50 spaces)
744         tadone[j] = '>';       // Make progress bar look like an arrow
745                                          // (may overwrite 51st space)
746          // note that null-terminator, after strcpy(), is not affected
747         switch(i)
748         { case 1:
749             sprintf(tmpstr, "Initializing work area: [%s]", tadone);
750             break;
751           case  2:
752             sprintf(tmpstr, "Gathering Control Primes: [%s]", tadone);
753             break;
754           case  3:
755             j = (fetched - 108) >> 3;
756             if(j > 65536)
757               j = 65536;
758             sprintf(tmpstr,
759                     "Please be patient; pulling Primary Cryption Key,"
760                     " up to %d prime numbers", j);    // Fetched is at
761                                          // least 8300; 8300-108=8192;
762                // 3 bit-shifts=division-by-8 (8192 bytes from Key File
763                                                 // yields 1024 primes)
764             SetTextColor(hdc, 0x0000FFFF);                   // Yellow
765             TextOut(hdc, 1, 190, tmpstr, strlen(tmpstr));   // Special
766                                                // "be patient" message
767             SetTextColor(hdc, oldcolr);
768             sprintf(tmpstr, "Loaded %d Primes: [%s]", prmbar, tadone);
769             break;
770           case  4:
771             TextOut(hdc, 1, 190, eraser, 99); // erase special message
772             tmpstr[0] = '\0';
773             sprintf(tmpstr, "Crypting File #%d of %d: [%s]",
774                     affnum, affcou, tadone);
775         }
776         TextOut(hdc, 1, 206, eraser, 99);           // Erase any prior
777                                                        // progress bar
778         TextOut(hdc, 1, 206, tmpstr, strlen(tmpstr));   // (Re)Display
779                                    // current message and progress bar
780       }
781       SetTextColor(hdc, oldcolr);
782       SelectObject(hdc, hPriorF);
783       EndPaint(hwnd, &ps);
784       painting = 0;
785       if(proceed == 'M')
786       { proceed = ' ';
787         gotdat = 0;
788         NeedInfo |= 15;
789         repaint = 1;                // WANT to repaint, to prepare for
790                                                    // new data entries
791       }
792       if((proceed == 'A') && !working)
793       { working = 1;
794         PostMessage(hwnd, WM_COMMAND, 123456789, 987654321);
795                                               // **** BEGIN TASK! ****
796       }
797       if(repaint)
798       { InvalidateRect(hwnd, &rect, 0);      // The window must now be
799                                                          // re-updated
800         repaint = 0;
801       }
802       return(0);                                    // END OF WM_PAINT
803 
804 
805 ////
806     case WM_COMMAND:
807       if((wParam == 123456789) && (lParam == 987654321))
808       { if(0 < (ret = WorkAreaInit()))
809         { PostQuitMessage(ret);      // any of several possible errors
810           return(0);
811         }
812         if(0 < (ret = KeyToPrimes()))
813         { PostQuitMessage(ret);      // any of several possible errors
814           return(0);
815         }
816         if(0 < (ret = AffectFiles()))
817         { PostQuitMessage(ret);      // any of several possible errors
818           return(0);
819         }
820         PostQuitMessage(0);             // QUIT AUTOMATICALLY WHEN ALL
821                                          // TESTING/PROCESSING IS DONE
822         return(0);
823       }
824       break;                   // ignore all other WM_COMMAND messages
825 
826 
827 
828 ////
829 
830     case WM_DESTROY: // Clean-up work goes here, before ending overall
831                                                  // conversion program
832       PostQuitMessage(0);      // Note memory allocations freed at end
833                                                        // of WinMain()
834       return(0);        // Always return Zero from any Windows message
835                                                           // processed
836   }        // all Windows messages not handled in switch block must be
837                                                     // processed below
838   return(DefWindowProc(hwnd, iMsg, wParam, lParam));
839 };                                                 // END OF WndProc()
840 
841 
842 
843 /********************************************************************/
844 // This semi-clone of the Main Windows Message-Handling Loop has the
845 // purpose of being available anywhere in this program, to process
846 // anything outstanding in the Message Queue.  That is, some of the
847 // other functions below may take a long time to do their things, and
848 // Windows might think the program is "Not Responding".  By placing
849 // calls to this function in appropriate places (during Progress-Bar
850 // handling, most likely), not only will Windows stay happy, but it
851 // also makes it easier for the user to abort the program by pressing
852 // the ESCape key.  NOTE:  When a large Key File is specified, such
853 // that more than ten thousand Primes will be pulled as the Primary
854 // CRYPTION Key, it does indeed take time to sort out those thousands
855 // of data items from random sequence, and then pull the primes from
856 // the main compressed-data file.  (IF YOU WANT REAL SPEED FOR THIS
857 // PART OF THE PROCESS, GET A "SOLID-STATE DISK" a.k.a. RAM DISK TO
858 // HOLD THE PRIMES DIRECTORY.)  If the user chooses to Abort, several
859 // seconds may pass before the CRYPTION program acknowledges it by
860 // quitting.  In a way this slow preparation work is good because the
861 // user is granted a reasonable chance to abort -- since the CRYPTION
862 // process itself is the very next thing that happens after loading
863 // all those Primes, and this process does depend on the speed of the
864 // computer, which can be quite fast.  There may not be any other
865 // equally good place to abort the CRYPTION program after all data has
866 // been accepted, especially if small files are to be scrambled
867 // (UNLESS very large Skip Numbers are chosen).  IN GENERAL, it may be
868 // preferable to use large Key Files only when you want to scramble
869 // very large data files, or perhaps a great many small files.  In
870 // those cases the time to load 65,000 primes for the Primary CRYPTION
871 // Key is OK because you know it's going to take a while, anyway, for
872 // the overall scrambling process to be completed.
873 S_32 ProcessMessages(void)
874 { static MSG mesg;         // Make this multi-byte structure static so
875                                            // doesn't go on the stack.
876   S_32 ret = 0;//Initialize return-value-variable to Everything-is-OK.
877                   // For the inexperienced, this assigment will happen
878                // every time this function is called, because  ret  is
879                    // NOT a "static" type of variable.  Assignments to
880                // static variables (in their declaration statements at
881                  // the start of a function) are only done once, after
882                   // which the assignment-code is ignored in all later
883                 // calls to the function.  However, the assigned value
884                    // is remembered in-between function calls, and the
885                 // body of the function can change it if desired (then
886                       // the new value will be remembered, of course).
887   while(!ret && PeekMessage(&mesg, NULL, 0, 0, PM_NOREMOVE))   // Seek
888                               // anything in the Windows Message queue
889   { if(GetMessage(&mesg, NULL, 0, 0))        // We arrive here ONLY if
890                                       // PeekMessage() found something
891     { TranslateMessage(&mesg);
892       DispatchMessage(&mesg);
893     }
894     else // GetMessage pulled a WM_QUIT
895     { PostQuitMessage(0);      // Must put it back in Messge Queue for
896                                          // primary loop in WinMain()!
897       ret = 1;      // Tell this while() loop AND the calling function
898                                                            // to quit.
899   } }         // Otherwise loop til processed all accumulated Messages
900                                                        // in the Queue
901   return(ret); // return-value  ret  will be 0 if no messages in Queue
902 };
903 
904 
905 
906 S_32 keycheck(void)  // Let's try to get 90 bytes of reasonably random
907                                              // data from the Key File
908 { S_32 k;
909   U_08 uc, *ucp2 = ucMemBlk1;  // Point at start of buffer loaded from
910                                                            // Key File
911      // Remember Key File data begins 15000 bytes into the buffer, and
912                                       // that ucp1 points at its start
913   for(i=0; i<100; i++)
914     ucp2[i] = 0;         // Erase the first 100 bytes of the ucMemBlk1
915                                                        // memory block
916   for(i=0, j=0, uc=0; (i<(int)fetched)&&(j<90); i++)// Prepare to walk
917                                     // length of fetched Key File data
918   { uc ^= ucp1[i];          // Get a byte (or combine with another via
919                                                       // Exclusive-Or)
920   // This trick with Exclusive-Or means that the 90 bytes we save via
921   // the ucp2 pointer will be rather unlike the data actually pulled
922   // from the file.  More, since we are seeking ALL DIFFERENT bytes,
923   // there is no telling what order they will be in.  That is, if a
924   // pulled/combined byte has already been found, we keep pulling/
925   // combining until something different pops out.  So, while a simple
926   // text file like the U.S. Constitution may not look much like
927   // random data, multiple Exclusive-Or operations between pulled
928   // bytes will indeed create reasonable randomness.  (Later on, in
929   // the main algorithm for using the Key File to select primes, bytes
930   // pulled from the Key File will be combined with pseudorandom
931   // numbers, so again even minimal randomness in the Key File will be
932   // acceptable.)
933     if(uc > 0)                              // for nonzero values only
934     { for(k=0; k<j; k++)              // check previously saved values
935         if(uc == ucp2[k])      // If current nonzero value has already
936                                                          // been saved
937           break;                      // consider it not random enough
938       if(k == j) // if for() loop ended with no match of current value
939       { ucp2[j++] = uc;                                     // save it
940         uc = 0;                    // reset Exclusive-Or "accumulator"
941   } } }                  // loop through as much of Key file as needed
942   return(j < 90);          // Return value is zero if got 90 different
943                                                         // byte values
944 };// Here is a place where parentheses with  return  make great sense,
945 // because they delimit a comparison-operation.  Parentheses force the
946       // compiler to code an evaluation of the comparison, and yield a
947     // guaranteed result of either Zero-for-"False" or One-for-"True".
948 
949 
950 S_32 WorkAreaInit(void)             // fill 4,725,000 bytes with zeros
951 { char *r, *s, *t, *u, *v;
952   S_32 x, y;
953 
954   p = (char *)(ucMemBlk4 + 525000);// Set pointer partway through this
955                                                        // memory block
956   q = p + 525000;     // set pointer partway through this memory block
957   r = q + 525000;     // set pointer partway through this memory block
958   s = r + 525000;     // set pointer partway through this memory block
959   t = s + 525000;     // set pointer partway through this memory block
960   u = t + 525000;     // set pointer partway through this memory block
961   v = u + 525000;     // set pointer partway through this memory block
962   for(status=100, x=0; x<525000; x+=10500, status+=2)
963   { InvalidateRect(hwnd, &rect, 0);         // make window update-able
964     PostMessage(hwnd, WM_PAINT, 0, 0); // Progress bar grows, based on
965                                                              // status
966     if(ProcessMessages())         // process ALL messages in the queue
967       return(CRP_WM_QUIT);                        // assume user abort
968     for(y=x; y<(x+10500); y++)
969     { ucMemBlk2[y] = '\0';                    // 50 * 10,500 = 525,000
970       ucMemBlk4[y] = '\0';                    // 50 * 10,500 = 525,000
971       p[y] = '\0';                            // 50 * 10,500 = 525,000
972       q[y] = '\0';                            // 50 * 10,500 = 525,000
973       r[y] = '\0';                            // 50 * 10,500 = 525,000
974       s[y] = '\0';                            // 50 * 10,500 = 525,000
975       t[y] = '\0';                            // 50 * 10,500 = 525,000
976       u[y] = '\0';                            // 50 * 10,500 = 525,000
977       v[y] = '\0';   // 50 * 10,500 = 525,000; last of 4,200,000 bytes
978   } }  // YES, the preceding could be written more efficiently and run
979       //faster.  But this was also the first chance to experiment with
980                                               // progress-bar code....
981   it = (U_32 *)ucMemBlk3;        // Initialize Index Table pointer for
982                                             // IndexToPrime() function
983   WorkSize = 0;        // There are no ScratchPads prepared yet in the
984                                              // WorkRegion (ucMemBlk2)
985   WhichWay[0] = 0;// Set for Encryption Algorithm (code for Decryption
986                                                     // Algorithm is 4)
987   WhichWay[1] = 1;// Set for Encryption Algorithm (code for Decryption
988                                                    // Algorithm is -1)
989               // Now give the Control Scratchpads some default values,
990                                                  // soon to be changed
991   LoadMaster->dvd = 0x12345;// Just a number to be divided a few times
992                                                    // (in hexadecimal)
993   LoadMaster->dvs = 0x13531;    // This is a prime, 79153 in Base Ten;
994                                                  // not used very long
995   ModCounter->dvd = 1;        // Two bits at a time will be yielded by
996                                                          // ModCounter
997   ModCounter->dvs = 0x8000000;   // This division produces ZEROS for a
998                                        // short time (2 modifications)
999   TypeSetter->dvd = 30;     // Three bits at a time will be yielded by
1000                                                         // TypeSetter
1001  TypeSetter->dvs = 63;      // This division produces 011 110 011 110
1002                                 //  011 110 ...(til dvd/dvs replaced)
1003  RandomSkip->dvd = 1;        // Two bits at a time will be yielded by
1004                                                         // RandomSkip
1005  RandomSkip->dvs = 3;       // This division produces 01 01 01 01 ...
1006                                             // (til dvd/dvs replaced)
1007  // Above default values will allow the PseudoRandomize() function to
1008  // be called even while gathering the final data that will replace
1009  // these default values.  This lets us scramble the Key File data
1010  // even while fetching it, thereby practically guaranteeing we
1011  // always have pseudorandom Key data.  Again, that is the main
1012  // reason why only a minimal randomness test was performed by
1013  // function keycheck().
1014  return(0);
1015};
1016/* NOTE REGARDING EFFECTIVENESS OF THE CRYPTION ALGORITHMS:  While
1017   someone watching the flow of this code with a debugging tool could
1018   easily use the above initial information to construct a list of
1019   initial "scramble values" (values that affect key-file data), it
1020   remains to be seen if that information can actually help unscramble
1021   a given .CRP file.  See, the dilemma faced by a cryptanalyst is
1022   that the scramble-data used to affect that file did NOT directly
1023   come from these easily computed initial scramble values.  These
1024   values are merely used, along some of with those 90 "random" bytes
1025   found by the keycheck() function, to replace themselves with all
1026   new values -- and the cryptanalyst does not know what key file was
1027   used to obtain those 90 bytes.  THEN, those new values are used to
1028   generate all new pseudorandom numbers which are combined with
1029   (again unknown to the cryptanalyst) straight key-file data to
1030   select a thousand or more primes from the compressed primes data
1031   file -- and it is those primes that generate the scramble-data
1032   used to affect a Message file.  It seems likely that without
1033   knowing the key file, and even knowing that the scrambled data in
1034   the affected file always begins with "Data Protected From
1035   Snoopercomputers"..., there is no easy way to decide which
1036   GROUPINGS of primes-as-divisors and which numbers-as-dividends were
1037   used to generate the actually-used scamble-values. */
1038
1039
1040
1041
1042
1043// Do binary search of Index for location of Nth prime, then fetch it
1044// from the COMPRESS.PRM file.  Parameter is a pointer to N;
1045// THIS FUNCTION REPLACES N WITH FOUND PRIME
1046S_32 IndexToPrime(U_32 *dp)
1047{ static U_32  N, hi, md, lo; // Static variables let the function run
1048                                                             // faster
1049/*
1050The Index to the COMPRESS.PRM file treats that file like 143023 blocks
1051of 720 bytes each (the last block is smaller).  The CMPRMDEX.QNT file
1052holds 143023 quantities of primes, each quantity being the number of
1053primes represented by the compressed data in one 720-byte block of the
1054file COMPRESS.PRM.  When the Index file was loaded, those quantites
1055were added up, and each subtotal was saved.  Therefore we now have in
1056memory an ever-increasing sequence of numbers, which we can use to
1057find the Nth prime.  N just needs to be no larger than the last value
1058in the sequence, which is the grand total number of primes that can be
1059accessed via COMPRESS.PRM (203,280,221).  The first thing this
1060function will do is ensure N is not too big.  Then it will conduct a
1061fast binary search to determine which 720-byte block inside
1062COMPRESS.PRM holds the desired Nth prime, and that compressed-data
1063block is of course immediately fetched.  The desired prime is then
1064quickly constructed using the Index value, N, and some of the elements
1065in the  tbl  array.
1066*/
1067  N = *dp;
1068  while(N > 203280221)      // Too big a value entered for finding Nth
1069                                                             // prime?
1070    N >>= 1;         // HALVE the value (ignore any odd-bit remainder)
1071  if(N < 7)
1072   *dp = skpd[N];         // These first primes are NOT represented in
1073                                                       // COMPRESS.PRM
1074  else
1075  { lo = 0;                                    // lowest Index element
1076    hi = 143022;                              // highest Index element
1077    md = hi >> 1;      // Prepare to do a binary search from middle of
1078                                                          // the Index
1079    while (lo != hi)
1080    { if(N < it[md])
1081        hi = md;       // Set new upper bound (this still might be the
1082                                                      // right block!)
1083      else if(N > it[md])
1084        lo = md + 1;// Set new lower bound (block following  md  might
1085                                                 // be the right one!)
1086      else
1087        break;    // Well, well,  cand  just happened to exactly match
1088                                                    // an Index entry!
1089      md = ((hi - lo) >> 1) + lo;  // Get new middle between hi and lo
1090                                 // (may equal untested lo if hi-lo=1,
1091                    //  but next loop then finds it or makes lo=md=hi)
1092    }
1093    lo = md * 720;     // Compute which block of compressed file holds
1094                                                              // our N
1095    fseek(prmfil, ((S_32)lo - fpb) , SEEK_CUR);   // Go to appropriate
1096                                                      // file location
1097    fpb = fread(tmpstr, 1, 720, prmfil);            // Load a block of
1098                                              // compressed-prime data
1099    fpb += lo;       // Set file-position-byte to current location for
1100                                                          // next seek
1101    ucp4 = tbl;                            // initialize table-pointer
1102    if(md > 0)                             // not the very first block
1103    { hi = it[(md - 1)]; // Fetch total number of primes preceding the
1104                                                      // fetched block
1105      md *= 30030;  // Initial computation for first possible prime in
1106                                                         // that block
1107      md++;      // Adjust for exactness:  first number represented by
1108                                                    // compressed data
1109      bt = 1;                                 // initialize bit-tester
1110    }
1111    else                                        // very first block...
1112    { hi = 6;            // Compressed-prime data starts at 7th prime;
1113                                            // ensure loop below works
1114      md = 17;
1115      bt = 2;                                 // initialize bit-tester
1116      ucp4++;                 // correct table pointer for first block
1117    }
1118    by = (U_08 *)tmpstr;  // Set byte-pointer to start of 720 items in
1119                                                             // buffer
1120    for(;;)                           // this loop guaranteed to break
1121    { if((*by & bt) == bt)                       // if this is a prime
1122        hi++;                               // count towards desired N
1123      if(hi >= N)
1124        break;                                    // exit if N reached
1125      md += *ucp4++;   // add a tbl entry to create new possible prime
1126      if(bt == 128) // check for last possible bit-value (in one byte)
1127      { bt = 1;                                    // reset bit-tester
1128        by++;                        // advance to next byte in buffer
1129      }
1130      else
1131        bt <<= 1;                       // double for next bit-to-test
1132    }     // when loop ends, variable  md  holds the desired Nth prime
1133    *dp = md;                                     // Replace N with it
1134  }
1135  return(0);                                              // no error!
1136};
1137
1138
1139// Divide using passed scratchpad pointer, to obtain some number of
1140// bits of result.  Since Base 2 is king, each division will yield one
1141// bit.  Most of the time this function will be used to obtain just
1142// two bytes, 16 bits, and often less.  NOTE: ENSURE (0 < .dvd) and
1143// (.dvd < .dvs) -- WHEN .dvs IS A PRIME>2, NEVER DIVIDES EVENLY!
1144U_32 Divide(struct scratchpad *sp, S_32 bits)
1145{ static U_32 ret;
1146  /*
1147  One of the keys to the CRYPTION program is the fact that this
1148  function operates on EXTERNAL data.  That modified data can be --
1149  and is -- simply retained until this function is called to operate
1150  on it some more.  Thus we do PART of an overall long division now --
1151  just a few bits of it -- some more bits later, some more bits still
1152  later still, and so on.  There will be up to 64K division-operations
1153  in progress!  That is how this program trades memory usage to obtain
1154  speed.  Only a relatively small amount of division is needed to
1155  obtain the pseudo-random numbers used for scrambling data, and it
1156  doesn't have to be re-done to get different pseudo-random numbers --
1157  because all the operations are held in memory, waiting for this: */
1158  ret = 0;                                  // initialize return value
1159  while(sp->dvd > sp->dvs)            // While divisor is smaller than
1160                                                      // to-be-divided
1161    sp->dvd >>= 1; // HALVE the dividend.   Here we do not care at all
1162                   // about keeping the thown-away lowest bit, because
1163                // we expect to be doing this only to convert a random
1164                    // 32-bit number down to the same magnitude of the
1165                // divisor-Prime -- and once done, will not need to be
1166                                     // done again to this ScratchPad.
1167  while(bits > 0)
1168  { ret <<= 1;      // For each bit counted in while() loop, prepare a
1169             // place to hold a One or a Zero (doubles ret by shifting
1170                  // all bits higher one position, "appending" a zero)
1171    if(sp->dvs > sp->dvd)//while divisor is greater than to-be-divided
1172      sp->dvd <<= 1;                       // double/redouble dividend
1173    /*    The two main steps in this loop are doing "long division" in
1174     Base Two, totally analogous to familiar Base Ten stuff.  Consider
1175     this Base Ten example:
1176           __0.009708_ <-appended zeros retained when can't subtract
1177       103 | 1.000     <-append and keep 2 zeros in quotient, but
1178              _927_    <-subtract after 3rd; nonzero put in quotient
1179                730    <-append a zero (multiply by Ten), but quotient
1180               _721_   <-gets a nonzero because we can subtract again
1181                  900  <-append/keep 1 more zero above
1182                 _824_ <-but 2nd appended zero allows subtraction
1183     Note in Base Ten each appended Zero means multiply-by-Ten, while
1184     in Base Two it means multiply-by-Two -- doubling, in other words.
1185     Also in Base Two, the only digit (and multiplier) besides Zero is
1186     ONE (not 9, 7 or 8 as above), which is why Base Two division can
1187     subtract without multiplying.                                  */
1188      // Below is the subtraction step; if ok-to-do, the Zero that was
1189       // appended to  ret  via bit-shift/doubling will be incremented
1190    if(sp->dvs < sp->dvd)    // TEST: is divisor smaller than dividend
1191                                                 // (can we subtract)?
1192    { sp->dvd -= sp->dvs;          // Division in Base Two consists of
1193     // subtracting the divisor from the (doubled/redoubled) dividend.
1194        // The remainder becomes new dividend for next division steps.
1195      ret++; // Obviously if no subtraction occurs, appended Zero will
1196                                                       // be unchanged
1197    }   // Ret is a partial quotient, the wanted string of bits, mixed
1198                                                     // Zeros and Ones
1199    bits--; /*    Each iteration of overall loop represents one bit in
1200    Base-Two division.  Since 16 or fewer bits are normally sought,
1201    next test exists for those rare occasions when we want to know
1202    that a prime's reciprocal-PERIOD is very long.  For these tests,
1203    dvs is set to the prime P, dvd is set to P-1, and the bits
1204    parameter is set to 100,020.  As it happens, when taking a
1205    reciprocal, the last division of a prime's period will always have
1206    a remainder of 1, while the MIDDLE division during the period will
1207    have a remainder of P-1 (this is a consequence of the two halves
1208    of a period adding their digits to a constant value).  So, by
1209    starting with a dividend of P-1 for dvd before calling this
1210    function, and seeking a constant of 1 as the current remainder...
1211    if a remainder of 1 appears before we countdown bits from 100,020
1212    to 20, then we know that the HALF-PERIOD is less than 100,000
1213    digits, and this is unacceptable for CRYPTION.  (Note 100,000
1214    loops are actually done quite quickly, since bit-shifts and
1215    subtractions are processed FAST.)  */
1216    if(bits > 20)   // Only do this test when wanting large quantities
1217                                                            // of bits
1218    { ret = 0;        // Prevent accidental return value of 0xFFFFFFFF
1219                                                       // by main loop
1220      if(sp->dvd == 1)
1221        return(0xFFFFFFFF);     // Let period-testing routine know the
1222                                           // divisor is unacceptable!
1223  } }
1224  return(ret);  // Note most return values will range 16 bits or less,
1225};                                                    // max of 0xFFFF




			
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