/* vernam.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <mem.h>
#define BUFFER_SIZE 51200
typedef unsigned long ULONG;
typedef union
{
ULONG a;
char b[4];
} LONGCHAR;
int (*rfunc)();
void (*wfunc)();
void (*ini_s)();
void (*rot_i)();
FILE *fp1, *fp2;
LONGCHAR m;
char *mb3 = m.b + 3;
ULONG rx[521];
ULONG *prx, *prx_end = rx + 521;
ULONG seed, bufsize1;
int count, llen, lshift, rshift;
char buf[8], rndkey[8], keybuf[16];
char *buffer, *blast, *bp;
static int deflag = -1, blen = 8, blena = 0, nwarm1 = 3, nwarm2 = 0;
static char initial[8];
char *initial4 = initial + 4;
/* prototype declaration */
void init_mrnd(void);
void rnd521(void);
ULONG mrnd(void);
void xor(char *in, char *out, int n);
ULONG char_to_long(char *a);
void long_to_char(ULONG m1, ULONG m2);
void rot_initial1(char *set);
void rot_initial2(char *set);
void rot_initial3(char *set);
void rot_initial4(char *set);
void init_crypt(void);
void make_rndkey(void);
void ini_shift1(void);
void ini_shift2(void);
void ini_shift3(void);
void ini_shift4(void);
void vernam(void);
int readdata1(void);
int readdata2(void);
void writedata1(char *data);
void writedata2(char *data);
void openerr(char *kind, char *file);
void usage(char *prog);
void init_mrnd(void)
{
int i, j;
ULONG *p1 = rx, *p2 = rx + 1, *p3, u;
if(seed == 0) seed = 1;
u = 0;
prx = rx;
i = 17;
do
{
j = 32;
do
{
seed *= 1566083941L;
u = (u >> 1) | (++seed & (1UL << 31));
} while(--j);
*prx++ = u;
} while(--i);
*(--prx) = (0xffffffff & (*prx << 23)) ^ (*rx >> 9) ^ *(rx + 15);
p3 = prx++;
while(prx != prx_end)
*prx++ = (0xffffffff & (*p1++ << 23)) ^ (*p2++ >> 9) ^ *p3++;
while(nwarm1--) rnd521(); /* wram up */
prx = rx + 520;
while(nwarm2--) mrnd();
}
void rnd521(void)
{
ULONG *p = rx, *q = rx + 489, *r = rx;
while(q != prx_end) *p++ ^= *q++;
while(p != prx_end) *p++ ^= *r++;
prx = rx;
}
ULONG mrnd(void)
{
if(++prx == prx_end) rnd521();
return *prx;
}
void xor(char *in, char *out, int n)
{
char *p = in, *q = out;
do
{
*q++ ^= *p++;
} while(--n);
}
ULONG char_to_long(char *a)
{
char *p = a, *q = mb3;
*q-- = *p++;
*q-- = *p++;
*q-- = *p++;
*q = *p;
return m.a;
}
void long_to_char(ULONG m1, ULONG m2)
{
char *p = initial, *q = mb3, *r = mb3;
m.a = m1;
*p++ = *q--;
*p++ = *q--;
*p++ = *q--;
*p++ = *q;
m.a = m2;
*p++ = *r--;
*p++ = *r--;
*p++ = *r--;
*p = *r;
}
void rot_initial1(char *set)
{
memcpy(initial, initial4, 4);
memcpy(initial4, set, 4);
}
void rot_initial2(char *set)
{
memcpy(initial, set, 8);
}
void rot_initial3(char *set)
{
ULONG m2;
m2 = char_to_long(initial4);
long_to_char((char_to_long(initial) << lshift) + (m2 >> rshift),
(m2 << lshift) + (char_to_long(set) >> rshift));
}
void rot_initial4(char *set)
{
ULONG s1;
s1 = char_to_long(set);
long_to_char((char_to_long(initial4) << lshift) + (s1 >> rshift),
(s1 << lshift) + (char_to_long(set + 4) >> rshift));
}
void init_crypt(void)
{
char *p, *q;
int i, j, k;
buffer = (char *)malloc(sizeof(char) * BUFFER_SIZE);
if(buffer != NULL)
{
rfunc = readdata1;
wfunc = writedata1;
bp = buffer;
bufsize1 = (BUFFER_SIZE / blen) * blen;
}
else
{
rfunc = readdata2;
wfunc = writedata2;
printf("abort buffer allocation (%ldKB)\n", BUFFER_SIZE / 1024);
}
p = keybuf;
i = 16;
do
{
if(*p >= '0' && *p <= '9') *p -= '0';
else if(*p >= 'a' && *p <= 'f') *p = *p - 'a' + 10;
else if(*p >= 'A' && *p <= 'F') *p = *p - 'A' + 10;
else *p &= 0x0f;
p++;
} while(--i);
p = keybuf;
q = initial;
i = 8;
do
{
j = *p++;
k = (j & 2) * 1024 + (j & 4) * 256 + (j & 1) * 512 + (j & 8) * 32;
j = *p++;
*q++ = k + ((j & 2) * 4 + (j & 4) + (j & 1) * 2 + (j >> 3) & 1);
} while(--i);
p = keybuf;
seed = *p++;
i = 7;
do
{
seed *= 16;
seed += *p++;
} while(--i);
nwarm1 += (keybuf[8] ^ keybuf[15]);
nwarm2 += (keybuf[9] ^ keybuf[14]);
llen = blen * 8 + blena * (keybuf[10] ^ keybuf[13])/ 2;
init_mrnd();
j = 1 + (keybuf[11] ^ keybuf[12]);
do
{
make_rndkey();
xor(rndkey, initial, 8);
} while(--j);
}
void make_rndkey(void)
{
ULONG mm[2];
mm[0] = mrnd();
mm[1] = mrnd();
memcpy(rndkey, mm, 8);
}
void ini_shift1(void)
{
memcpy(initial4, initial, 4);
setmem(initial, 4, 0);
}
void ini_shift2(void)
{
setmem(initial, 8, 0);
}
void ini_shift3(void)
{
long_to_char(0, (char_to_long(initial) >> rshift));
}
void ini_shift4(void)
{
ULONG m1;
m1 = char_to_long(initial);
long_to_char((m1 >> rshift), ((m1 << lshift) + (char_to_long(initial4) >> rshift)));
}
void vernam(void)
{
while((count = rfunc()) != 0)
{
if(count != blen) setmem(buf + count, blen - count, 0);
make_rndkey();
xor(initial, rndkey, 8);
xor(rndkey, buf, blen);
wfunc(buf);
rot_i(rndkey);
}
}
int readdata1(void)
{
ULONG i;
if(bp == buffer)
{
i = fread(buffer, sizeof(char), bufsize1, fp1);
blast = buffer + i;
}
else i = blast - bp;
memcpy(buf, bp, blen);
return (i >= blen)? blen: i;
}
int readdata2(void)
{
return fread(buf, sizeof(char), blen, fp1);
}
void writedata1(char *data)
{
memcpy(bp, data, blen);
if((bp += blen) >= blast)
{
fwrite(buffer, sizeof(char), bp - buffer, fp2);
bp = buffer;
}
}
void writedata2(char *data)
{
fwrite(data, sizeof(char), blen, fp2);
}
void openerr(char *kind, char *file)
{
fprintf(stderr, "Error : %s file(%s) can't open.\n", kind, file);
exit(-1);
}
void usage(char *prog)
{
fprintf(stderr, "Usage : %s [-Ffile] [-Kkey] [-Bn] <-E|-D> file1 file2\n", prog);
fprintf(stderr, " -F : key file definition\n");
fprintf(stderr, " file : key file name\n");
fprintf(stderr, " -K : key definition\n");
fprintf(stderr, " key : 8byte Hexa-decimal code = 16 characters\n");
fprintf(stderr, " -B : Block length direction\n");
fprintf(stderr, " n : Bleck length(1 - 8 Bytes, default = 8)\n");
fprintf(stderr, " -E : Encryption mode\n");
fprintf(stderr, " -D : Decryption mode\n");
fprintf(stderr, " file1 : source file\n");
fprintf(stderr, " file2 : destination file\n\n");
exit(0);
}
int main(int argc, char *argv[])
{
int k, kf = 0, kk = 0;
char *file1, *file2, *p, *q;
if(argc < 2 || *argv[1] != '-') usage(argv[0]);
k = 1;
do
{
switch(tolower(*(argv[k] + 1)))
{
case 'f': kf = k;
break;
case 'k': kk = k;
break;
case 'b': blen = atoi(argv[k] + 2);
if(blen < 1 || blen > 8) usage(argv[0]);
blena = 8 - blen;
break;
case 'd': if(deflag == 0) usage(argv[0]);
deflag = 1;
break;
case 'e': if(deflag == 1) usage(argv[0]);
deflag = 0;
break;
default: usage(argv[0]);
}
} while(*argv[++k] == '-');
if(deflag == -1 || k >= argc) usage(argv[0]);
file1 = argv[k++];
if(k >= argc) usage(argv[0]);
file2 = argv[k];
if(kk != 0)
{
p = argv[kk] + 2;
q = keybuf;
k = 0;
while(k++ < 16 && *p != '\0') *q++ = *p++;
}
else if(kf != 0)
{
fp1 = fopen(argv[kf] + 2, "rb");
if(fp1 == NULL) openerr("key", argv[kf] + 2);
fread(keybuf, sizeof(char), 16, fp1);
fclose(fp1);
}
init_crypt();
if(llen == 32)
{
ini_s = ini_shift1;
rot_i = rot_initial1;
}
else if(llen == 64)
{
ini_s = ini_shift2;
rot_i = rot_initial2;
}
else if(llen < 32)
{
ini_s = ini_shift3;
rot_i = rot_initial3;
lshift = llen;
rshift = 32 - lshift;
}
else
{
ini_s = ini_shift4;
rot_i = rot_initial4;
lshift = llen - 32;
rshift = 32 - lshift;
}
fp1 = fopen(file1, "rb");
if(fp1 == NULL) openerr("source", file1);
fp2 = fopen(file2, "rb");
if(fp2 != NULL)
{
fprintf(stderr, "Error : destination file(%s) already exist.\n", file2);
exit(-1);
}
fp2 = fopen(file2, "wb");
vernam();
if(wfunc == writedata1) fwrite(buffer, sizeof(char), bp - buffer, fp2);
fclose(fp1);
fclose(fp2);
return 0;
}
|