⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cipher.c

📁 des算法实现源码
💻 C
字号:
/* * cipher - a more secure replacement for UNIX crypt program  * * Generic block encipherment/decipherment program  * modified specifically for the Data Encryption Standard using * Cipher Block Feedback (CFB) mode as described in FIPS pub 81. * * See also FIPS PUB 74. * * Permission is given copy and use this program provided it is not sold * for profit. * * Written by David A. Barrett (barrett%asgard@boulder.Colorado.EDU) */#define _POSIX_SOURCE/* * Include files don't declare read(2), write(2), and getopt(3) consistantly. * Specifically, getopt is not part of POSIX so the location of its  * declaration and how to make it visable with _POSIX_SOURCE is non-portable. * Secondly, whether "const" is used in the prototypes or not causes some * compilers to issue a fatal error and abort compilation.    I use read * and write rather than fread and fwrite to avoid an extra copying step * and having yet another copy of the plaintext lying around in memory. * Getopt is, of course, used for parsing command-line options. */#include <unistd.h>	/* POSIX: read write */#include <stdlib.h>	/* AES: getopt ANSII C: exit */#include <stdio.h>#include <string.h>#if defined(__msdos) || defined(__MSDOS__)#include <fcntl.h>	/* for setmode O_BINARY */#endif#include "cipher.h"extern int errno;extern char *sys_errlist[];extern int sys_nerr;extern int optind;extern char *optarg;#if defined(__STDC__) || defined(__cplusplus)extern int getkey(char *, char *, unsigned);#elseextern int getkey();#endif#if defined(__msdos) || defined(__MSDOS__)#define PATHCHAR '\\'#else#define PATHCHAR '/'#endifstatic char ident[] =" @(#) cipher.c  version 3.00 04-Apr-94.  Copyright 1994 by Dave Barrett\n";static char rcsIdent[] = " @(#) cipher.c  $Revision: 1.8 $ $Date: 94/04/04 13:32:18 $\n";#define	IO_BUFSIZE	1024		/* small for data cache speed */#define MAXCIPHER	10		/* maximum multiple encipherments */#define KEYBUFLEN	129		/* allow long keys */typedef struct {   char	   iv[DES_BLOCKSIZE];   keyType key;   int	   ivlen;   int	   decr;} KeyItem;KeyItem keys[MAXCIPHER];char    bufs[2][IO_BUFSIZE];char    *progName;typedef unsigned char block[DES_BLOCKSIZE];/* * Keys which could accidently reproduce the plaintext with multiple-encryption */block badKeys[16] = {   { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 },   { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 },    { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e },   { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },    { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e },   { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 },    { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe },   { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 },   { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e },   { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 },    { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe },   { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 },    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },	/* self-dual */   { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },	/* self-dual */   { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 },	/* self-dual */   { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e },	/* self-dual */};/* * Return nonzero if the key is one of the well-known "weak" keys (FIPS Pub 74) */int weakKey(keybits)   char *keybits;{   register block *keyp = &(badKeys[0]);	/* common compiler bug here */   register unsigned count = sizeof(badKeys) / sizeof(badKeys[0]);   register unsigned i;   do {      for (i = 0; i < DES_BLOCKSIZE; i++) {	 if ((((*keyp)[i] ^ keybits[i]) & 0xfe) != 0) goto notfound;      }      break;notfound:      keyp++;   } while (--count != 0);   return count;}int hexdigit(ch)   register char ch;{   if (ch >= '0' && ch <= '9') return ch - '0';   if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;   if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;   return -1;}/* * Convert an ASCII hexadecimal number to it's corresponding string of bytes */unsigned hex(d, s, size)   register char *d, *s;   register unsigned size;{   register unsigned count = 0;   register int lo, hi;   if (size > 0) do {      hi = hexdigit(*s++);      if (hi < 0) break;      lo = hexdigit(*s++);      if (lo < 0) break;      *d++ = (hi << 4) | lo;      count++;   } while (count < size);   return count;}/* * Because we are using CFB, we always encrypt.  Since we'd like to be * able to run the chips in either mode, perhaps CBC would be better. * If CBC is used though, the last block must be handled in OFB mode.  Sigh. * * Returns:   *  -1 - out of memory (program exits, and error reported) *   0 - success *   1 - key is a weak key */int setKey(kp, keybits, keystr, mode)   register keyType *kp;   char *keybits, *keystr;   int  mode;{   register int res;   if (keystr != (char *) 0) {      desKey(keybits, keystr, ' ');		/* space padded */      memset(keystr, '\0', strlen(keystr));	/* blank out key asap */   }   res = weakKey(keybits);   makeKey(kp, keybits, DES_BLOCKSIZE, mode);	/* 0 means encrypt mode */   memset(keybits, '\0', DES_BLOCKSIZE);	/* zero out bits asap */   if (*kp == (keyType) 0) {      fprintf(stderr, "%s: couldn't allocate memory for encryption key\n",	 progName);      exit(1);   }   return res;}int main(argc, argv)   int argc;   char *argv[];{   int 	    i, ch, rcount, wcount = -1;    int	    ivcount = 0, keycount = 0, decrcount = 0, ciphercount = 1;   int      checkkey = 1, keystrlen = 0, keylen = 0;   char	    *chp, *ibuf = bufs[1], *obuf = bufs[0];   char     keybits[DES_BLOCKSIZE], ivbits[DES_BLOCKSIZE];   char	    keybuf[KEYBUFLEN], chkbuf[KEYBUFLEN], ivbuf[DES_BLOCKSIZE];   KeyItem  *kip;   progName = *argv;   if ((chp = strrchr(progName, PATHCHAR)) != (char *) 0) progName = chp+1;   if (strcmp(progName, "decipher")==0 || strcmp(progName, "decrypt")==0)  {      keys[decrcount].decr = 1;   } else {      keys[decrcount].decr = 0;   }   while ((ch = getopt(argc, argv, "devni:k:x:")) != EOF) switch (ch) {   case 'd':        if (decrcount == MAXCIPHER) goto cipherError;      keys[decrcount++].decr = 1;		/* decrypt */      break;   case 'e':        if (decrcount == MAXCIPHER) goto cipherError;      keys[decrcount++].decr = 0;		/* encrypt */      break;   case 'i':					/* initialization vector */      if (ivcount == MAXCIPHER) goto cipherError;      memset(ivbits,  '\0', DES_BLOCKSIZE);		/* pad iv  with '\0' */						/* default IV is zero */      i  = hex(ivbuf, optarg, DES_BLOCKSIZE);	/* right-justified */      memcpy(ivbits + DES_BLOCKSIZE - i, ivbuf, i);      memcpy(keys[ivcount++].iv, ivbits, DES_BLOCKSIZE);      break;   case 'x':					/* key in hexadecimal */      if (keycount == MAXCIPHER) goto cipherError;      memset(keybits, '\0', DES_BLOCKSIZE);		/* pad key with '\0' */      keylen = hex(keybits, optarg,DES_BLOCKSIZE);	/* left-justified */      i = setKey(&keys[keycount++].key, keybits, (char *) 0, 0);      goto chkKey;   case 'k':  					/* key as a string */      if (keycount == MAXCIPHER) goto cipherError;      i = setKey(&keys[keycount++].key, keybits, optarg, 0);chkKey:      if (i) {	 fprintf(stderr, "%s: warning -- weak key selected\n", progName);      }      break;   case 'v':      checkkey++;      break;   case 'n':      --checkkey;      break;   case '?':   default:usage:      fprintf(stderr, "usage: %s [ -v|n ] {-de} {-i hex_initvec } {-x hex_key } {-k keystring }\n",       progName);      return 1;cipherError:      fprintf(stderr,       "%s: can't exceed %d multiple-encipherments\n", progName, MAXCIPHER);      return 1;   }   argc -= optind;   argv += optind;   if (argc != 0) goto usage;   if (decrcount == 0) decrcount++;#if defined(__msdos) || defined(__MSDOS__)/* *  Microsoft C munges '\r', '\n', and ^Z on EOF *  This stops that behavior (ciphertext is definitely binary) * * I cannot find a machine independent way to re-open stdin in binary mode */   ch = setmode(0, O_BINARY);   ch = setmode(1, O_BINARY);#endif   if (decrcount > ciphercount) ciphercount = decrcount;   if (ivcount   > ciphercount) ciphercount = ivcount;   if (keycount  > ciphercount) ciphercount = keycount;   while (decrcount < ciphercount) keys[decrcount++].decr = keys[0].decr;   while (ivcount < ciphercount) {			/* default IV = 0 */      keys[ivcount].ivlen = DES_BLOCKSIZE;      memset(keys[ivcount++].iv, '\0', DES_BLOCKSIZE);   }   while (keycount < ciphercount) {		   /* must input all keys */      keystrlen = getkey("Input Key:", keybuf, KEYBUFLEN-1);keyRetry:      if (keystrlen == 0) return 0;		/* empty key means give up */      if (keystrlen < 0) {	 fprintf(stderr, "%s: couldn't get key\n", progName);	 return 1;      }      if (checkkey) {	 i = getkey("Verify Key:", chkbuf, KEYBUFLEN-1);	 if (i != keystrlen || memcmp(chkbuf, keybuf, i) != 0) {	    keystrlen = getkey("Keys didn't match; try again\r\nInput Key:", 	       keybuf, KEYBUFLEN-1);	    goto keyRetry;	 }	 memset(chkbuf, '\0', i);      }      keybuf[keystrlen] = '\0';      i = setKey(&keys[keycount].key, keybits, keybuf, 0);      if (i) {	 keystrlen = 	    getkey("Weak key generated; use another one\r\nInput Key:",	       keybuf, KEYBUFLEN-1);	 goto keyRetry;      }      keycount++;   }   do {      rcount = read(0, obuf, IO_BUFSIZE);      if (rcount <= 0) break;      i = ciphercount;      kip = keys;      do {	 chp = obuf; obuf = ibuf; ibuf = chp;	 kip->ivlen = desCFB(	    obuf, ibuf, rcount, kip->iv, kip->ivlen, kip->key, kip->decr);	 kip++;      } while (--i != 0);      wcount = write(1, obuf, rcount);   } while (wcount == rcount);   /*    * Actually, we should register this code with atexit and catch all     * interrupt signals.  This still won't protect us against a system crash    * leaving the bit image on the virtual memory disc.  Sigh.    */   i = ciphercount;   kip = keys;   do {      desDestroyKey(&(kip->key));		/* erase the key schedules */      kip++;   } while (--i != 0);   if (rcount < 0) {      fprintf(stderr, "%s: read failed: %s\n", progName, sys_errlist[errno]);      return 3;   }   if (rcount != 0 && rcount != wcount)  {      fprintf(stderr, "%s: write failed: %s\n", progName, sys_errlist[errno]);      return 2;   }   return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -