Charles.Forsyth20060303644188019 years agoHistory
254 lines · 4.8 KB · C
RawDownload
/* * Copyright © 2002 Vita Nuova Holdings Limited.  All rights reserved. */#include <lib9.h>#include <bio.h> /* CBC, ECB, integrate, SSL */ #define KEYLEN	52 #define	MODA	0x10000#define	MODM	0x10001#define	MASKA	(MODA-1) #define 	OP1(x, y)		((x) ^ (y))#define	OP2(x, y)		(((x) + (y)) & MASKA)#define 	OP3(x, y)		mod(x, y) #define	OP2INV(x)	(-(x))#define	OP3INV(x)	inv(x) #define BIGEND(k, i)	((k[i]<<8)|k[i+1])#define MSB(x)		((x)>>8)#define LSB(x)		((x)&0xff) static ushortmod(ushort x, ushort y){	ushort q, r;	uint z; 	if (x == 0)		return 1-y;	if (y == 0)		return 1-x;	z = (uint)x*(uint)y;	q = z >> 16;	r = z & MASKA;	return r-q+(r<q);} static ushort inv(ushort x){	int q, r0, r1, r2, v0, v1, v2; 	if (x <= 1)		return x;	r0 = MODM;	r1 = x;	v0 = 0;	v1 = 1;	while (r1 != 0) {		q = r0/r1;		r2 = r0-q*r1;		v2 = v0-q*v1;		r0 = r1;		r1 = r2;		v0 = v1;		v1 = v2;	}	if (v0 < 0)		v0 += MODM;	return v0 & MASKA;} static voididea_key_setup_decrypt(ushort ek[KEYLEN], ushort dk[KEYLEN]){	int i; 	for (i = 0; i < 54; i += 6) {		dk[i] = OP3INV(ek[48-i]);		dk[i+1] = OP2INV(ek[50-i]);		dk[i+2] = OP2INV(ek[49-i]);		dk[i+3] = OP3INV(ek[51-i]);		if (i < 48) {			dk[i+4] = ek[46-i];			dk[i+5] = ek[47-i];		}	}} voididea_key_setup(uchar key[16], ushort ek[2*KEYLEN]){	int i, j;	ushort tmp, *e = ek; 	for (i = 0; i < 8; i++)		ek[i] = BIGEND(key, 2*i);	for (i = 8, j = 1; i < KEYLEN; i++, j++) {		ek[i] = (e[j&7]<<9)|(e[(j+1)&7]>>7);		if (((i+1) & 7) == 0)			e += 8;	}	tmp = ek[49];	ek[49] = ek[50];	ek[50] = tmp;	idea_key_setup_decrypt(ek, &ek[KEYLEN]);} voididea_cipher(ushort key[2*KEYLEN], uchar text[8], int decrypting){	int i;	ushort *k;	ushort x[4];	ushort tmp, yout, zout; 	k = decrypting ? &key[KEYLEN] : key;	for (i = 0; i < 4; i++)		x[i] = BIGEND(text, 2*i);	for (i = 0; i < 17; i++) {		if (!(i&1)) {		/* odd round */			x[0] = OP3(x[0], k[3*i]);			tmp = OP2(x[2], k[3*i+2]);			x[2] = OP2(x[1], k[3*i+1]);			x[3] = OP3(x[3], k[3*i+3]);			x[1] = tmp;		}		else {			tmp = OP3(k[3*i+1], OP1(x[0], x[1]));			yout = OP3(OP2(tmp, OP1(x[2], x[3])), k[3*i+2]);			zout = OP2(tmp, yout);			x[0] = OP1(x[0], yout);			x[1] = OP1(x[1], yout);			x[2] = OP1(x[2], zout);			x[3] = OP1(x[3], zout);		}	}	for (i = 0; i < 4; i++) {		text[2*i] = MSB(x[i]); 		text[2*i+1] = LSB(x[i]);	}} static voiddecerr(char *s){	fprint(2, "decrypt error: %s (wrong password ?)\n", s);	exits("decrypt");} voidmain(int argc, char **argv){/*	uchar key[] = { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,			        0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 };	uchar plain[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 };	uchar cipher[] = { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 };	uchar tmp[8];*/	ushort edkey[2*KEYLEN];	uchar obuf[8], buf[8], key[16];	long i, m, n, om;	int dec, stdin = 0, stdout = 1;	Biobuf *bin, *bout; /*	memcpy(tmp, plain, 8);	idea_key_setup(key, edkey);	idea_cipher(edkey, tmp, 0);	if (memcmp(tmp, cipher, 8)) {		print("encrypt wrong\n");		exits("");	}	idea_cipher(edkey, tmp, 1);	if (memcmp(tmp, plain, 8)) {		print("decrypt wrong\n");		exits("");	}*/ 	if((argc != 3 && argc != 4) || (strcmp(argv[1], "-e") != 0 && strcmp(argv[1], "-d") != 0) || strlen(argv[2]) != 16){		fprint(2, "usage: idea -[e | d] <16 char key> [inputfile]\n");		exits("usage");	}	dec = strcmp(argv[1], "-d") == 0;	if(argc == 4){		char s[128]; 		stdin = open(argv[3], OREAD);		if(stdin < 0){			fprint(2, "cannot open %s\n", argv[3]);			exits("");		}		strcpy(s, argv[3]);		if(dec){			if(strcmp(s+strlen(s)-3, ".id") != 0){				fprint(2, "input file not a .id file\n");				exits("");			}			s[strlen(s)-3] = '\0';		}		else			strcat(s, ".id");		stdout = create(s, OWRITE, 0666);		if(stdout < 0){			fprint(2, "cannot create %s\n", s);			exits("");		}	}	for(i = 0; i < 16; i++)		key[i] = argv[2][i];	idea_key_setup(key, edkey);	m = om = 0;	bin = (Biobuf*)malloc(sizeof(Biobuf));	bout = (Biobuf*)malloc(sizeof(Biobuf));	Binit(bin, stdin, OREAD);	Binit(bout, stdout, OWRITE);	for(;;){		n = Bread(bin, &buf[m], 8-m);		if(n <= 0)			break;		m += n;		if(m == 8){			idea_cipher(edkey, buf, dec);			if(dec){	/* leave last block around */				if(om > 0)					Bwrite(bout, obuf, 8);				memcpy(obuf, buf, 8);				om = 8;			}			else				Bwrite(bout, buf, 8);			m = 0;		}	}	if(dec){		if(om != 8)			decerr("no last block");		if(m != 0)			decerr("last block not 8 bytes long");		m = obuf[7];		if(m < 0 || m > 7)			decerr("bad modulus");		for(i = m; i < 8-1; i++)			if(obuf[i] != 0)				decerr("byte not 0");		Bwrite(bout, obuf, m);	}	else{		for(i = m; i < 8; i++)			buf[i] = 0;		buf[7] = m;		idea_cipher(edkey, buf, dec);		Bwrite(bout, buf, 8);	}	Bflush(bout);	Bterm(bin);	Bterm(bout);}