home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1990 / 11 / stevens.asc < prev    next >
Text File  |  1990-10-12  |  18KB  |  671 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. /* -------------- des.h ---------------- */
  7. /* Header file for Data Encryption Standard algorithms  */
  8.  
  9. /* -------------- prototypes ------------------- */
  10. void initkey(char *key);
  11. void encrypt(char *blk);
  12. void decrypt(char *blk);
  13.  
  14. /* ----------- tables ------------ */
  15. extern unsigned char Pmask[];
  16. extern unsigned char IPtbl[];
  17. extern unsigned char Etbl[];
  18. extern unsigned char Ptbl[];
  19. extern unsigned char stbl[8][4][16];
  20. extern unsigned char PC1tbl[];
  21. extern unsigned char PC2tbl[];
  22. extern unsigned char ex6[8][2][4];
  23.  
  24.  
  25.  
  26. [LISTING TWO]
  27.  
  28. /* Data Encryption Standard front end
  29.  * Usage: des [-e -d] keyvalue infile outfile
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include "des.h"
  35.  
  36. static void setparity(char *key);
  37.  
  38. void main(int argc, char *argv[])
  39. {
  40.    FILE *fi, *fo;
  41.    char key[9];
  42.    char blk[8];
  43.  
  44.    if (argc > 4)    {
  45.         strncpy(key, argv[2], 8);
  46.         key[8] = '\0';
  47.         setparity(key);
  48.  
  49.         initkey(key);
  50.        if ((fi = fopen(argv[3], "rb")) != NULL)    {
  51.            if ((fo = fopen(argv[4], "wb")) != NULL)    {
  52.                while (!feof(fi))    {
  53.                    memset(blk, 0, 8);
  54.                    if (fread(blk, 1, 8, fi) != 0)    {
  55.                        if (stricmp(argv[1], "-e") == 0)
  56.                            encrypt(blk);
  57.                        else
  58.                            decrypt(blk);
  59.                           fwrite(blk, 1, 8, fo);
  60.                    }
  61.                }
  62.                fclose(fo);
  63.            }
  64.            fclose(fi);
  65.        }
  66.    }
  67.    else
  68.        printf("\nUsage: des [-e -d] keyvalue infile outfile");
  69. }
  70.  
  71. /* -------- make a character odd parity ---------- */
  72. static unsigned char oddparity(unsigned char s)
  73. {
  74.    unsigned char c = s | 0x80;
  75.    while (s)    {
  76.        if (s & 1)
  77.            c ^= 0x80;
  78.        s = (s >> 1) & 0x7f;
  79.    }
  80.    return c;
  81. }
  82.  
  83. /* ------ make a key odd parity ------- */
  84. void setparity(char *key)
  85. {
  86.    int i;
  87.    for (i = 0; i < 8; i++)
  88.        *(key+i) = oddparity(*(key+i));
  89. }
  90.  
  91.  
  92. [LISTING THREE]
  93.  
  94. /* ---------------------- des.c --------------------------- */
  95. /* Functions and tables for DES encryption and decryption
  96.  */
  97.  
  98. #include <stdio.h>
  99. #include <string.h>
  100. #include "des.h"
  101.  
  102. /* -------- 48-bit key permutation ------- */
  103. struct ks    {
  104.     char ki[6];
  105. };
  106.  
  107. /* ------- two halves of a 64-bit data block ------- */
  108. struct LR    {
  109.     long L;
  110.     long R;
  111. };
  112.  
  113. static struct ks keys[16];
  114.  
  115. static void rotate(unsigned char *c, int n);
  116. static int fourbits(struct ks, int s);
  117. static int sixbits(struct ks, int s);
  118. static void inverse_permute(long *op,long *ip,long *tbl,int n);
  119. static void permute(long *op, long *ip, long *tbl, int n);
  120. static long f(long blk, struct ks ky);
  121. static struct ks KS(int n, char *key);
  122. static void swapbyte(long *l);
  123.  
  124. /* ----------- initialize the key -------------- */
  125. void initkey(char *key)
  126. {
  127.     int i;
  128.     for (i = 0; i < 16; i++)
  129.         keys[i] = KS(i, key);
  130. }
  131.  
  132. /* ----------- encrypt an 8-byte block ------------ */
  133. void encrypt(char *blk)
  134. {
  135.    struct LR ip, op;
  136.    long temp;
  137.    int n;
  138.  
  139.    memcpy(&ip, blk, sizeof(struct LR));
  140.    /* -------- initial permuation -------- */
  141.    permute(&op.L, &ip.L, (long *)IPtbl, 64);
  142.    swapbyte(&op.L);
  143.    swapbyte(&op.R);
  144.    /* ------ swap and key iterations ----- */
  145.    for (n = 0; n < 16; n++)    {
  146.        temp = op.R;
  147.        op.R = op.L ^ f(op.R, keys[n]);
  148.        op.L = temp;
  149.    }
  150.    ip.R = op.L;
  151.    ip.L = op.R;
  152.    swapbyte(&ip.L);
  153.    swapbyte(&ip.R);
  154.    /* ----- inverse initial permutation ---- */
  155.    inverse_permute(&op.L, &ip.L,
  156.        (long *)IPtbl, 64);
  157.    memcpy(blk, &op, sizeof(struct LR));
  158. }
  159.  
  160. /* ----------- decrypt an 8-byte block ------------ */
  161. void decrypt(char *blk)
  162. {
  163.    struct LR ip, op;
  164.    long temp;
  165.    int n;
  166.  
  167.    memcpy(&ip, blk, sizeof(struct LR));
  168.    /* -------- initial permuation -------- */
  169.    permute(&op.L, &ip.L, (long *)IPtbl, 64);
  170.    swapbyte(&op.L);
  171.    swapbyte(&op.R);
  172.    ip.R = op.L;
  173.    ip.L = op.R;
  174.    /* ------ swap and key iterations ----- */
  175.    for (n = 15; n >= 0; --n)    {
  176.        temp = ip.L;
  177.        ip.L = ip.R ^ f(ip.L, keys[n]);
  178.        ip.R = temp;
  179.    }
  180.    swapbyte(&ip.L);
  181.    swapbyte(&ip.R);
  182.    /* ----- inverse initial permuation ---- */
  183.    inverse_permute(&op.L, &ip.L,
  184.        (long *)IPtbl, 64);
  185.    memcpy(blk, &op, sizeof(struct LR));
  186. }
  187.  
  188. /* ------- inverse permute a 64-bit string ------- */
  189. static void inverse_permute(long *op,long *ip,long *tbl,int n)
  190. {
  191.     int i;
  192.     long *pt = (long *)Pmask;
  193.  
  194.     *op = *(op+1) = 0;
  195.     for (i = 0; i < n; i++)    {
  196.        if ((*ip & *pt) || (*(ip+1) & *(pt+1)))  {
  197.            *op |= *tbl;
  198.            *(op+1) |= *(tbl+1);
  199.         }
  200.         tbl += 2;
  201.         pt += 2;
  202.    }
  203. }
  204.  
  205. /* ------- permute a 64-bit string ------- */
  206. static void permute(long *op, long *ip, long *tbl, int n)
  207. {
  208.     int i;
  209.     long *pt = (long *)Pmask;
  210.  
  211.     *op = *(op+1) = 0;
  212.     for (i = 0; i < n; i++)    {
  213.         if ((*ip & *tbl) || (*(ip+1) & *(tbl+1))) {
  214.             *op |= *pt;
  215.             *(op+1) |= *(pt+1);
  216.         }
  217.         tbl += 2;
  218.         pt += 2;
  219.     }
  220. }
  221.  
  222. /* ----- Key dependent computation function f(R,K) ----- */
  223. static long f(long blk, struct ks key)
  224. {
  225.     struct LR ir;
  226.     struct LR or;
  227.     int i;
  228.  
  229.     union    {
  230.         struct LR f;
  231.         struct ks kn;
  232.     } tr = {0,0}, kr = {0,0};
  233.  
  234.     ir.L = blk;
  235.     ir.R = 0;
  236.  
  237.     kr.kn = key;
  238.  
  239.     swapbyte(&ir.L);
  240.     swapbyte(&ir.R);
  241.  
  242.     permute(&tr.f.L, &ir.L, (long *)Etbl, 48);
  243.  
  244.     tr.f.L ^= kr.f.L;
  245.     tr.f.R ^= kr.f.R;
  246.  
  247.    /*   the DES S function: ir.L = S(tr.kn);  */
  248.     ir.L = 0;
  249.     for (i = 0; i < 8; i++)    {
  250.         long four = fourbits(tr.kn, i);
  251.         ir.L |= four << ((7-i) * 4);
  252.     }
  253.     swapbyte(&ir.L);
  254.  
  255.     ir.R = or.R = 0;
  256.     permute(&or.L, &ir.L, (long *)Ptbl, 32);
  257.  
  258.     swapbyte(&or.L);
  259.     swapbyte(&or.R);
  260.  
  261.     return or.L;
  262. }
  263.  
  264. /* ------- extract a 4-bit stream from the block/key ------- */
  265. static int fourbits(struct ks k, int s)
  266. {
  267.     int i = sixbits(k, s);
  268.     int row, col;
  269.     row = ((i >> 4) & 2) | (i & 1);
  270.     col = (i >> 1) & 0xf;
  271.     return stbl[s][row][col];
  272. }
  273.  
  274. /* ---- extract 6-bit stream fr pos s of the  block/key ---- */
  275. static int sixbits(struct ks k, int s)
  276. {
  277.     int op = 0;
  278.     int n = (s);
  279.     int i;
  280.     for (i = 0; i < 2; i++)    {
  281.         int off = ex6[n][i][0];
  282.         unsigned char c = k.ki[off];
  283.         c >>= ex6[n][i][1];
  284.         c <<= ex6[n][i][2];
  285.         c &=  ex6[n][i][3];
  286.         op |= c;
  287.     }
  288.     return op;
  289. }
  290.  
  291. /* ---------- DES Key Schedule (KS) function ----------- */
  292. static struct ks KS(int n, char *key)
  293. {
  294.     static unsigned char cd[8];
  295.     static int its[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
  296.     union    {
  297.         struct ks kn;
  298.         struct LR filler;
  299.     } result;
  300.  
  301.     if (n == 0)
  302.         permute((long *)cd, (long *) key, (long *)PC1tbl, 64);
  303.  
  304.     rotate(cd, its[n]);
  305.     rotate(cd+4, its[n]);
  306.  
  307.     permute(&result.filler.L, (long *)cd, (long *)PC2tbl, 48);
  308.     return result.kn;
  309. }
  310.  
  311. /* rotate a 4-byte string n (1 or 2) positions to the left */
  312. static void rotate(unsigned char *c, int n)
  313. {
  314.     int i;
  315.     unsigned j, k;
  316.     k = ((*c) & 255) >> (8 - n);
  317.     for (i = 3; i >= 0; --i)    {
  318.         j = ((*(c+i) << n) + k);
  319.         k = (j >> 8) & 255;
  320.         *(c+i) = j & 255;
  321.     }
  322.     if (n == 2)
  323.        *(c+3) = (*(c+3) & 0xc0) | ((*(c+3) << 4) & 0x30);
  324.     else
  325.        *(c+3) = (*(c+3) & 0xe0) | ((*(c+3) << 4) & 0x10);
  326. }
  327.  
  328. /* -------- swap bytes in a long integer ---------- */
  329. static void swapbyte(long *l)
  330. {
  331.    char *cp = (char *) l;
  332.    char t = *(cp+3);
  333.  
  334.    *(cp+3) = *cp;
  335.    *cp = t;
  336.    t = *(cp+2);
  337.    *(cp+2) = *(cp+1);
  338.    *(cp+1) = t;
  339. }
  340.  
  341. [LISTING FOUR]
  342.  
  343. /* --------------- tables.c --------------- */
  344. /* tables for the DES algorithm
  345.  */
  346.  
  347. /* --------- macros to define a permutation table ---------- */
  348. #define ps(n)       ((unsigned char)(0x80 >> (n-1)))
  349. #define b(n,r)      ((n>r||n<r-7)?0:ps(n-(r-8)))
  350. #define p(n)        b(n, 8),b(n,16),b(n,24),b(n,32),\
  351.                     b(n,40),b(n,48),b(n,56),b(n,64)
  352. #define q(n)        p((n)+4)
  353.  
  354. /* --------- permutation masks ----------- */
  355. unsigned char Pmask[] = {
  356.     p( 1),p( 2),p( 3),p( 4),p( 5),p( 6),p( 7),p( 8),
  357.     p( 9),p(10),p(11),p(12),p(13),p(14),p(15),p(16),
  358.     p(17),p(18),p(19),p(20),p(21),p(22),p(23),p(24),
  359.     p(25),p(26),p(27),p(28),p(29),p(30),p(31),p(32),
  360.     p(33),p(34),p(35),p(36),p(37),p(38),p(39),p(40),
  361.     p(41),p(42),p(43),p(44),p(45),p(46),p(47),p(48),
  362.     p(49),p(50),p(51),p(52),p(53),p(54),p(55),p(56),
  363.     p(57),p(58),p(59),p(60),p(61),p(62),p(63),p(64)
  364. };
  365.  
  366. /* ----- initial and inverse-initial permutation table ----- */
  367. unsigned char IPtbl[] = {
  368.     p(58),p(50),p(42),p(34),p(26),p(18),p(10),p( 2),
  369.     p(60),p(52),p(44),p(36),p(28),p(20),p(12),p( 4),
  370.     p(62),p(54),p(46),p(38),p(30),p(22),p(14),p( 6),
  371.     p(64),p(56),p(48),p(40),p(32),p(24),p(16),p( 8),
  372.     p(57),p(49),p(41),p(33),p(25),p(17),p( 9),p( 1),
  373.     p(59),p(51),p(43),p(35),p(27),p(19),p(11),p( 3),
  374.     p(61),p(53),p(45),p(37),p(29),p(21),p(13),p( 5),
  375.     p(63),p(55),p(47),p(39),p(31),p(23),p(15),p( 7)
  376. };
  377.  
  378. /* ---------- permutation table E for f function --------- */
  379. unsigned char Etbl[] = {
  380.     p(32),p( 1),p( 2),p( 3),p( 4),p( 5),
  381.     p( 4),p( 5),p( 6),p( 7),p( 8),p( 9),
  382.     p( 8),p( 9),p(10),p(11),p(12),p(13),
  383.     p(12),p(13),p(14),p(15),p(16),p(17),
  384.     p(16),p(17),p(18),p(19),p(20),p(21),
  385.     p(20),p(21),p(22),p(23),p(24),p(25),
  386.     p(24),p(25),p(26),p(27),p(28),p(29),
  387.     p(28),p(29),p(30),p(31),p(32),p( 1)
  388. };
  389.  
  390. /* ---------- permutation table P for f function --------- */
  391. unsigned char Ptbl[] = {
  392.     p(16),p( 7),p(20),p(21),p(29),p(12),p(28),p(17),
  393.     p( 1),p(15),p(23),p(26),p( 5),p(18),p(31),p(10),
  394.     p( 2),p( 8),p(24),p(14),p(32),p(27),p( 3),p( 9),
  395.     p(19),p(13),p(30),p( 6),p(22),p(11),p( 4),p(25)
  396. };
  397.  
  398. /* --- table for converting six-bit to four-bit stream --- */
  399. unsigned char stbl[8][4][16] = {
  400.     /* ------------- s1 --------------- */
  401.     14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
  402.     0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
  403.     4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
  404.     15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13,
  405.     /* ------------- s2 --------------- */
  406.     15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,
  407.     3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
  408.     0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
  409.     13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9,
  410.     /* ------------- s3 --------------- */
  411.     10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,
  412.     13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
  413.     13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
  414.     1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12,
  415.     /* ------------- s4 --------------- */
  416.     7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,
  417.     13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
  418.     10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
  419.     3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14,
  420.     /* ------------- s5 --------------- */
  421.     2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,
  422.     14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
  423.     4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
  424.     11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3,
  425.     /* ------------- s6 --------------- */
  426.     12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,
  427.     10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
  428.     9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
  429.     4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13,
  430.     /* ------------- s7 --------------- */
  431.     4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,
  432.     13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
  433.     1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
  434.     6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12,
  435.     /* ------------- s8 --------------- */
  436.     13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,
  437.     1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
  438.     7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
  439.     2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11
  440. };
  441.  
  442. /* ---- Permuted Choice 1 for Key Schedule calculation ---- */
  443. unsigned char PC1tbl[] = {
  444.     p(57),p(49),p(41),p(33),p(25),p(17),p( 9),
  445.     p( 1),p(58),p(50),p(42),p(34),p(26),p(18),
  446.     p(10),p( 2),p(59),p(51),p(43),p(35),p(27),
  447.     p(19),p(11),p( 3),p(60),p(52),p(44),p(36),
  448.     p(0),p(0),p(0),p(0),
  449.  
  450.     p(63),p(55),p(47),p(39),p(31),p(23),p(15),
  451.     p( 7),p(62),p(54),p(46),p(38),p(30),p(22),
  452.     p(14),p( 6),p(61),p(53),p(45),p(37),p(29),
  453.     p(21),p(13),p( 5),p(28),p(20),p(12),p( 4),
  454.     p(0),p(0),p(0),p(0)
  455. };
  456.  
  457. /* ---- Permuted Choice 2 for Key Schedule calculation ---- */
  458. unsigned char PC2tbl[] = {
  459.     p(14),p(17),p(11),p(24),p( 1),p( 5),p( 3),p(28),
  460.     p(15),p( 6),p(21),p(10),p(23),p(19),p(12),p( 4),
  461.     p(26),p( 8),p(16),p( 7),p(27),p(20),p(13),p( 2),
  462.  
  463.     q(41),q(52),q(31),q(37),q(47),q(55),q(30),q(40),
  464.     q(51),q(45),q(33),q(48),q(44),q(49),q(39),q(56),
  465.     q(34),q(53),q(46),q(42),q(50),q(36),q(29),q(32)
  466. };
  467.  
  468. /* ---- For extracting 6-bit strings from 64-bit string ---- */
  469. unsigned char ex6[8][2][4] = {
  470.     /* byte, >>, <<, & */
  471.     /* ---- s = 8  ---- */
  472.     0,2,0,0x3f,
  473.     0,2,0,0x3f,
  474.     /* ---- s = 7  ---- */
  475.     0,0,4,0x30,
  476.     1,4,0,0x0f,
  477.     /* ---- s = 6  ---- */
  478.     1,0,2,0x3c,
  479.     2,6,0,0x03,
  480.     /* ---- s = 5  ---- */
  481.     2,0,0,0x3f,    
  482.     2,0,0,0x3f,
  483.     /* ---- s = 4 ---- */
  484.     3,2,0,0x3f,
  485.     3,2,0,0x3f,
  486.     /* ---- s = 3 ---- */
  487.     3,0,4,0x30,
  488.     4,4,0,0x0f,
  489.     /* ---- s = 2 ---- */
  490.     4,0,2,0x3c,
  491.     5,6,0,0x03,
  492.     /* ---- s = 1 ---- */
  493.     5,0,0,0x3f,    
  494.     5,0,0,0x3f    
  495. };
  496.  
  497.  
  498.  
  499. [LISTING FIVE]
  500.  
  501. /* ---------------------- encrypto.c ----------------------- */
  502. /* Single key text file encryption
  503.  * Usage: encrypto keyvalue infile outfile
  504.  */
  505.  
  506. #include <stdio.h>
  507. #include <stdlib.h>
  508. #include <string.h>
  509.  
  510. #define FALSE 0
  511. #define TRUE !FALSE
  512.  
  513. static void charout(FILE *fo, char prev, int runct, int last);
  514. static void encrypt(FILE *fo, char ch, int last);
  515.  
  516. static char *key = NULL;
  517. static int keylen;
  518. static char *cipher = NULL;
  519. static int clen = 0;
  520.  
  521. void main(int argc, char *argv[])
  522. {
  523.    FILE *fi, *fo;
  524.    char ch, prev = 0;
  525.    int runct = 0;
  526.  
  527.    if (argc > 3)    {
  528.        /* --- alloc memory for the key and cipher blocks --- */
  529.        keylen = strlen(argv[1]);
  530.        cipher = malloc(keylen+1);
  531.        key = malloc(keylen+1);
  532.        strcpy(key, argv[1]);
  533.  
  534.        if (cipher != NULL && key != NULL &&
  535.                (fi = fopen(argv[2], "rb")) != NULL)        {
  536.            if ((fo = fopen(argv[3], "wb")) != NULL)    {
  537.                while ((ch = fgetc(fi)) != EOF)    {
  538.                     /* ---- validate ASCII input ---- */
  539.                    if (ch & 128)    {
  540.                        fprintf(stderr, "%s is not ASCII",
  541.                                    argv[2]);
  542.                        fclose(fi);
  543.                        fclose(fo);
  544.                        remove(argv[3]);
  545.                        free(cipher);
  546.                        free(key);
  547.                        exit(1);
  548.                    }
  549.  
  550.                    /* --- test for duplicate bytes --- */
  551.                    if (ch == prev && runct < 127)
  552.                        runct++;
  553.                    else    {
  554.                        charout(fo, prev, runct, FALSE);
  555.                        prev = ch;
  556.                        runct = 0;
  557.                    }
  558.                }
  559.                charout(fo, prev, runct, TRUE);
  560.                fclose(fo);
  561.            }
  562.            fclose(fi);
  563.        }
  564.        if (cipher)
  565.            free(cipher);
  566.        if (key)
  567.            free(key);
  568.    }
  569. }
  570.  
  571. /* ------- send an encrypted byte to the output file ------ */
  572. static void charout(FILE *fo, char prev, int runct, int last)
  573. {
  574.    if (runct)
  575.        encrypt(fo, (runct+1) | 0x80, last);
  576.    if (prev)
  577.        encrypt(fo, prev, last);
  578. }
  579.  
  580. /* ---------- encrypt a byte and write it ---------- */
  581. static void encrypt(FILE *fo, char ch, int last)
  582. {
  583.    *(cipher+clen) = ch ^ *(key+clen);
  584.    clen++;
  585.    if (last || clen == keylen)    {
  586.        /* ----- cipher buffer full or last buffer ----- */
  587.        int i;
  588.        for (i = 0; i < clen; i++)
  589.            fputc(*(cipher+i), fo);
  590.        clen = 0;
  591.    }
  592. }
  593.  
  594. [LISTING SIX]
  595.  
  596. /* ---------------------- decrypto.c ----------------------- */
  597. /* Single key text file decryption
  598.  * Usage: decrypto keyvalue infile outfile
  599.  */
  600.  
  601. #include <stdio.h>
  602. #include <string.h>
  603. #include <stdlib.h>
  604. #include <process.h>
  605.  
  606. static char decrypt(FILE *);
  607.  
  608. static char *key = NULL;
  609. static int keylen;
  610. static char *cipher = NULL;
  611. static int clen = 0, coff = 0;
  612.  
  613. void main(int argc, char *argv[])
  614. {
  615.    FILE *fi, *fo;
  616.    char ch;
  617.    int runct = 0;
  618.  
  619.    if (argc > 3)    {
  620.        /* --- alloc memory for the key and cipher blocks --- */
  621.        keylen = strlen(argv[1]);
  622.        cipher = malloc(keylen+1);
  623.        key = malloc(keylen+1);
  624.        strcpy(key, argv[1]);
  625.  
  626.        if (cipher != NULL && key != NULL &&
  627.                (fi = fopen(argv[2], "rb")) != NULL)    {
  628.  
  629.            if ((fo = fopen(argv[3], "wb")) != NULL)    {
  630.                while ((ch = decrypt(fi)) != EOF)    {
  631.                    /* --- test for run length counter --- */
  632.                    if (ch & 0x80)
  633.                        runct = ch & 0x7f;
  634.                    else    {
  635.                        if (runct)
  636.                            /* --- run count: dup the byte -- */
  637.                            while (--runct)
  638.                                fputc(ch, fo);
  639.                        fputc(ch, fo);
  640.                    }
  641.                }
  642.                fclose(fo);
  643.            }
  644.            fclose(fi);
  645.        }
  646.        if (cipher)
  647.            free(cipher);
  648.        if (key)
  649.            free(key);
  650.    }
  651. }
  652.  
  653. /* ------ decryption function: returns decrypted byte ----- */
  654. static char decrypt(FILE *fi)
  655. {
  656.    char ch = EOF;
  657.    if (clen == 0)    {
  658.        /* ---- read a block of encrypted bytes ----- */
  659.        clen = fread(cipher, 1, keylen, fi);
  660.        coff = 0;
  661.    }
  662.    if (clen > 0)    {
  663.        /* --- decrypt the next byte in the input block --- */
  664.        ch = *(cipher+coff) ^ *(key+coff);
  665.        coff++;
  666.        --clen;
  667.    }
  668.    return ch;
  669. }
  670.  
  671.