home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume14
/
okbridge2
/
part12
/
cipher.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-27
|
7KB
|
279 lines
/* cipher.c
*
! Copyright (C) 1990-1992 by Matthew Clegg. All Rights Reserved
!
! OKbridge is made available as a free service to the Internet.
! Accordingly, the following restrictions are placed on its use:
!
! 1. OKbridge may not be modified in any way without the explicit
! permission of Matthew Clegg.
!
! 2. OKbridge may not be used in any way for commercial advantage.
! It may not be placed on for-profit networks or on for-profit
! computer systems. It may not be bundled as part of a package
! or service provided by a for-profit organization.
!
! If you have questions about restrictions on the use of OKbridge,
! write to mclegg@cs.ucsd.edu.
!
! DISCLAIMER: The user of OKbridge accepts full responsibility for any
! damage which may be caused by OKbridge.
*
* This file implements procedures for a very simple cipher which
* is used to encode crucial parts of the files which contain
* email duplicate hands.
*
* The intention of this cipher is to make the contents
* of an email duplicate file non-obvious. This cipher is certainly
* not intended to be difficult to break -- it is simply intended to
* allow email duplicate files to be manipulated (e.g., mailed, copied,
* etc.) without having their contents revealed.
*
* The cipher that we use is based upon the following principles:
* 1. Only the 64 characters a-zA-Z0-9+- are encoded.
* This defines a function h(c) for characters c which is 0
* if c is not coded and which is a unique integer in the
* range [1,64] if c is coded.
* 2. An initial permutation p the integers [1,64] is chosen.
* 3. Given a string s, a permuted string s' is computed according
* to the following formula:
*
* s'[i] = s[i] if h[s[i]] = 0,
* h^-1 [ p[ (h[s[i]] + i) mod 64 ]] otherwise.
*
* In other words, the encoding of a character is determined
* by a fixed permutation and by its index in the string.
*
* An email duplicate file begins with a header line identifying the
* fact that it is an email duplicate file. The following line contains
* the permutation which has been used to encode the file. The
* succeeding lines are a mixture of plain-text and coded lines.
* Coded lines begin with an exclamation point '!'.
*/
#include <stdio.h>
#include <string.h>
#include "cipher.h"
extern char *malloc ();
#ifdef GCC
extern int fgetc ();
extern fprintf ();
#endif
/* extern long random (); */
extern int rand ();
#define random(n) ((rand () / 64) % n)
static int cipher_mapping [128]; /* the function h above. */
static int cipher_unmapping [128]; /* h^-1, where defined */
static int mapping_is_initialized = 0;
#define LINEBUF_SIZE 128
static char line_buf[LINEBUF_SIZE];
static void Initialize_Cipher_Mapping ()
{
int i;
for (i = 0; i < 128; i++)
cipher_mapping[i] = 0;
for (i = 0; i < CIPHER_SIZE1; i++)
cipher_unmapping[i] = 0;
for (i = 'A'; i <= 'Z'; i++)
cipher_mapping[i] = i - 'A' + 1;
for (i = 'a'; i <= 'z'; i++)
cipher_mapping[i] = i - 'a' + 26 + 1;
for (i = '0'; i <= '9'; i++)
cipher_mapping[i] = i - '0' + 52 + 1;
cipher_mapping['+'] = 63;
cipher_mapping['-'] = 64;
for (i = 0; i < 128; i++)
if (cipher_mapping[i])
cipher_unmapping[cipher_mapping[i]] = i;
}
static int Read_Line (f, buf, buflen)
FILE *f; char *buf; int buflen;
/* Reads a line of up to buflen characters from the file f into
the buffer buf. Returns the number of characters read, or -1
if EOF reached.
*/
{
int n, ch;
if (fgets(buf, buflen, f) == NULL)
return (-1);
n = strlen(buf);
if ((n >= buflen) && (buf[n-1] != '\n'))
do
{ ch = fgetc (f); }
while ((ch != '\n') && (ch != EOF));
else
buf[--n] = '\0';
return (n);
}
int Read_Cipher_Descriptor (f, c)
FILE *f;
Cipher *c;
/* Reads a cipher descriptor from the file f. Returns 0 if successful
or 1 if an error occurred. */
{
char code_buffer[80];
int i, n;
if (!mapping_is_initialized)
Initialize_Cipher_Mapping ();
n = Read_Line (f, code_buffer, 80);
if (n < CIPHER_SIZE)
return (1);
for (i = 0; i < CIPHER_SIZE; i++)
c->encoding[i+1] = cipher_mapping[(int) code_buffer[i]];
for (i = 1; i < CIPHER_SIZE1; i++)
c->decoding[c->encoding[i]] = i;
return (0);
}
void Write_Cipher_Descriptor (f, c)
FILE *f;
Cipher *c;
/* Writes the cipher descriptor c to the file f. */
{
char code_buffer[CIPHER_SIZE1];
int i;
for (i = 0; i < CIPHER_SIZE; i++)
code_buffer[i] = cipher_unmapping[c->encoding[i+1]];
code_buffer[CIPHER_SIZE] = '\0';
fprintf (f, "%s\n", code_buffer);
}
void Create_Cipher_Descriptor (f, c)
FILE *f;
Cipher *c;
/* Fills the structure c with a randomly generated cipher descriptor. */
{
int i, t, r;
if (!mapping_is_initialized)
Initialize_Cipher_Mapping ();
c->encoding[0] = c->decoding[0] = 0;
for (i = 1; i < CIPHER_SIZE1; i++)
c->encoding [i] = i;
for (i = 1; i < CIPHER_SIZE; i++) {
r = random (CIPHER_SIZE + 1 - i);
t = c->encoding[i+r];
c->encoding[i+r] = c->encoding[i];
c->encoding[i] = t;
};
for (i = 1; i < CIPHER_SIZE1; i++)
c->decoding[c->encoding[i]] = i;
}
void Encode_String (c, source, dest)
Cipher *c;
char *source;
char *dest;
/* Encodes the string in source, placing the result in dest.
If c == NULL, then simply copies source to dest. */
{
int i, base_code;
if (c == NULL) {
strcpy (dest, source);
return;
}
for (i = 0; source[i] != '\0'; i++)
if ((base_code = cipher_mapping[(int) (source[i])]) != 0)
dest[i] = cipher_unmapping
[c->encoding [(base_code + 3*i) % CIPHER_SIZE + 1]];
else
dest[i] = source[i];
dest[i] = '\0';
}
void Decode_String (c, source, dest)
Cipher *c;
char *source;
char *dest;
/* Decodes the string in source, placing the result in dest.
If c == NULL, then simply copies source to dest. */
{
int i, p, base_code;
if (c == NULL) {
strcpy (dest, source);
return;
}
for (i = 0; source[i] != '\0'; i++)
if ((base_code = cipher_mapping[(int) (source[i])]) != 0) {
p = (c->decoding[base_code] + 3*CIPHER_SIZE - 3*i)
% CIPHER_SIZE - 1;
if (p == 0) p = CIPHER_SIZE;
dest[i] = cipher_unmapping[p];
} else
dest[i] = source[i];
dest[i] = '\0';
}
void Write_Ciphered_Line (f, c, buf)
FILE *f;
Cipher *c;
char *buf;
/* Encodes buf using the cipher c and writes it to the file f.
The first character written to the file is an exclamation point '!' */
{
if (c == NULL)
fprintf (f, "%s\n", buf);
else {
Encode_String (c, buf, line_buf);
fprintf (f, "!%s\n", line_buf);
}
}
int Read_Ciphered_Line (f, c, buf, buflen)
FILE *f;
Cipher *c;
char *buf;
int buflen;
/* Reads a line of up to buflen characters from the file f and decodes
the line using the cipher c. If the first character of the line
is not an exclamation point '!', then the line is assumed to be
in plain text. Returns the number of characters read or -1 if
end of file reached.
*/
{
int n;
buf[0] = '\0';
n = Read_Line (f, line_buf, buflen);
if (n <= 0)
return (n);
if (line_buf[0] == '!') {
Decode_String (c, line_buf+1, buf);
return (n-1);
} else {
strcpy (buf, line_buf);
return (n);
}
}