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

📄 crypt.c

📁 《应用密码学》协议、算法与C原程序(第二版)配套源码。很多人都需要的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   crypt.c (full version) by Info-ZIP.        Last revised:  15 Aug 94   This code is not copyrighted and is put in the public domain.  The   encryption/decryption parts (as opposed to the non-echoing password   parts) were originally written in Europe; the whole file can there-   fore be freely distributed from any country except the USA.  If this   code is imported into the USA, it cannot be re-exported from from   there to another country.  (This restriction might seem curious, but   this is what US law requires.) *//* This encryption code is a direct transcription of the algorithm from   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This   file (appnote.txt) is distributed with the PKZIP program (even in the   version without encryption capabilities). */#include "zip.h"#include "crypt.h"#ifndef PUTC#  define PUTC putc#endif#ifndef UNZIP#  ifdef BSD#    define TEMP_BSD BSD#    undef BSD#  endif#  include <sys/param.h>   /* this gets BSD4_4 on NET/2 and 4.4BSD systems */#  if (defined(TEMP_BSD) && !defined(BSD))#    define BSD TEMP_BSD#    undef TEMP_BSD#  endif#  include <time.h>   /* time.h already included in unzip's zip.h */#  if (defined(DOS_NT_OS2) && !defined(__GO32__))#    include <process.h>#  else#    if !defined(BSD4_4) && !defined(SYSV)  /* getpid() in unistd.h */       int  getpid OF((void));#    endif#  endif#  ifndef __GNUC__     void srand OF((unsigned int));#  endif   int rand OF((void));#endif /* !UNZIP */#if defined(LINUX) || defined(BSD4_4)  /* POSIX termio */#  define TERMIOS#else#  if (defined(DIRENT) || defined(SYSV) || defined(CRAY))     /* for now, assume DIRENT implies System V implies TERMIO */#    if (!defined(NO_TERMIO) && !defined(TERMIO) && !defined(__MINT__))#      define TERMIO#    endif#  endif#endif /* LINUX || BSD4_4 */#if (!defined(AMIGA) && !defined(MACOS))      /* (see crypt.h) */#  if (defined(DOS_NT_OS2) || defined(VMS))#    ifndef MSVMS#      define MSVMS#    endif#    ifdef DOS_NT_OS2#      ifdef __EMX__#        define getch() _read_kbd(0, 1, 0)#      else#        ifdef __GO32__#          include <pc.h>#          define getch() getkey()#        else /* !__GO32__ */#          include <conio.h>#        endif /* ?__GO32__ */#      endif#    else /* !DOS_NT_OS2 */#      ifdef PASSWD_FROM_STDIN#        define getch() getc(stdin)#      else#        define getch() getc(stderr)#      endif#      include <descrip.h>#      include <iodef.h>#      include <ttdef.h>#      include <starlet.h>#      if !defined(SS$_NORMAL)#        define SS$_NORMAL 1   /* only thing we need from <ssdef.h> */#      endif#    endif /* ?DOS_NT_OS2 */#  else /* !(DOS_NT_OS2 || VMS) */#    ifdef TERMIOS#      include <termios.h>#      define sgttyb termios#      define sg_flags c_lflag#      define GTTY(f, s) tcgetattr(f, (voidp *) s)#      define STTY(f, s) tcsetattr(f, TCSAFLUSH, (voidp *) s)#    else /* !TERMIOS */#       ifdef TERMIO       /* Amdahl, Cray, all SysV? */#         ifdef COHERENT#           include <termio.h>#         else#             include <sys/termio.h>#         endif /* ?COHERENT */#         define sgttyb termio#         define sg_flags c_lflag#         ifndef SYSV            int ioctl OF((int, int, voidp *)); /* already in unistd.h */#         endif#         define GTTY(f,s) ioctl(f,TCGETA,(voidp *)s)#         define STTY(f,s) ioctl(f,TCSETAW,(voidp *)s)#       else /* !TERMIO */#         ifndef MINIX#           include <sys/ioctl.h>#         endif /* !MINIX */#         include <sgtty.h>#         define GTTY gtty#         define STTY stty          int gtty OF((int, struct sgttyb *));          int stty OF((int, struct sgttyb *));#       endif /* ?TERMIO */#    endif /* ?TERMIOS */#    if defined(BSD4_4) || defined(SYSV) || defined(__convexc__)#      ifndef UNZIP#        include <fcntl.h>#      endif#    else       char *ttyname OF((int));#    endif#  endif /* ?(DOS_NT_OS2 || VMS) */#endif /* !AMIGA && !MACOS */#ifdef UNZIP   char *key = (char *)NULL;  /* password with which to decrypt data, or NULL */#  ifndef FUNZIP     local int testp OF((uch *h));#  endif#endif /* UNZIP */local ulg keys[3]; /* keys defining the pseudo-random sequence */#ifndef Trace#  ifdef CRYPT_DEBUG#    define Trace(x) fprintf x#  else#    define Trace(x)#  endif#endif/*********************************************************************** * Return the next byte in the pseudo-random sequence */int decrypt_byte(){   ush temp;   temp = (ush)keys[2] | 2;   return (int)(((ush)(temp * (temp ^ 1)) >> 8) & 0xff);}/*********************************************************************** * Update the encryption keys with the next byte of plain text */int update_keys(c)    int c;                  /* byte of plain text */{    keys[0] = CRC32(keys[0], c);    keys[1] += keys[0] & 0xff;    keys[1] = keys[1] * 134775813L + 1;    keys[2] = CRC32(keys[2], (int)(keys[1] >> 24));    return c;}/*********************************************************************** * Initialize the encryption keys and the random header according to * the given password. */void init_keys(passwd)    char *passwd;             /* password string with which to modify keys */{    keys[0] = 305419896L;    keys[1] = 591751049L;    keys[2] = 878082192L;    while (*passwd != '\0') {        update_keys((int)*passwd);        passwd++;    }}#ifndef UNZIP/*********************************************************************** * Write encryption header to file zfile using the password passwd * and the cyclic redundancy check crc. */void crypthead(passwd, crc, zfile)    char *passwd;                /* password string */    ulg crc;                     /* crc of file being encrypted */    FILE *zfile;                 /* where to write header */{    int n;                       /* index in random header */    int t;                       /* temporary */    int c;                       /* random byte */    int ztemp;                   /* temporary for zencoded value */    uch header[RAND_HEAD_LEN-2]; /* random header */    static unsigned calls = 0;   /* ensure different random header each time */    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the     * output of rand() to get less predictability, since rand() is     * often poorly implemented.     */    if (++calls == 1) {        srand((unsigned)time(NULL) ^ getpid());    }    init_keys(passwd);    for (n = 0; n < RAND_HEAD_LEN-2; n++) {        c = (rand() >> 7) & 0xff;        header[n] = (uch)zencode(c, t);    }    /* Encrypt random header (last two bytes is high word of crc) */    init_keys(passwd);    for (n = 0; n < RAND_HEAD_LEN-2; n++) {        ztemp = zencode(header[n], t);        putc(ztemp, zfile);    }    ztemp = zencode((int)(crc >> 16) & 0xff, t);    putc(ztemp, zfile);    ztemp = zencode((int)(crc >> 24) & 0xff, t);    putc(ztemp, zfile);}#ifdef UTIL/*********************************************************************** * Encrypt the zip entry described by z from file source to file dest * using the password passwd.  Return an error code in the ZE_ class. */int zipcloak(z, source, dest, passwd)    struct zlist far *z;    /* zip entry to encrypt */    FILE *source, *dest;    /* source and destination files */    char *passwd;           /* password string */{    int c;                  /* input byte */    int res;                /* result code */    ulg n;                  /* holds offset and counts size */    ush flag;               /* previous flags */    int t;                  /* temporary */    int ztemp;              /* temporary storage for zencode value */    /* Set encrypted bit, clear extended local header bit and write local       header to output file */    if ((n = ftell(dest)) == -1L) return ZE_TEMP;    z->off = n;    flag = z->flg;    z->flg |= 1,  z->flg &= ~8;    z->lflg |= 1, z->lflg &= ~8;    z->siz += RAND_HEAD_LEN;    if ((res = putlocal(z, dest)) != ZE_OK) return res;    /* Initialize keys with password and write random header */    crypthead(passwd, z->crc, dest);    /* Skip local header in input file */    if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),              SEEK_CUR)) {        return ferror(source) ? ZE_READ : ZE_EOF;    }    /* Encrypt data */    for (n = z->siz - RAND_HEAD_LEN; n; n--) {        if ((c = getc(source)) == EOF) {            return ferror(source) ? ZE_READ : ZE_EOF;        }        ztemp = zencode(c, t);        putc(ztemp, dest);    }    /* Skip extended local header in input file if there is one */    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {        return ferror(source) ? ZE_READ : ZE_EOF;    }    if (fflush(dest) == EOF) return ZE_TEMP;    return ZE_OK;}/*********************************************************************** * Decrypt the zip entry described by z from file source to file dest * using the password passwd.  Return an error code in the ZE_ class. */int zipbare(z, source, dest, passwd)    struct zlist far *z;  /* zip entry to encrypt */    FILE *source, *dest;  /* source and destination files */    char *passwd;         /* password string */{    int c0, c1;           /* last two input bytes */    ulg offset;           /* used for file offsets */    ulg size;             /* size of input data */    int r;                /* size of encryption header */    int res;              /* return code */    ush flag;             /* previous flags */    /* Save position and skip local header in input file */    if ((offset = ftell(source)) == -1L ||        fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),              SEEK_CUR)) {        return ferror(source) ? ZE_READ : ZE_EOF;    }    /* Initialize keys with password */    init_keys(passwd);    /* Decrypt encryption header, save last two bytes */    c1 = 0;    for (r = RAND_HEAD_LEN; r; r--) {        c0 = c1;        if ((c1 = getc(source)) == EOF) {            return ferror(source) ? ZE_READ : ZE_EOF;        }        Trace((stdout, " (%02x)", c1));        zdecode(c1);        Trace((stdout, " %02x", c1));    }    Trace((stdout, "\n"));    /* If last two bytes of header don't match crc (or file time in the     * case of an extended local header), back up and just copy. For     * pkzip 2.0, the check has been reduced to one byte only.     */#ifdef ZIP10    if ((ush)(c0 | (c1<<8)) !=        (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) {#else    c0++; /* avoid warning on unused variable */    if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) {#endif        if (fseek(source, offset, SEEK_SET)) {            return ferror(source) ? ZE_READ : ZE_EOF;        }        if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;        return ZE_MISS;    }    /* Clear encrypted bit and local header bit, and write local header to       output file */    if ((offset = ftell(dest)) == -1L) return ZE_TEMP;    z->off = offset;    flag = z->flg;    z->flg &= ~9;    z->lflg &= ~9;    z->siz -= RAND_HEAD_LEN;    if ((res = putlocal(z, dest)) != ZE_OK) return res;    /* Decrypt data */    for (size = z->siz; size; size--) {        if ((c1 = getc(source)) == EOF) {            return ferror(source) ? ZE_READ : ZE_EOF;        }        zdecode(c1);        putc(c1, dest);    }    /* Skip extended local header in input file if there is one */    if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) {        return ferror(source) ? ZE_READ : ZE_EOF;    }    if (fflush(dest) == EOF) return ZE_TEMP;    return ZE_OK;}#else /* !UTIL *//*********************************************************************** * If requested, encrypt the data in buf, and in any case call fwrite() * with the arguments to zfwrite().  Return what fwrite() returns. */unsigned zfwrite(buf, item_size, nb, f)    voidp *buf;                /* data buffer */    extent item_size;          /* size of each item in bytes */    extent nb;                 /* number of items */    FILE *f;                   /* file to write to */{    int t;                    /* temporary */    if (key != (char *)NULL) { /* key is the global password pointer */        ulg size;              /* buffer size */        char *p = (char*)buf;  /* steps through buffer */        /* Encrypt data in buffer */        for (size = item_size*(ulg)nb; size != 0; p++, size--) {            *p = (char)zencode(*p, t);        }    }    /* Write the buffer out */    return fwrite(buf, item_size, nb, f);}#endif /* ?UTIL */#endif /* !UNZIP */#ifdef VMS/*********************************************************************** * Turn keyboard echoing on or off (VMS).  Loosely based on VMSmunch.c * and hence on Joe Meadows' file.c code. */int echo(opt)    int opt;{    /*     * For VMS v5.x:     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,     *     System Services Reference Manual, pp. sys-23, sys-379     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,     *     Intro to System Routines, sec. 2.9.2     * GRR, 15 Aug 91     */    static struct dsc$descriptor_s DevDesc =        {9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"};     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */    static short           DevChan, iosb[4];    static long            i, status;    static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */      /* assign a channel to standard input */    status = sys$assign(&DevDesc, &DevChan, 0, 0);    if (!(status & 1))        return status;    /* use sys$qio and the IO$_SENSEMODE function to determine the current     * tty status (for password reading, could use IO$_READVBLK function     * instead, but echo on/off will be more general)     */    status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,                     oldmode, 8, 0, 0, 0, 0);    if (!(status & 1))        return status;

⌨️ 快捷键说明

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