home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / cbw / part05 / cipher.c next >
Encoding:
C/C++ Source or Header  |  1987-06-17  |  9.4 KB  |  436 lines

  1. /* 
  2.  * Routines for operating on cipher blocks.
  3.  *
  4.  * Robert W. Baldwin, January 1985.
  5.  */
  6.  
  7.  
  8. #include    <stdio.h>
  9. #include    <math.h>
  10. #include    "window.h"
  11. #include    "specs.h"
  12. #include    "cipher.h"
  13.  
  14.  
  15. #define    DEBUG    FALSE
  16.  
  17.  
  18. /* Decode the cblock into pblock using perm.
  19.  * Return FALSE if find a non-ascii character, else 1.
  20.  */
  21. decode(cblock, pblock, perm)
  22. char    cblock[];
  23. int        pblock[];
  24. int        perm[];
  25. {
  26. int iplace;        /* Index into ciphertext block. */
  27. int spchar;        /* Plaintext char not unshifted. */
  28. int pchar;        /* Plaintext char. */
  29. int    good;        /* Plaintext doesn't have any unacceptable chars in it. */
  30.  
  31. good = TRUE;
  32. for (iplace = 0 ; iplace < BLOCKSIZE ; iplace++) {
  33.     spchar = perm[(iplace+cblock[iplace])&MODMASK];
  34.     if (spchar == -1) {
  35.         pchar = -1;
  36.         }
  37.     else {
  38.         pchar = (spchar-iplace) & MODMASK;
  39.         if (notascii(pchar))  {
  40.             good = FALSE;
  41.             }
  42.         }
  43.     pblock[iplace] = pchar;
  44.     }
  45. return(good);
  46. }
  47.  
  48.  
  49. /* Searches for string in block.
  50.  * Returns position it found that didn't have conflicts, or -1.
  51.  * If found, it will add to perm all the deduced wirings.
  52.  * If perm is not initially all -1, search will not accept any
  53.  * position that conflicts with the initial wirings, nor will
  54.  * it mutate any of those wirings.
  55.  */
  56. int    search(cipher, perm, initpos, thing)
  57. char    *cipher;
  58. int        *perm;
  59. int        initpos;
  60. char    *thing;        /* NULL terminated string. */
  61. {
  62.     int    iplace;        /* Current placement of trigram in plaintext block. */
  63.     int i;            /* Index for initializing arrays. */
  64.     int    pchar;        /* Plaintext character. */
  65.     int    spchar;        /* Plaintext character cyclically shifted by its pos. */
  66.     int    *spstkp;
  67.     int    spstack[BLOCKSIZE];
  68.     int    *scstkp;
  69.     int    scstack[BLOCKSIZE];
  70.     int    scchar;        /* Ciphertext character cyclically shifted by its pos. */
  71.     int    offset;
  72.     int    thinglen;
  73.     char *p;
  74.  
  75.     p = thing;
  76.     for (thinglen = 0 ; *p++ != 0 ; thinglen++) ;
  77.  
  78.   for (iplace = initpos ; iplace < BLOCKSIZE-thinglen ; iplace++) {
  79.     spstkp = spstack;
  80.     scstkp = scstack;
  81.     for (offset = 0 ; offset < thinglen ; offset++) {
  82.         pchar = ((int) thing[offset]);
  83.         spchar = (pchar + iplace + offset) & MODMASK;
  84.         scchar = (cipher[iplace + offset] + iplace + offset) & MODMASK;
  85.         if ((perm[spchar] != -1  ||  perm[scchar] != -1)
  86.          && (perm[spchar] != scchar))  {
  87.                 while (spstkp > &spstack[0]) perm[*(--spstkp)] = -1;
  88.                 while (scstkp > &scstack[0]) perm[*(--scstkp)] = -1;
  89.                 goto nextplace;
  90.                 }
  91.         perm[spchar] = scchar;
  92.         *spstkp++ = spchar;
  93.         perm[scchar] = spchar;
  94.         *scstkp++ = scchar;
  95.         }
  96.     return(iplace);
  97.     nextplace: ;
  98.     }
  99.   return(-1);
  100. }
  101.  
  102.  
  103. /* Fill in the pvec with the characters decoded from assuming
  104.  * that the ciphertext character at position firstpos maps to
  105.  * the plaintext character firstplain.
  106.  * Return the number of characters added to pvec not counting
  107.  * the termination character (NONE) that we always add.
  108.  * If any of the characers decoded to non-ascii values, then
  109.  * return ERROR (a negative number).
  110.  * Also return ERROR if the guess would conflict with the ones already
  111.  * in eci->perm.
  112.  */
  113. int    decode_class(eci, firstpos, firstplain, pvec)
  114. ecinfo    *eci;
  115. int        firstpos;
  116. int        firstplain;
  117. int        *pvec;
  118. {
  119.     int        x,y;
  120.  
  121.     firstpos = MODMASK & firstpos;
  122.     firstplain = CHARMASK & firstplain;
  123.  
  124.     x = eci->scipher[firstpos];
  125.     y = MODMASK & (firstplain + firstpos);
  126.  
  127.     return(decode_wire(eci, x, y, pvec));
  128. }
  129.  
  130.  
  131. /* Fill in the pvec with the characters decoded from assuming
  132.  * that the permutation for this block maps x to y and vice-versa.
  133.  * Return the number of characters added to pvec not counting
  134.  * the termination character (NONE) that we always add (but not if
  135.  * we return ERROR).
  136.  * If any of the characers decoded to non-ascii values, then
  137.  * return ERROR (a negative number).
  138.  * Also return ERROR if the guess would conflict with the ones already
  139.  * in eci->perm.
  140.  * Also return ERROR if x == y.
  141.  */
  142. int    decode_wire(eci, x, y, pvec)
  143. ecinfo    *eci;
  144. int        x;
  145. int        y;
  146. int        *pvec;
  147. {
  148.     decode_wire_but(eci, x, y, pvec, NONE, NONE);
  149. }
  150.  
  151.  
  152. /* Fill in the pvec with the characters decoded from assuming
  153.  * that the permutation for this block maps x to y and vice-versa.
  154.  * Return the number of characters added to pvec not counting
  155.  * the termination character (NONE) that we always add (but not if
  156.  * we return ERROR).
  157.  * If any of the characers decoded to non-ascii values, then
  158.  * return ERROR (a negative number).
  159.  * Also return ERROR if the guess would conflict with the ones already
  160.  * in eci->perm.
  161.  * Also return ERROR if x == y.
  162.  * DO NOT include any characters in the postions ranging from
  163.  * first to last inclusive.
  164.  */
  165. int    decode_wire_but(eci, x, y, pvec, first, last)
  166. ecinfo    *eci;
  167. int        x;
  168. int        y;
  169. int        *pvec;
  170. int        first, last;
  171. {
  172.     int        delta;
  173.     int        pos, firstflag;
  174.     int        c,i;
  175.     int        firstpos;
  176.     int        otherpos;
  177.     int        pvecindex;
  178.  
  179.  
  180.     pvecindex = 0;
  181.     pvec[pvecindex] = NONE;
  182.     x = x & MODMASK;
  183.     y = y & MODMASK;
  184.     if (first > last)  {
  185.         printf("\ndecode_wire_but called with first > last.\n");
  186.         exit(0);
  187.         }
  188.  
  189.     if (perm_conflict(eci->perm,x,y)  ||  x == y) {
  190. #if DEBUG
  191.         printf("CANNOT accept the guess of %d wired to %d.\n",
  192.                 x, y);
  193. #endif
  194.         return(ERROR);
  195.         }
  196.  
  197.     firstpos = eci->permmap[x];
  198.     if (firstpos != NONE) {
  199.         delta = y - x;
  200.         for_pos_in_class(pos, firstpos) {
  201.             if (first <= pos && pos <= last)  continue;
  202.             c = MODMASK & (eci->scipher[pos] + delta - pos);
  203.             if (c != (c & CHARMASK))  return(ERROR);
  204.             pvec[pvecindex++] = c;
  205.             }
  206.         }
  207.  
  208.     otherpos = eci->permmap[y];
  209.     if (otherpos != NONE) {
  210.         delta = x - y;
  211.         for_pos_in_class(pos, otherpos) {
  212.             if (first <= pos && pos <= last)  continue;
  213.             c = MODMASK & (eci->scipher[pos] + delta - pos);
  214.             if (c != (c & CHARMASK))  return(ERROR);
  215.             pvec[pvecindex++] = c;
  216.             }
  217.         }
  218.  
  219.     pvec[pvecindex] = NONE;
  220.     return(pvecindex);
  221. }
  222.  
  223.  
  224.  
  225. /* Fill in an interger buffer from the characters of a byte buffer.
  226.  * The buffers must have equal lengths.
  227.  */
  228. char2buf(cptr, iptr, length)
  229. char    *cptr;
  230. int        *iptr;
  231. int        length;
  232. {
  233.     int        i;
  234.  
  235.     for (i = 0 ; i < length ; i++)  {
  236.         *iptr++ = MODMASK & (*cptr++);
  237.         }
  238. }
  239.  
  240.  
  241. /* Fill in a character buffer from the integers of a byte buffer.
  242.  * If the integer value is NONE, use nonechar instead.
  243.  * The buffers must have equal lengths.
  244.  */
  245. buf2char(cptr, iptr, length, nonechar)
  246. char    *cptr;
  247. int        *iptr;
  248. int        length;
  249. int        nonechar;
  250. {
  251.     int        i;
  252.  
  253.     for (i = 0 ; i < length ; i++)  {
  254.         if (*iptr != NONE)  {
  255.             *cptr++ = MODMASK & (*iptr++);
  256.             }
  257.         else {
  258.             *cptr++ = nonechar;
  259.             }
  260.         }
  261. }
  262.  
  263.  
  264.  
  265. /* Fill in an interger vector with the characters from a null
  266.  * terminated string.  The interger vector is terminated by the
  267.  * value NONE.
  268.  */
  269. str2pvec(cptr, iptr)
  270. char    *cptr;
  271. int    *iptr;
  272. {
  273.     while (*iptr++ = (MODMASK & *cptr++));
  274.     *(--iptr) = NONE;
  275. }
  276.  
  277.  
  278. /* Fill in a null terminated string with the integers from a NONE
  279.  * terminated vector.
  280.  */
  281. pvec2str(cptr, iptr)
  282. char    *cptr;
  283. int        *iptr;
  284. {
  285.     while (*iptr != NONE)  {
  286.         *cptr++ = (MODMASK & *iptr++);
  287.         }
  288.     *cptr = 0;
  289. }
  290.  
  291.  
  292. /* Print a pvec on a stream.
  293.  */
  294. print_pvec(out, pvec)
  295. FILE    *out;
  296. int        *pvec;
  297. {
  298.     int        i,c;
  299.  
  300.     i = 0;
  301.     while (*pvec != NONE)  {
  302.         c = *pvec++;
  303.         if (i++ % 20 == 0) fprintf(out,"\n");
  304.         write_char(out, c);
  305.         }
  306.     fprintf(out,"\n");
  307. }
  308.  
  309.  
  310. /* Returns number of wires added to permvec assuming
  311.  * that plaintext str occurs at pos.
  312.  * Fills in permvec.  Returns -1 if conflict.
  313.  * Note that the last entry in permvec is marked by x == -1.
  314.  * The permvec will not have duplicates and will not conflict
  315.  * with the perm specified by eci->perm.
  316.  */
  317. int        permvec_from_string(eci, str, pos, permvec)
  318. ecinfo    *eci;
  319. char    *str;
  320. int        pos;
  321. perment    permvec[];
  322. {
  323.     int        wcount;
  324.     int        i, c, tmp;
  325.     int        x,y;
  326.     char    *cp;
  327.     int        curpos;
  328.  
  329.     if (pos < 0 || pos >= BLOCKSIZE)  {return(ERROR);}
  330.  
  331.     wcount = 0;
  332.     curpos = pos;
  333.     cp = str;
  334.     while ((c = (*cp & MODMASK)) != 0  &&  (curpos < BLOCKSIZE))  {
  335.         x = eci->scipher[curpos];
  336.         y = MODMASK & (c + curpos);
  337.         if (perm_conflict(eci->perm, x, y))  {
  338.             permvec[0].x = NONE;
  339.             return(ERROR);
  340.             }
  341.         for (i = 0 ; i < wcount ; i++) {
  342.             if ( (permvec[i].x == x  &&  permvec[i].y != y)
  343.               || (permvec[i].x == y  &&  permvec[i].y != x)
  344.               || (permvec[i].y == x  &&  permvec[i].x != y)
  345.               || (permvec[i].y == y  &&  permvec[i].x != x) )  {
  346. #if DEBUG
  347.                 printf("Conflict within permvec.\n");
  348. #endif
  349.                 permvec[0].x = NONE;
  350.                 return(ERROR);
  351.                 }
  352.             if ( (permvec[i].x == x  &&  permvec[i].y == y)
  353.               || (permvec[i].x == y  &&  permvec[i].y == x) )
  354.                 break;
  355.             }
  356.         permvec[i].x = x;
  357.         permvec[i].y = y;
  358.         if (i >= wcount)  wcount++;
  359.          curpos++;
  360.         cp++;
  361.         }
  362.  
  363.     permvec[wcount].x = NONE;
  364.     return(wcount);
  365. }
  366.  
  367.  
  368.  
  369. /* Copy routine for permvecs.
  370.  */
  371. permvec_copy(from, to, maxnum)
  372. perment    from[];
  373. perment    to[];
  374. int        maxnum;
  375. {
  376.     int        i;
  377.  
  378.     for (i = 0 ; i < maxnum ; i++)  {
  379.         to[i] = from[i];
  380.         if (from[i].x == NONE) break;
  381.         }
  382. }
  383.  
  384.  
  385. /* Copy routine for pvecs.
  386.  */
  387. pvec_copy(from, to, maxnum)
  388. int        from[];
  389. int        to[];
  390. int        maxnum;
  391. {
  392.     int        i;
  393.  
  394.     for (i = 0 ; i < maxnum ; i++)  {
  395.         to[i] = from[i];
  396.         if (from[i] == NONE) break;
  397.         }
  398. }
  399.  
  400.  
  401.  
  402. /* Fills in pvec with the plaintext characters deduced
  403.  * from the wires in permvec that are not in the positions
  404.  * ranging from butfirst to butlast.  Returns -1 if any
  405.  * non-ascii chars are deduced, else count of chars.
  406.  */
  407. int        permvec2pvec(eci, permvec, pvec, butfirst, butlast)
  408. ecinfo    *eci;
  409. perment    permvec[];
  410. int        pvec[];
  411. int        butfirst;
  412. int        butlast;
  413. {    int        i, x, y;
  414.     int        ccount;
  415.     int        added;
  416.  
  417.     ccount = 0;
  418.  
  419.     for (i = 0 ; permvec[i].x != NONE ; i++)  {
  420.         if (ccount >= BLOCKSIZE-1) break;
  421.         x = permvec[i].x;
  422.         y = permvec[i].y;
  423.         added = decode_wire_but(eci, x, y, &(pvec[ccount]), butfirst, butlast);
  424.         if (added < 0)  {
  425. #if DEBUG
  426.             printf("permvec wire decodes to non-ascii.\n");
  427. #endif
  428.             pvec[0] = -1;
  429.             return(ERROR);
  430.             }
  431.         ccount += added;
  432.         }
  433.     pvec[ccount] = -1;
  434.     return(ccount);
  435. }
  436.