home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume14 / okbridge2 / part12 / cipher.c < prev    next >
C/C++ Source or Header  |  1993-01-27  |  7KB  |  279 lines

  1. /* cipher.c
  2.  *
  3.  ! Copyright (C) 1990-1992 by Matthew Clegg.  All Rights Reserved
  4.  ! 
  5.  ! OKbridge is made available as a free service to the Internet.
  6.  ! Accordingly, the following restrictions are placed on its use:
  7.  ! 
  8.  ! 1.  OKbridge may not be modified in any way without the explicit 
  9.  !     permission of Matthew Clegg.  
  10.  ! 
  11.  ! 2.  OKbridge may not be used in any way for commercial advantage.
  12.  !     It may not be placed on for-profit networks or on for-profit
  13.  !     computer systems.  It may not be bundled as part of a package
  14.  !     or service provided by a for-profit organization.
  15.  ! 
  16.  ! If you have questions about restrictions on the use of OKbridge,
  17.  ! write to mclegg@cs.ucsd.edu.
  18.  ! 
  19.  ! DISCLAIMER:  The user of OKbridge accepts full responsibility for any
  20.  ! damage which may be caused by OKbridge.
  21.  *
  22.  * This file implements procedures for a very simple cipher which
  23.  * is used to encode crucial parts of the files which contain
  24.  * email duplicate hands.
  25.  *
  26.  * The intention of this cipher is to make the contents
  27.  * of an email duplicate file non-obvious.  This cipher is certainly
  28.  * not intended to be difficult to break -- it is simply intended to
  29.  * allow email duplicate files to be manipulated (e.g., mailed, copied,
  30.  * etc.) without having their contents revealed.
  31.  *
  32.  * The cipher that we use is based upon the following principles:
  33.  *    1.  Only the 64 characters a-zA-Z0-9+- are encoded.
  34.  *        This defines a function h(c) for characters c which is 0
  35.  *        if c is not coded and which is a unique integer in the
  36.  *        range [1,64] if c is coded.
  37.  *    2.  An initial permutation p the integers [1,64] is chosen.
  38.  *    3.  Given a string s, a permuted string s' is computed according
  39.  *        to the following formula:
  40.  *
  41.  *      s'[i] =  s[i]                  if h[s[i]] = 0,
  42.  *           h^-1 [ p[ (h[s[i]] + i) mod 64 ]]    otherwise.
  43.  *
  44.  *        In other words, the encoding of a character is determined
  45.  *        by a fixed permutation and by its index in the string.
  46.  *
  47.  * An email duplicate file begins with a header line identifying the
  48.  * fact that it is an email duplicate file.  The following line contains
  49.  * the permutation which has been used to encode the file.  The
  50.  * succeeding lines are a mixture of plain-text and coded lines.
  51.  * Coded lines begin with an exclamation point '!'.
  52.  */
  53.  
  54. #include <stdio.h>
  55. #include <string.h>
  56.  
  57. #include "cipher.h"
  58.  
  59. extern char *malloc ();
  60.  
  61. #ifdef GCC
  62. extern int  fgetc ();
  63. extern fprintf ();
  64. #endif
  65.  
  66. /* extern long random (); */
  67. extern int rand ();
  68. #define random(n) ((rand () / 64) % n)
  69.  
  70. static  int cipher_mapping [128];    /* the function h above. */
  71. static  int cipher_unmapping [128];    /* h^-1, where defined  */
  72. static  int mapping_is_initialized = 0;
  73.  
  74. #define LINEBUF_SIZE  128
  75. static char line_buf[LINEBUF_SIZE];
  76.  
  77. static void Initialize_Cipher_Mapping ()
  78. {
  79.     int i;
  80.  
  81.     for (i = 0; i < 128; i++)
  82.       cipher_mapping[i] = 0;
  83.     for (i = 0; i < CIPHER_SIZE1; i++)
  84.       cipher_unmapping[i] = 0;
  85.  
  86.     for (i = 'A'; i <= 'Z'; i++)
  87.         cipher_mapping[i] = i - 'A' + 1;
  88.     for (i = 'a'; i <= 'z'; i++)
  89.         cipher_mapping[i] = i - 'a' + 26 + 1;
  90.     for (i = '0'; i <= '9'; i++)
  91.         cipher_mapping[i] = i - '0' + 52 + 1;
  92.     cipher_mapping['+'] = 63;
  93.     cipher_mapping['-'] = 64;
  94.  
  95.     for (i = 0; i < 128; i++)
  96.         if (cipher_mapping[i])
  97.             cipher_unmapping[cipher_mapping[i]] = i;
  98. }
  99.  
  100. static int Read_Line (f, buf, buflen)
  101.     FILE *f; char *buf; int buflen;
  102. /* Reads a line of up to buflen characters from the file f into
  103.    the buffer buf.  Returns the number of characters read, or -1
  104.    if EOF reached.
  105. */
  106. {
  107.     int n, ch;
  108.  
  109.     if (fgets(buf, buflen, f) == NULL)
  110.       return (-1);
  111.  
  112.     n = strlen(buf);
  113.     if ((n >= buflen) && (buf[n-1] != '\n'))
  114.       do
  115.         { ch = fgetc (f); }
  116.       while ((ch != '\n') && (ch != EOF));
  117.     else
  118.       buf[--n] = '\0';
  119.  
  120.     return (n);
  121. }
  122.  
  123. int Read_Cipher_Descriptor (f, c)
  124.      FILE *f;
  125.      Cipher *c;
  126. /*  Reads a cipher descriptor from the file f.  Returns 0 if successful
  127.     or 1 if an error occurred. */
  128. {
  129.   char code_buffer[80];
  130.   int i, n;
  131.  
  132.   if (!mapping_is_initialized)
  133.     Initialize_Cipher_Mapping ();
  134.  
  135.   n = Read_Line (f, code_buffer, 80);
  136.   if (n < CIPHER_SIZE)
  137.     return (1);
  138.  
  139.   for (i = 0; i < CIPHER_SIZE; i++)
  140.     c->encoding[i+1] = cipher_mapping[(int) code_buffer[i]];
  141.   for (i = 1; i < CIPHER_SIZE1; i++)
  142.     c->decoding[c->encoding[i]] = i;
  143.   return (0);
  144. }
  145.  
  146. void Write_Cipher_Descriptor (f, c)
  147.      FILE *f;
  148.      Cipher *c;
  149. /* Writes the cipher descriptor c to the file f. */
  150. {
  151.   char code_buffer[CIPHER_SIZE1];
  152.   int i;
  153.  
  154.   for (i = 0; i < CIPHER_SIZE; i++)
  155.     code_buffer[i] = cipher_unmapping[c->encoding[i+1]];
  156.   code_buffer[CIPHER_SIZE] = '\0';
  157.   fprintf (f, "%s\n", code_buffer);
  158. }
  159.  
  160. void Create_Cipher_Descriptor (f, c)
  161.      FILE *f;
  162.      Cipher *c;
  163. /* Fills the structure c with a randomly generated cipher descriptor. */
  164. {
  165.   int i, t, r;
  166.  
  167.   if (!mapping_is_initialized)
  168.     Initialize_Cipher_Mapping ();
  169.  
  170.   c->encoding[0] = c->decoding[0] = 0;
  171.  
  172.   for (i = 1; i < CIPHER_SIZE1; i++) 
  173.     c->encoding [i] = i;
  174.   for (i = 1; i < CIPHER_SIZE; i++) {
  175.     r = random (CIPHER_SIZE + 1 - i);
  176.     t = c->encoding[i+r]; 
  177.     c->encoding[i+r] = c->encoding[i];
  178.     c->encoding[i] = t;
  179.   };
  180.   
  181.   for (i = 1; i < CIPHER_SIZE1; i++)
  182.     c->decoding[c->encoding[i]] = i;
  183.  
  184. }
  185.  
  186. void Encode_String (c, source, dest)
  187.      Cipher *c;
  188.      char *source;
  189.      char *dest;
  190. /* Encodes the string in source, placing the result in dest.
  191.    If c == NULL, then simply copies source to dest. */
  192. {
  193.   int i, base_code;
  194.   
  195.   if (c == NULL) {
  196.     strcpy (dest, source);
  197.     return;
  198.   }
  199.     
  200.   for (i = 0; source[i] != '\0'; i++)
  201.     if ((base_code = cipher_mapping[(int) (source[i])]) != 0)
  202.       dest[i] = cipher_unmapping 
  203.     [c->encoding [(base_code + 3*i) % CIPHER_SIZE + 1]];
  204.     else
  205.       dest[i] = source[i];
  206.   dest[i] = '\0';
  207.   
  208. }
  209.  
  210. void Decode_String (c, source, dest)
  211.      Cipher *c;
  212.      char *source;
  213.      char *dest;
  214. /* Decodes the string in source, placing the result in dest.
  215.    If c == NULL, then simply copies source to dest. */
  216. {
  217.   int i, p, base_code;
  218.  
  219.   if (c == NULL) {
  220.     strcpy (dest, source);
  221.     return;
  222.   }
  223.  
  224.   for (i = 0; source[i] != '\0'; i++)
  225.     if ((base_code = cipher_mapping[(int) (source[i])]) != 0) {
  226.       p = (c->decoding[base_code] + 3*CIPHER_SIZE - 3*i)
  227.     % CIPHER_SIZE - 1;
  228.       if (p == 0) p = CIPHER_SIZE;
  229.       dest[i] = cipher_unmapping[p];
  230.     } else
  231.       dest[i] = source[i];
  232.  
  233.   dest[i] = '\0';
  234. }
  235.  
  236. void Write_Ciphered_Line (f, c, buf)
  237.      FILE *f;
  238.      Cipher *c;
  239.      char *buf;
  240. /* Encodes buf using the cipher c and writes it to the file f. 
  241.    The first character written to the file is an exclamation point '!' */
  242. {
  243.   if (c == NULL)
  244.     fprintf (f, "%s\n", buf);
  245.   else {
  246.     Encode_String (c, buf, line_buf);
  247.     fprintf (f, "!%s\n", line_buf);
  248.   }
  249. }
  250.  
  251. int Read_Ciphered_Line (f, c, buf, buflen)
  252.      FILE *f;
  253.      Cipher *c;
  254.      char *buf;
  255.      int buflen;
  256. /* Reads a line of up to buflen characters from the file f and decodes
  257.    the line using the cipher c.  If the first character of the line
  258.    is not an exclamation point '!', then the line is assumed to be
  259.    in plain text.  Returns the number of characters read or -1 if
  260.    end of file reached.
  261. */
  262. {
  263.   int n;
  264.  
  265.   buf[0] = '\0';
  266.   n = Read_Line (f, line_buf, buflen);
  267.   if (n <= 0)
  268.     return (n);
  269.  
  270.   if (line_buf[0] == '!') {
  271.     Decode_String (c, line_buf+1, buf);
  272.     return (n-1);
  273.   } else {
  274.     strcpy (buf, line_buf);
  275.     return (n);
  276.   }
  277.   
  278. }
  279.