home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume19 / md4tools / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-05-08  |  29.7 KB

  1. From: kent@sparky.imd.sterling.com (Kent Landfield)
  2. Newsgroups: comp.sources.misc
  3. Subject: v19i018:  md4tools - MD4 netnews verification tools, Part02/02
  4. Message-ID: <1991May9.021107.28230@sparky.IMD.Sterling.COM>
  5. Date: 9 May 91 02:11:07 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7.  
  8. Submitted-by: Kent Landfield <kent@sparky.imd.sterling.com>
  9. Posting-number: Volume 19, Issue 18
  10. Archive-name: md4tools/part02
  11.  
  12. #! /bin/sh
  13. # into a shell via "sh file" or similar.  To overwrite existing files,
  14. # type "sh file -c".
  15. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  16. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  17. # Contents:  Makefile TestArticle checkmd4.1 checkmd4.c hashmd4.1
  18. #   hashmd4.c md4.h md4driver.c pipeit.c
  19. # Wrapped by kent@sparky on Tue May  7 23:23:54 1991
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 2 (of 2)."'
  23. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'Makefile'\"
  25. else
  26.   echo shar: Extracting \"'Makefile'\" \(1496 characters\)
  27.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  28. X#
  29. X# Makefile for md4
  30. X#
  31. X
  32. XINSTALLDIR=/usr/local/bin
  33. XMAN_DIR=/usr/man/manl
  34. XMAN_SEC=l
  35. X
  36. XPROGS = md4 checkmd4 hashmd4
  37. X
  38. Xall: $(PROGS)
  39. X
  40. Xmd4: md4.o md4driver.o
  41. X    $(CC) $(CFLAGS) -o $@ md4.o md4driver.o
  42. X
  43. Xcheckmd4:      checkmd4.o pipeit.o 
  44. X    $(CC) $(CFLAGS) -o $@ checkmd4.o pipeit.o
  45. X
  46. Xhashmd4:       hashmd4.o pipeit.o 
  47. X    $(CC) $(CFLAGS) -o $@ hashmd4.o pipeit.o
  48. X
  49. Xmd4.o:        md4.c md4.h md4driver.c
  50. Xcheckmd4.o:     checkmd4.c md4_def.h
  51. Xhashmd4:    hashmd4.c md4_def.h
  52. Xpipeit.o:    pipeit.c md4_def.h
  53. X
  54. Xclean:
  55. X    rm -f md4driver.o md4.o
  56. X    rm -f checkmd4.o hashmd4.o pipeit.o
  57. X
  58. Xclobber: clean
  59. X    rm -f $(PROGS)
  60. X
  61. Xprint: print_md4 print_tools print_rfc
  62. X    cprint README | lpr
  63. X    cprint TestArticle | lpr
  64. X    cprint Makefile | lpr
  65. X
  66. Xprint_tools:
  67. X    cprint checkmd4.c | lpr
  68. X    cprint hashmd4.c  | lpr
  69. X    cprint pipeit.c  | lpr
  70. X    cprint md4_def.h | lpr
  71. X    psroff -man checkmd4.1
  72. X    psroff -man hashmd4.1
  73. X
  74. Xprint_md4:
  75. X    cprint md4.h | lpr
  76. X    cprint md4.c | lpr
  77. X    cprint md4driver.c | lpr
  78. X
  79. Xprint_rfc:
  80. X    cprint rfc1186 | lpr
  81. X
  82. Xinstall:        all
  83. X    @echo Installing according to local convention
  84. X#    strip md4 checkmd4 hashmd4
  85. X#    cp md4 checkmd4 hashmd4 $(INSTALLDIR)
  86. X#    chown bin $(INSTALLDIR)/md4 
  87. X#    chgrp bin $(INSTALLDIR)/md4 
  88. X#    chmod 755 $(INSTALLDIR)/md4 
  89. X#    chown bin $(INSTALLDIR)/checkmd4 
  90. X#    chgrp bin $(INSTALLDIR)/checkmd4 
  91. X#    chmod 755 $(INSTALLDIR)/checkmd4 
  92. X#    chown bin $(INSTALLDIR)/hashmd4
  93. X#    chgrp bin $(INSTALLDIR)/hashmd4
  94. X#    chmod 755 $(INSTALLDIR)/hashmd4
  95. X#    cp checkmd4.1 $(MAN_DIR)/checkmd4.$(MAN_SEC)
  96. X#    cp hashmd4.1 $(MAN_DIR)/hashmd4.$(MAN_SEC)
  97. X#
  98. END_OF_FILE
  99.   if test 1496 -ne `wc -c <'Makefile'`; then
  100.     echo shar: \"'Makefile'\" unpacked with wrong size!
  101.   fi
  102.   # end of 'Makefile'
  103. fi
  104. if test -f 'TestArticle' -a "${1}" != "-c" ; then 
  105.   echo shar: Will not clobber existing file \"'TestArticle'\"
  106. else
  107.   echo shar: Extracting \"'TestArticle'\" \(3146 characters\)
  108.   sed "s/^X//" >'TestArticle' <<'END_OF_FILE'
  109. XPath: sparky!kent
  110. XFrom: kent@sparky.imd.sterling.com (Kent Landfield)
  111. XNewsgroups: sterling.test
  112. XSubject: This is a test of the MD4 fingerprint function
  113. XOrganization: Sterling Intelligence and Military Division
  114. XX-Md4-Signature: ea6ec5dcd12eb080587e12a6b4ceae23
  115. X
  116. XAs stated in RFC1186:
  117. X   This  note describes the MD4 message digest algorithm.  The algorithm
  118. X   takes as input an input message of arbitrary length and produces as
  119. X   output a 128-bit "fingerprint" or "message digest" of the input.  It
  120. X   is conjectured that it is computationally infeasible to produce two
  121. X   messages having the same message digest, or to produce any message
  122. X   having a given prespecified target message digest.  The MD4 algorithm
  123. X   is thus ideal for digital signature applications, where a large file
  124. X   must be "compressed" in a secure manner before being signed with the
  125. X   RSA public-key cryptosystem.
  126. X
  127. XMD4 can be used to apply a fingerprint on an article posted to USENET that,
  128. Xwhen run through a verification tool, will tell you whether an article has 
  129. Xbeen corrupted. It does not detect or prevent complete replacement of the
  130. Xarticle. Think of MD4 as a super-strong checksum.
  131. X
  132. XThis package is an "assembled" set of tools that uses the MD4 Message 
  133. XDigest Algorithm specified in RFC1186.  There are three parts to the package. 
  134. X
  135. Xmd4 - This is the heart of the tools. The code was taken from RFC1186, 
  136. X      "The MD4 Message Digest Algorithm" authored by Ronald L. Rivest.
  137. X
  138. XI *completely* and shamefully stole the MD4 code from the RFC and as such it 
  139. Xmust be distributed under the terms specified in md4.c, md4.h and md4driver.c.
  140. XThanks to Ron for the code and to RSA Data Security, Inc. for giving me the
  141. Xpermission to post it.
  142. X
  143. Xhashmd4 -  This program is used to apply an MD4 digest on a specified
  144. X           USENET article.  A new header is added to the article. The
  145. X           header X-Md4-Signature: contains the value that will be checked
  146. X           against to determine if the article is intact.
  147. X
  148. Xcheckmd4 - This is the program used to check whether the MD4 digest
  149. X           of a USENET article indicates whether or not the article
  150. X           has been tampered with.
  151. X
  152. XI would like to thank Rich Salz for posting snefru and giving me something
  153. Xto "hack".. :-) checkmd4 and hashmd4 look almost exactly like Rich's code
  154. Xfor good reason. They are... I did the bare minimum to get this working.
  155. XThat's all I had to do... :-)  For those of you currently using hashnews
  156. Xand checknews, this (other than the names) should be a plug amd play...
  157. X
  158. XThere are manual pages for checkmd4 and for hashmd4 supplied.  The actual 
  159. XRFC1186 is supplied as a reference for MD4.
  160. X
  161. XCode that does not contain an explicit RSA copyright was derived from
  162. XRich Salz's code that was already in the public domain. Feel free to do 
  163. Xwhat you want with those pieces.
  164. X
  165. XThis code needs a 32bit machine; good luck if you've only got 16 bits!
  166. X
  167. XStarting with this posting, I am going to be using hashmd4 on all my
  168. Xc.s.m articles.  While I don't think that this is worth doing for most
  169. Xgeneral Usenix articles, I think it will be an interesting experiment for
  170. Xarchives. 
  171. X
  172. XEnjoy!
  173. X        -Kent+
  174. END_OF_FILE
  175.   if test 3146 -ne `wc -c <'TestArticle'`; then
  176.     echo shar: \"'TestArticle'\" unpacked with wrong size!
  177.   fi
  178.   # end of 'TestArticle'
  179. fi
  180. if test -f 'checkmd4.1' -a "${1}" != "-c" ; then 
  181.   echo shar: Will not clobber existing file \"'checkmd4.1'\"
  182. else
  183.   echo shar: Extracting \"'checkmd4.1'\" \(1024 characters\)
  184.   sed "s/^X//" >'checkmd4.1' <<'END_OF_FILE'
  185. X.TH CHECKMD4 1 LOCAL
  186. X.SH NAME
  187. Xcheckmd4 \- Check the MD4 hash code on a Usenet article
  188. X.SH SYNOPSIS
  189. X.B checkmd4
  190. X[
  191. X.B \-n
  192. X] [
  193. X.I input
  194. X]
  195. X.SH DESCRIPTION
  196. X.I Checkmd4
  197. Xreads a Usenet article from the named file, or standard input if no file
  198. Xis given.
  199. XIt filters out the headers and calls
  200. X.IR md4 
  201. X(see RFC1186) to generate a one-way hash signature or "message digest" for 
  202. Xthe article.  It compares this with the value specified in the X-Md4-Signature:
  203. Xheader, and prints a message indicating whether they match or not.
  204. XTo suppress the message, use the ``\-s'' flag.
  205. X.PP
  206. XThe program will exit with status zero if the article is okay. An exit value
  207. Xof one is returned if the signatures don't match, or a two if no 
  208. XX-Md4-Signature header can be found.
  209. X.SH WARNING
  210. X.I Checkmd4
  211. Xwill only prove if an article has been tampered with; it does not
  212. Xprovide any authentication.
  213. X.SH AUTHOR
  214. X.nf
  215. XOriginally written by Rich Salz <rsalz@bbn.com>
  216. XHacked by Kent Landfield <kent@sparky.imd.sterling.com>
  217. X.fi
  218. X.SH "SEE ALSO"
  219. Xhashmd4(1L), RFC1186.
  220. END_OF_FILE
  221.   if test 1024 -ne `wc -c <'checkmd4.1'`; then
  222.     echo shar: \"'checkmd4.1'\" unpacked with wrong size!
  223.   fi
  224.   # end of 'checkmd4.1'
  225. fi
  226. if test -f 'checkmd4.c' -a "${1}" != "-c" ; then 
  227.   echo shar: Will not clobber existing file \"'checkmd4.c'\"
  228. else
  229.   echo shar: Extracting \"'checkmd4.c'\" \(2713 characters\)
  230.   sed "s/^X//" >'checkmd4.c' <<'END_OF_FILE'
  231. X/*
  232. X**  Verify a Usenet article with a MD4 hash header.
  233. X*/
  234. X#include <stdio.h>
  235. X#include <ctype.h>
  236. X#include "md4_def.h"
  237. X
  238. X#ifndef    isascii
  239. X#define isascii(c)    (1)
  240. X#endif    /* isascii */
  241. X
  242. Xextern char    *optarg;
  243. Xextern int    optind;
  244. X
  245. Xextern char    *mktemp();
  246. Xextern char    *Md4Close();
  247. Xextern char    *strcpy();
  248. Xextern FILE    *Md4Open();
  249. X
  250. X
  251. Xstatic void
  252. XUsage()
  253. X{
  254. X    (void)fprintf(stderr, "Usage: checkhash [filename]\n");
  255. X    exit(1);
  256. X}
  257. X
  258. X
  259. Xmain(ac, av)
  260. X    int        ac;
  261. X    char    *av[];
  262. X{
  263. X    char    *p;
  264. X    char    buff[BUFSIZ];
  265. X    char    Checksum[40];
  266. X    FILE    *Input;
  267. X    FILE    *Md4;
  268. X    int        i;
  269. X    int        Silent;
  270. X
  271. X    /* Set defaults. */
  272. X    Silent = FALSE;
  273. X
  274. X    /* Parse JCL. */
  275. X    while ((i = getopt(ac, av, "s")) != EOF)
  276. X    switch (i) {
  277. X    default:
  278. X        Usage();
  279. X        /* NOTREACHED */
  280. X    case 's':
  281. X        Silent = TRUE;
  282. X        break;
  283. X    }
  284. X
  285. X    /* Get input. */
  286. X    ac -= optind;
  287. X    av += optind;
  288. X    switch (ac) {
  289. X    default:
  290. X    Usage();
  291. X    case 0:
  292. X    Input = stdin;
  293. X    break;
  294. X    case 1:
  295. X    if ((Input = fopen(av[0], "r")) == NULL) {
  296. X        perror("No input");
  297. X        (void)fprintf(stderr, "Can't open \"%s\" for reading.\n", av[0]);
  298. X        exit(1);
  299. X    }
  300. X    break;
  301. X    }
  302. X
  303. X    /* Read headers, looking for the checksum. */
  304. X    Checksum[0] = '\0';
  305. X    while (fgets(buff, sizeof buff, Input)) {
  306. X    if (buff[0] == '\n')
  307. X        break;
  308. X    if (buff[0] == HDRFIRSTCHAR
  309. X     && strncmp(buff, CHECKSUMHDR, sizeof CHECKSUMHDR - 1) == 0) {
  310. X        p = &buff[sizeof CHECKSUMHDR] + 1;
  311. X        /* Right length, allowing for the newline? */
  312. X        if (strlen(p) != HDRTEXTSIZE + 1) {
  313. X        if (!Silent)
  314. X            (void)printf("%d Wrong length:\n\t%s", strlen(p) ,buff);
  315. X        continue;
  316. X        }
  317. X        (void)strcpy(Checksum, p);
  318. X        Checksum[HDRTEXTSIZE] = '\0';
  319. X        for (p = Checksum; *p; p++)
  320. X        if (*p != ' ' && !(isascii(*p) && isxdigit(*p)))
  321. X            break;
  322. X        if (*p) {
  323. X        if (!Silent)
  324. X            (void)printf("Bad character '%c':\n\t%s", *p, buff);
  325. X        /* Broke out before reaching the end, invalid header. */
  326. X        Checksum[0] = '\0';
  327. X        }
  328. X    }
  329. X    }
  330. X
  331. X    if (Checksum[0] == '\0') {
  332. X    if (!Silent)
  333. X        (void)printf("No valid checksum header found.\n");
  334. X    exit(2);
  335. X    }
  336. X
  337. X    /* Call up Md4. */
  338. X    if ((Md4 = Md4Open()) == NULL) {
  339. X    if (!Silent)
  340. X        perror("Can't open pipe to md4");
  341. X    exit(2);
  342. X    }
  343. X
  344. X    /* Send the rest of the article down the pipe. */
  345. X    while (fgets(buff, sizeof buff, Input))
  346. X    (void)fputs(buff, Md4);
  347. X    (void)fclose(Input);
  348. X
  349. X    if ((p = Md4Close()) == NULL) {
  350. X    if (!Silent)
  351. X        perror("Can't open tempfile");
  352. X    exit(2);
  353. X    }
  354. X
  355. X    /* Compare them. */
  356. X    if (strcmp(p, Checksum) == 0) {
  357. X    if (!Silent)
  358. X        (void)printf("Valid.\n");
  359. X    exit(0);
  360. X    }
  361. X    if (!Silent) {
  362. X    (void)printf("Invalid!\n");
  363. X    (void)printf("Computed: %s\n", p);
  364. X    (void)printf("  Posted: %s\n", Checksum);
  365. X    }
  366. X    exit(1);
  367. X}
  368. END_OF_FILE
  369.   if test 2713 -ne `wc -c <'checkmd4.c'`; then
  370.     echo shar: \"'checkmd4.c'\" unpacked with wrong size!
  371.   fi
  372.   # end of 'checkmd4.c'
  373. fi
  374. if test -f 'hashmd4.1' -a "${1}" != "-c" ; then 
  375.   echo shar: Will not clobber existing file \"'hashmd4.1'\"
  376. else
  377.   echo shar: Extracting \"'hashmd4.1'\" \(1586 characters\)
  378.   sed "s/^X//" >'hashmd4.1' <<'END_OF_FILE'
  379. X.TH HASHMD4 1 LOCAL
  380. X.SH NAME
  381. Xhashmd4 \- add a MD4 hash to a Usenet article
  382. X.SH SYNOPSIS
  383. X.B hashmd4
  384. X[
  385. X.B \-n
  386. X] [
  387. X.I input
  388. X]
  389. X.SH DESCRIPTION
  390. XThis program is used to apply an MD4 digest, or fingerprint, on an article 
  391. Xintended to be posted to USENET.
  392. X.I Hashmd4
  393. Xadds the X-Md4-Signature: header to the article. The header contains 
  394. Xthe article's MD4 signature value that will be checked by 
  395. X.IR checkmd4 
  396. Xto determine if the article is intact. 
  397. X.I Hashmd4
  398. Xcalls
  399. X.IR md4
  400. X(See RFC1186) to generate a one-way hash signature for the article.
  401. X.PP
  402. XIf a file is named on the command line, then
  403. X.I hashmd4
  404. Xwill overwrite the named file after inserting the md4 hashcode.
  405. XIf no file is named, the program will read the article from standard
  406. Xinput, and write the new article on standard output; this makes it
  407. Xconvenient to do ``:%!hashmd4'' from
  408. X.IR vi (1)
  409. Xjust before exiting the editor with your article in it.
  410. X.PP
  411. XBy default,
  412. X.I hashmd4
  413. Xwill try to read the file ``.signature'' in your home directory and
  414. Xappend it to the article.
  415. XIt tries to simulate the actions of B2.11
  416. X.IR inews (8).
  417. XTo suppress this check (for example, if you append your own signature),
  418. Xuse the ``\-n'' flag.
  419. XThe header that hashmd4 puts on an article is of the form
  420. X.IP
  421. XX-Md4-Signature: value
  422. X.SH WARNING
  423. X.I Hashmd4
  424. Xusage will only prove if an article has or has no been tampered with. It
  425. Xdoes not provide any authentication.
  426. X.SH AUTHOR
  427. X.nf
  428. XOriginally written as hashnews for snefru by Rich Salz <rsalz@bbn.com>
  429. XHacked into hashmd4 by Kent Landfield <kent@sparky.imd.sterling.com>
  430. X.fi
  431. X.SH "SEE ALSO"
  432. Xcheckmd4(1L), RFC1186.
  433. END_OF_FILE
  434.   if test 1586 -ne `wc -c <'hashmd4.1'`; then
  435.     echo shar: \"'hashmd4.1'\" unpacked with wrong size!
  436.   fi
  437.   # end of 'hashmd4.1'
  438. fi
  439. if test -f 'hashmd4.c' -a "${1}" != "-c" ; then 
  440.   echo shar: Will not clobber existing file \"'hashmd4.c'\"
  441. else
  442.   echo shar: Extracting \"'hashmd4.c'\" \(4909 characters\)
  443.   sed "s/^X//" >'hashmd4.c' <<'END_OF_FILE'
  444. X/*
  445. X**  Call MD4 on something about to be feed into INEWS.  Then, rewrite
  446. X**  the file to add the X-Md4-Signature header.
  447. X*/
  448. X#include <stdio.h>
  449. X#include <pwd.h>
  450. X#include "md4_def.h"
  451. X
  452. X#ifdef    USE_STRCHR
  453. X#define IDX    strchr
  454. X#else
  455. X#define IDX    index
  456. X#endif    /* USE_STRCHR */
  457. X
  458. X#ifndef    SEEK_ABS
  459. X#define SEEK_ABS    0
  460. X#endif    /* SEEK_ABS */
  461. X
  462. Xextern char    *optarg;
  463. Xextern int    optind;
  464. X
  465. Xextern char        *getenv();
  466. Xextern char        *IDX();
  467. Xextern char        *mktemp();
  468. Xextern char        *Md4Close();
  469. Xextern char        *strcpy();
  470. Xextern FILE        *Md4Open();
  471. Xextern long        ftell();
  472. Xextern struct passwd    *getpwuid();
  473. X#ifdef    CHARPSPRINTF
  474. Xextern char    *sprintf();
  475. X#endif    /* CHARPSPRINTF */
  476. X
  477. Xstatic void
  478. XUsage()
  479. X{
  480. X    (void)fprintf(stderr, "Usage: hashmd4 articlename\n");
  481. X    exit(1);
  482. X}
  483. X
  484. X
  485. X/*
  486. X**  Simulate what B2.11 inews does for appending signatures.
  487. X*/
  488. Xstatic int
  489. XAppendSignature(Md4)
  490. X    FILE        *Md4;
  491. X{
  492. X    char        *p;
  493. X    char        buff[256];
  494. X    FILE        *F;
  495. X    int            i;
  496. X    struct passwd    *pwd;
  497. X
  498. X    if ((p = getenv("HOME")) == NULL
  499. X     && (p = getenv("LOGDIR")) == NULL) {
  500. X    if ((pwd = getpwuid(getuid())) == NULL)
  501. X        return 0;
  502. X    p = pwd->pw_dir;
  503. X    }
  504. X    (void)sprintf(buff, "%s/.signature", p);
  505. X    if ((F = fopen(buff, "r")) == NULL)
  506. X    return 0;
  507. X    for (i = 0; fgets(buff, sizeof buff, F); i++)
  508. X    if (IDX(buff, '\n') == NULL) {
  509. X        i = 0;
  510. X        break;
  511. X    }
  512. X    if (i > 5 || i == 0) {
  513. X    (void)fclose(F);
  514. X    return 0;
  515. X    }
  516. X    (void)fprintf(Md4, "-- \n");
  517. X    rewind(F);
  518. X    while (fgets(buff, sizeof buff, F))
  519. X    (void)fputs(buff, Md4);
  520. X    (void)fclose(F);
  521. X    return i;
  522. X}
  523. X
  524. X
  525. Xmain(ac, av)
  526. X    int        ac;
  527. X    char    *av[];
  528. X{
  529. X    int        i;
  530. X    int        CheckSignature;
  531. X    FILE    *Input;
  532. X    FILE    *Md4;
  533. X    FILE    *Output;
  534. X    FILE    *Body;
  535. X    char    buff[BUFSIZ];
  536. X    char    *p;
  537. X    char    tempfile[20];
  538. X    char    bodyfile[20];
  539. X    long    cookie;
  540. X
  541. X    /* Set defaults. */
  542. X    CheckSignature = TRUE;
  543. X
  544. X    /* Parse JCL. */
  545. X    while ((i = getopt(ac, av, "n")) != EOF)
  546. X    switch (i) {
  547. X    default:
  548. X        Usage();
  549. X    case 'n':
  550. X        CheckSignature = FALSE;
  551. X        break;
  552. X    }
  553. X
  554. X    /* Get input. */
  555. X    ac -= optind;
  556. X    av += optind;
  557. X    switch (ac) {
  558. X    default:
  559. X    Usage();
  560. X    /* NOTREACHED */
  561. X    case 0:
  562. X    /* We're being piped into.  Create a temp file to hold the
  563. X     * article body. */
  564. X    Input = stdin;
  565. X    (void)strcpy(bodyfile, "/tmp/hashBXXXXXX");
  566. X    (void)mktemp(bodyfile);
  567. X    if ((Body = fopen(bodyfile, "w")) == NULL) {
  568. X        perror("No temporary");
  569. X        (void)fprintf(stderr, "Can't open \"%s\" for writing.\n",
  570. X            bodyfile);
  571. X        exit(1);
  572. X    }
  573. X    break;
  574. X    case 1:
  575. X    if ((Input = fopen(av[0], "r")) == NULL) {
  576. X        perror("No input");
  577. X        (void)fprintf(stderr, "Can't open \"%s\" for reading.\n", av[0]);
  578. X        exit(1);
  579. X    }
  580. X    Body = NULL;
  581. X    break;
  582. X    }
  583. X
  584. X    /* Get output file. */
  585. X    (void)strcpy(tempfile, "/tmp/hashHXXXXXX");
  586. X    (void)mktemp(tempfile);
  587. X    if ((Output = fopen(tempfile, "w")) == NULL) {
  588. X    perror("No output");
  589. X    (void)fprintf(stderr, "Can't open \"%s\" for writing.\n", tempfile);
  590. X    exit(1);
  591. X    }
  592. X
  593. X    /* Open stream to md4. */
  594. X    if ((Md4 = Md4Open()) == NULL) {
  595. X    perror("Can't open pipe to md4");
  596. X    (void)fclose(Output);
  597. X    (void)unlink(tempfile);
  598. X    exit(1);
  599. X    }
  600. X
  601. X    /* Read article, skipping headers. */
  602. X    while (fgets(buff, sizeof buff, Input)) {
  603. X    if (buff[strlen(buff) - 1] != '\n')
  604. X        (void)fprintf(stderr, "Warning, line truncated:\n%s\n",
  605. X            buff);
  606. X    if (buff[0] == '\n')
  607. X        break;
  608. X    (void)fputs(buff, Output);
  609. X    }
  610. X
  611. X    /* If not from stdin we can seek, so remember where the headers end. */
  612. X    if (Body == NULL)
  613. X    cookie = ftell(Input);
  614. X
  615. X    /* Send rest of article to md4. */
  616. X    while (fgets(buff, sizeof buff, Input)) {
  617. X    if (buff[strlen(buff) - 1] != '\n')
  618. X        (void)fprintf(stderr, "Warning, line truncated:\n%s\n",
  619. X            buff);
  620. X    (void)fputs(buff, Md4);
  621. X    if (Body)
  622. X        (void)fputs(buff, Body);
  623. X    }
  624. X
  625. X    /* Do the signature? */
  626. X    if (CheckSignature) {
  627. X    if ((i = AppendSignature(Md4)) == 0)
  628. X        (void)fprintf(stderr, ".signature unreadable or too long...\n");
  629. X    }
  630. X
  631. X    (void)fclose(Input);
  632. X
  633. X    /* Write the checksum. */
  634. X    if (p = Md4Close())
  635. X    (void)fprintf(Output, "%s: %s\n", CHECKSUMHDR, p);
  636. X    else
  637. X    (void)fprintf(stderr, "Md4 checksum lost!?\n");
  638. X
  639. X    /* Send the article body. */
  640. X    if (Body) {
  641. X    (void)fclose(Body);
  642. X    Input = fopen(bodyfile, "r");
  643. X    }
  644. X    else {
  645. X    Input = fopen(av[0], "r");
  646. X    (void)fseek(Input, cookie, SEEK_ABS);
  647. X    }
  648. X    (void)fputs("\n", Output);
  649. X    while (fgets(buff, sizeof buff, Input))
  650. X    (void)fputs(buff, Output);
  651. X    (void)fclose(Output);
  652. X
  653. X    if (Input == stdin)
  654. X    /* Input is stdin, so send output to stdout. */
  655. X    Output = stdout;
  656. X    else if ((Output = fopen(av[0], "w")) == NULL) {
  657. X    perror("Can't rewrite file");
  658. X    (void)fprintf(stderr,
  659. X        "Can't overwrite \"%s\", output is in \"%s\".\n",
  660. X        av[0], tempfile);
  661. X    exit(1);
  662. X    }
  663. X
  664. X    Input = fopen(tempfile, "r");
  665. X    while (fgets(buff, sizeof buff, Input))
  666. X    (void)fputs(buff, Output);
  667. X
  668. X    if (Output != stdout);
  669. X    (void)unlink(tempfile);
  670. X    (void)fclose(Output);
  671. X    exit(0);
  672. X}
  673. END_OF_FILE
  674.   if test 4909 -ne `wc -c <'hashmd4.c'`; then
  675.     echo shar: \"'hashmd4.c'\" unpacked with wrong size!
  676.   fi
  677.   # end of 'hashmd4.c'
  678. fi
  679. if test -f 'md4.h' -a "${1}" != "-c" ; then 
  680.   echo shar: Will not clobber existing file \"'md4.h'\"
  681. else
  682.   echo shar: Extracting \"'md4.h'\" \(3266 characters\)
  683.   sed "s/^X//" >'md4.h' <<'END_OF_FILE'
  684. X/*
  685. X*--------------------------------------------------------------------------*
  686. X* (C) Copyright 1990, RSA Data Security, Inc.  All rights reserved.        *
  687. X* License to copy and use this software is granted provided it is          *
  688. X* identified as the "RSA Data Security, Inc. MD4 message digest algorithm" *
  689. X* in all material mentioning or referencing this software or function.     *
  690. X*                                                                          *
  691. X* License is also granted to make and use derivative works provided such   *
  692. X* works are identified as "derived from the RSA Data Securitry, Inc. MD4   *
  693. X* message digest algorithm" in all material mentioning or referencing the  *
  694. X* derived work.                                                            *
  695. X*                                                                          *
  696. X* RSA Data Security, Inc. makes no representations concerning the          *
  697. X* merchantability of this software or the suitability of the software      *
  698. X* for any particular purpose.  It is provided "as is" without express      *
  699. X* or implied warranty of any kind.                                         *
  700. X*                                                                          *
  701. X* These notices must be retained in any copies of any part of this         *
  702. X* documentation and/or software.                                           *
  703. X*--------------------------------------------------------------------------*
  704. X** ********************************************************************
  705. X** md4.h -- Header file for implementation of                        **
  706. X** MD4 Message Digest Algorithm                                      **
  707. X** Updated: 2/13/90 by Ronald L. Rivest                              **
  708. X** (C) 1990 RSA Data Security, Inc.                                  **
  709. X** ********************************************************************
  710. X*/
  711. X
  712. X/* MDstruct is the data structure for a message digest computation.
  713. X*/
  714. Xtypedef struct {
  715. X  unsigned int buffer[4]; /* Holds 4-word result of MD computation */
  716. X  unsigned char count[8]; /* Number of bits processed so far */
  717. X  unsigned int done;      /* Nonzero means MD computation finished */
  718. X} MDstruct, *MDptr;
  719. X
  720. X/* MDbegin(MD)
  721. X** Input: MD -- an MDptr
  722. X** Initialize the MDstruct prepatory to doing a message digest
  723. X** computation.
  724. X*/
  725. Xextern void MDbegin();
  726. X
  727. X/* MDupdate(MD,X,count)
  728. X** Input: MD -- an MDptr
  729. X**        X -- a pointer to an array of unsigned characters.
  730. X**        count -- the number of bits of X to use (an unsigned int).
  731. X** Updates MD using the first "count" bits of X.
  732. X** The array pointed to by X is not modified.
  733. X** If count is not a multiple of 8, MDupdate uses high bits of
  734. X** last byte.
  735. X** This is the basic input routine for a user.
  736. X** The routine terminates the MD computation when count < 512, so
  737. X** every MD computation should end with one call to MDupdate with a
  738. X** count less than 512.  Zero is OK for a count.
  739. X*/
  740. Xextern void MDupdate();
  741. X
  742. X/* MDprint(MD)
  743. X** Input: MD -- an MDptr
  744. X** Prints message digest buffer MD as 32 hexadecimal digits.
  745. X** Order is from low-order byte of buffer[0] to high-order byte
  746. X** of buffer[3].
  747. X** Each byte is printed with high-order hexadecimal digit first.
  748. X*/
  749. Xextern void MDprint();
  750. X
  751. X/*
  752. X** End of md4.h
  753. X*/
  754. END_OF_FILE
  755.   if test 3266 -ne `wc -c <'md4.h'`; then
  756.     echo shar: \"'md4.h'\" unpacked with wrong size!
  757.   fi
  758.   # end of 'md4.h'
  759. fi
  760. if test -f 'md4driver.c' -a "${1}" != "-c" ; then 
  761.   echo shar: Will not clobber existing file \"'md4driver.c'\"
  762. else
  763.   echo shar: Extracting \"'md4driver.c'\" \(4915 characters\)
  764.   sed "s/^X//" >'md4driver.c' <<'END_OF_FILE'
  765. X/*
  766. X*--------------------------------------------------------------------------*
  767. X* (C) Copyright 1990, RSA Data Security, Inc.  All rights reserved.        *
  768. X* License to copy and use this software is granted provided it is          *
  769. X* identified as the "RSA Data Security, Inc. MD4 message digest algorithm" *
  770. X* in all material mentioning or referencing this software or function.     *
  771. X*                                                                          *
  772. X* License is also granted to make and use derivative works provided such   *
  773. X* works are identified as "derived from the RSA Data Securitry, Inc. MD4   *
  774. X* message digest algorithm" in all material mentioning or referencing the  *
  775. X* derived work.                                                            *
  776. X*                                                                          *
  777. X* RSA Data Security, Inc. makes no representations concerning the          *
  778. X* merchantability of this software or the suitability of the software      *
  779. X* for any particular purpose.  It is provided "as is" without express      *
  780. X* or implied warranty of any kind.                                         *
  781. X*                                                                          *
  782. X* These notices must be retained in any copies of any part of this         *
  783. X* documentation and/or software.                                           *
  784. X*--------------------------------------------------------------------------*
  785. X** ********************************************************************
  786. X** md4driver.c -- sample routines to test                            **
  787. X** MD4 message digest algorithm.                                     **
  788. X** Updated: 2/16/90 by Ronald L. Rivest                              **
  789. X** (C) 1990 RSA Data Security, Inc.                                  **
  790. X** ********************************************************************
  791. X*/
  792. X
  793. X#include <stdio.h>
  794. X#include "md4.h"
  795. X
  796. X/* MDtimetrial()
  797. X** A time trial routine, to measure the speed of MD4.
  798. X** Measures speed for 1M blocks = 64M bytes.
  799. X*/
  800. XMDtimetrial()
  801. X{ unsigned int X[16];
  802. X  MDstruct MD;
  803. X  int i;
  804. X  double t;
  805. X  for (i=0;i<16;i++) X[i] = 0x01234567 + i;
  806. X  printf
  807. X  ("MD4 time trial. Processing 1 million 64-character blocks...\n");
  808. X  clock();
  809. X  MDbegin(&MD);
  810. X  for (i=0;i<1000000;i++) MDupdate(&MD,X,512);
  811. X  MDupdate(&MD,X,0);
  812. X  t = (double) clock(); /* in microseconds */
  813. X  MDprint(&MD); printf(" is digest of 64M byte test input.\n");
  814. X  printf("Seconds to process test input:   %g\n",t/1e6);
  815. X  printf("Characters processed per second: %ld.\n",(int)(64e12/t));
  816. X}
  817. X
  818. X/* MDstring(s)
  819. X** Computes the message digest for string s.
  820. X** Prints out message digest, a space, the string (in quotes) and a
  821. X** carriage return.
  822. X*/
  823. XMDstring(s)
  824. Xunsigned char *s;
  825. X{ unsigned int i, len = strlen(s);
  826. X  MDstruct MD;
  827. X  MDbegin(&MD);
  828. X  for (i=0;i+64<=len;i=i+64) MDupdate(&MD,s+i,512);
  829. X  MDupdate(&MD,s+i,(len-i)*8);
  830. X  MDprint(&MD);
  831. X  printf(" \"%s\"\n",s);
  832. X}
  833. X
  834. X/* MDfile(filename)
  835. X** Computes the message digest for a specified file.
  836. X** Prints out message digest, a space, the file name, and a
  837. X** carriage return.
  838. X*/
  839. XMDfile(filename)
  840. Xchar *filename;
  841. X{ FILE *f = fopen(filename,"rb");
  842. X  unsigned char X[64];
  843. X  MDstruct MD;
  844. X  int b;
  845. X  if (f == NULL)
  846. X     { printf("%s can't be opened.\n",filename); return; }
  847. X  MDbegin(&MD);
  848. X  while ((b=fread(X,1,64,f))!=0) MDupdate(&MD,X,b*8);
  849. X  MDupdate(&MD,X,0);
  850. X  MDprint(&MD);
  851. X  printf(" %s\n",filename);
  852. X  fclose(f);
  853. X}
  854. X
  855. X/* MDfilter()
  856. X** Writes the message digest of the data from stdin onto stdout,
  857. X** followed by a carriage return.
  858. X*/
  859. XMDfilter()
  860. X{ unsigned char X[64];
  861. X  MDstruct MD;
  862. X  int b;
  863. X  MDbegin(&MD);
  864. X  while ((b=fread(X,1,64,stdin))!=0) MDupdate(&MD,X,b*8);
  865. X  MDupdate(&MD,X,0);
  866. X  MDprint(&MD);
  867. X  printf("\n");
  868. X}
  869. X
  870. X/* MDtestsuite()
  871. X** Run a standard suite of test data.
  872. X*/
  873. XMDtestsuite()
  874. X{
  875. X  printf("MD4 test suite results:\n");
  876. X  MDstring("");
  877. X  MDstring("a");
  878. X  MDstring("abc");
  879. X  MDstring("message digest");
  880. X  MDstring("abcdefghijklmnopqrstuvwxyz");
  881. X  MDstring
  882. X  ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
  883. X  MDfile("foo"); /* Contents of file foo are "abc" */
  884. X}
  885. X
  886. Xmain(argc,argv)
  887. Xint argc;
  888. Xchar *argv[];
  889. X{ int i;
  890. X  /* For each command line argument in turn:
  891. X  ** filename          -- prints message digest and name of file
  892. X  ** -sstring          -- prints message digest and contents of string
  893. X  ** -t                -- prints time trial statistics for 64M bytes
  894. X  ** -x                -- execute a standard suite of test data
  895. X  ** (no args)         -- writes messages digest of stdin onto stdout
  896. X  */
  897. X  if (argc==1) MDfilter();
  898. X  else
  899. X    for (i=1;i<argc;i++)
  900. X      if (argv[i][0]=='-' && argv[i][1]=='s') MDstring(argv[i]+2);
  901. X      else if (strcmp(argv[i],"-t")==0)       MDtimetrial();
  902. X      else if (strcmp(argv[i],"-x")==0)       MDtestsuite();
  903. X      else                                    MDfile(argv[i]);
  904. X}
  905. X
  906. X/*
  907. X** end of md4driver.c
  908. X*/
  909. END_OF_FILE
  910.   if test 4915 -ne `wc -c <'md4driver.c'`; then
  911.     echo shar: \"'md4driver.c'\" unpacked with wrong size!
  912.   fi
  913.   # end of 'md4driver.c'
  914. fi
  915. if test -f 'pipeit.c' -a "${1}" != "-c" ; then 
  916.   echo shar: Will not clobber existing file \"'pipeit.c'\"
  917. else
  918.   echo shar: Extracting \"'pipeit.c'\" \(1266 characters\)
  919.   sed "s/^X//" >'pipeit.c' <<'END_OF_FILE'
  920. X/*
  921. X**  Utility routines to interface to the MD4 program as a filter.
  922. X*/
  923. X#include <stdio.h>
  924. X#include "md4_def.h"
  925. X
  926. X#ifdef    USE_STRCHR
  927. X#define RDX    strrchr
  928. X#else
  929. X#define RDX    rindex
  930. X#endif    /* USE_STRCHR */
  931. X
  932. Xstatic char    OutputFile[] = "/tmp/hashcodeXXXXXX";
  933. Xstatic char    ChecksumBuffer[HDRTEXTSIZE + 2];
  934. Xstatic FILE    *Stream;
  935. X
  936. Xextern char    *RDX();
  937. Xextern char    *mktemp();
  938. X#ifdef    CHARPSPRINTF
  939. Xextern char    *sprintf();
  940. X#endif    /* CHARPSPRINTF */
  941. X
  942. X
  943. X/*
  944. X**  Spawn a MD4 that has its output redirected.
  945. X*/
  946. XFILE *
  947. XMd4Open()
  948. X{
  949. X    char    buff[sizeof OutputFile + 20];
  950. X
  951. X    /* Open stream to md4. */
  952. X    (void)mktemp(OutputFile);
  953. X    (void)sprintf(buff, "md4 >%s", OutputFile);
  954. X    if ((Stream = popen(buff, "w")) == NULL)
  955. X    (void)unlink(OutputFile);
  956. X    return Stream;
  957. X}
  958. X
  959. X
  960. X/*
  961. X**  Close the pipe and read in the Md4's output.
  962. X*/
  963. Xchar *
  964. XMd4Close()
  965. X{
  966. X    FILE    *F;
  967. X    char    *p;
  968. X
  969. X    (void)pclose(Stream);
  970. X
  971. X    /* Open the output file, read the one line. */
  972. X    if ((F = fopen(OutputFile, "r")) == NULL)
  973. X    return NULL;
  974. X    p = fgets(ChecksumBuffer, sizeof ChecksumBuffer, F);
  975. X    (void)fclose(F);
  976. X    (void)unlink(OutputFile);
  977. X    if (p == NULL)
  978. X    return NULL;
  979. X
  980. X    /* Kill the newline. */
  981. X    if ((p = RDX(ChecksumBuffer, '\n')) == NULL)
  982. X    return NULL;
  983. X    *p = '\0';
  984. X    return ChecksumBuffer;
  985. X}
  986. END_OF_FILE
  987.   if test 1266 -ne `wc -c <'pipeit.c'`; then
  988.     echo shar: \"'pipeit.c'\" unpacked with wrong size!
  989.   fi
  990.   # end of 'pipeit.c'
  991. fi
  992. echo shar: End of archive 2 \(of 2\).
  993. cp /dev/null ark2isdone
  994. MISSING=""
  995. for I in 1 2 ; do
  996.     if test ! -f ark${I}isdone ; then
  997.     MISSING="${MISSING} ${I}"
  998.     fi
  999. done
  1000. if test "${MISSING}" = "" ; then
  1001.     echo You have unpacked both archives.
  1002.     rm -f ark[1-9]isdone
  1003. else
  1004.     echo You still must unpack the following archives:
  1005.     echo "        " ${MISSING}
  1006. fi
  1007. exit 0
  1008. exit 0 # Just in case...
  1009. -- 
  1010. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1011. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1012. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1013. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1014. exit 0 # Just in case...
  1015. -- 
  1016. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1017. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1018. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1019. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1020.