www.pudn.com > speakfs72.zip > MAIN.C, change:2002-01-05,size:4139b


/* Encrypt/decrypt command compatible with Sun's "des" command */ 
#include <stdio.h> 
 
char iv[8];	/* Initial vector for CBC mode */ 
int block; 
 
main(argc,argv) 
int argc; 
char *argv[]; 
{ 
	int c,cnt,encrypt,decrypt,hexflag; 
	register int i; 
	char key[8],tkey1[20],tkey2[20],*akey,*getpass(); 
	extern char *optarg; 
 
	hexflag = block = encrypt = decrypt = 0; 
	akey = NULL; 
	while((c = getopt(argc,argv,"hedk:b")) != EOF){ 
		switch(c){ 
		case 'h': 
			hexflag++; 
			break; 
		case 'e': 
			encrypt++; 
			break; 
		case 'd': 
			decrypt++; 
			break; 
		case 'k': 
			akey = optarg; 
			break; 
		case 'b': 
			block++; 
			break; 
		} 
	} 
	if(encrypt == 0 && decrypt == 0){ 
		fprintf(stderr,"Usage: des -e|-d [-h] [-k key]\n"); 
		exit(2); 
	} 
	if(akey == NULL){ 
		/* No key on command line, prompt for it */ 
		memset(tkey1,0,sizeof(tkey1)); 
		memset(tkey2,0,sizeof(tkey2)); 
		for(;;){ 
			akey = getpass("Enter key: "); 
			strncpy(tkey1,akey,sizeof(tkey1)); 
			akey = getpass("Enter key again: "); 
			strncpy(tkey2,akey,sizeof(tkey2)); 
			if(strncmp(tkey1,tkey2,sizeof(tkey1)) != 0){ 
				fprintf(stderr,"Key mistyped, try again\n"); 
			} else 
				break; 
		} 
		akey = tkey1; 
	} 
	if(hexflag){ 
		for(i=0;i<16;i++){ 
			if(htoa(akey[i]) == -1){ 
				fprintf(stderr,"Non-hex character in key\n"); 
				exit(1); 
			} 
		} 
		gethex(key,akey,8); 
	} else { 
		strncpy(key,akey,8); 
		/* Set up key, determine parity bit */ 
		for(cnt = 0; cnt < 8; cnt++){ 
			c = 0; 
			for(i=0;i<7;i++) 
				if(key[cnt] & (1 << i)) 
					c++; 
			if((c & 1) == 0) 
				key[cnt] |= 0x80; 
			else 
				key[cnt] &= ~0x80; 
		} 
	} 
	/* Blot out original key */ 
	i = strlen(akey); 
	i = (i < 8) ? i : 8; 
	memset(akey,0,i); 
 
	desinit(0); 
	setkey(key); 
 
	/* Initialize IV to all zeros */ 
	memset(iv,0,8); 
 
	if(encrypt){ 
		doencrypt(); 
	} else { 
		dodecrypt(); 
	} 
} 
/* Encrypt standard input to standard output */ 
doencrypt() 
{ 
	char work[8],*cp,*cp1; 
	int cnt,i; 
 
	for(;;){ 
		if((cnt = fread(work,1,8,stdin)) != 8){ 
			/* Put residual byte count in the last block. 
			 * Note that garbage is left in the other bytes, 
			 * if any; this is a feature, not a bug, since it'll 
			 * be stripped out at decrypt time. 
			 */ 
			work[7] = cnt; 
		} 
		if(!block){ 
			/* CBC mode; chain in last cipher word */ 
			cp = work; 
			cp1 = iv; 
			for(i=8; i!=0; i--) 
				*cp++ ^= *cp1++; 
		} 
		endes(work);	/* Encrypt block */ 
		if(!block){	/* Save outgoing ciphertext for chain */ 
			memcpy(iv,work,8); 
		} 
		fwrite(work,1,8,stdout); 
		if(cnt != 8) 
			break; 
	} 
} 
dodecrypt() 
{ 
	char work[8],nwork[8],ivtmp[8],*cp,*cp1; 
	int cnt,i; 
 
 
	cnt = fread(work,1,8,stdin);	/* Prime the pump */ 
	for(;;){ 
		if(!block){	/* Save incoming ciphertext for chain */ 
			memcpy(ivtmp,work,8); 
		} 
		dedes(work); 
		if(!block){	/* Unchain block, save ciphertext for next */ 
			cp = work; 
			cp1 = iv; 
			for(i=8; i!=0; i--){ 
				*cp++ ^= *cp1++; 
			} 
			memcpy(iv,ivtmp,8); 
		} 
		/* Save buffer pending next read */ 
		memcpy(nwork,work,8); 
		/* Try to read next block */ 
		cnt = fread(work,1,8,stdin); 
		if(cnt != 8){	/* Can "only" be 0 if not 8 */ 
			/* Prev block was last one, write appropriate number 
			 * of bytes 
			 */ 
			cnt = nwork[7]; 
			if(cnt < 0 || cnt > 7){ 
				fprintf(stderr,"Corrupted file or wrong key\n"); 
			} else if(cnt != 0) 
				fwrite(nwork,1,cnt,stdout); 
			exit(0); 
		} else { 
			/* Now okay to write previous buffer */ 
			fwrite(nwork,1,8,stdout); 
		} 
 
	} 
} 
/* Convert hex/ascii nybble to binary */ 
int 
htoa(c) 
char c; 
{ 
	if(c >= '0' && c <= '9') 
		return c - '0'; 
	if(c >= 'a' && c <= 'f') 
		return 10 + c - 'a'; 
	if(c >= 'A' && c <= 'F') 
		return 10 + c - 'A'; 
	return -1; 
} 
/* Convert bytes from hex/ascii to binary */ 
gethex(result,cp,cnt) 
register char *result; 
register char *cp; 
register int cnt; 
{ 
	while(cnt-- != 0){ 
		*result = htoa(*cp++) << 4; 
		*result++ |= htoa(*cp++); 
	} 
} 
#ifdef	DEBUG 
put8(cp) 
register char *cp; 
{ 
	int i; 
 
	for(i=0;i<8;i++){ 
		fprintf(stderr,"%02x ",*cp++ & 0xff); 
	} 
} 
#endif