rsalz@bbn.com (Rich Salz) (03/23/90)
Submitted-by: Rich $alz <rsalz@bbn.com> Posting-number: Volume 21, Issue 19 Archive-name: snefru/part01 This is my revision of Ralph Merkle's SNEFRU program. Snefru is a one-way hash algorithm: given some input text, Snefru will come up with a single number such that no two texts will hash down to the same number. In this way, Snefru can tell you whether an article has been corrupted, but not if it is authentic or not -- think of it as a super-strong checksum. Starting with this posting, I am going to be using hashnews on all my c.s.u articles. While I don't think that this is worth doing for most general Usenix articles, I think it will be an interesting experiment for archives. I completely rewrote and reorganized the code that Ralph has made available. For example, I split the comments out into manual pages, and put all the tests out into a separate program. What I'm making available is a derived work, and therefore must be distributed under the same terms as Ralph's original code. Thanks to him and Xerox for making his work available. Some of the programs and manual pages are my original work, and therefore don't contain the Xerox copyright. They are in the public domain, and feel free to do what you want with them. This code needs a 32bit machine; good luck if you've only got 16 bits! To compile, edit the Makefile if you use strchr/strrchr rather than index/rindex. Also edit snefru.c to determine the byte order of your machine. Once that's done, do "make tests" to verify the output. If you get wrong answers, the first thing to suspect is the byte order. Enjoy, Rich $alz <rsalz@bbn.com> #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 4)." # Contents: HISTORY MANIFEST Makefile README TestArticle checkhash.1 # checkhash.c hashn.c hashnews.1 hashnews.c patchlevel.h pipeit.c # snefru.1 snefru.c snefru.h tests.sh # Wrapped by rsalz@litchi.bbn.com on Thu Mar 22 13:36:36 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'HISTORY' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'HISTORY'\" else echo shar: Extracting \"'HISTORY'\" \(4975 characters\) sed "s/^X//" >'HISTORY' <<'END_OF_FILE' XThis is Snefru, derived from the Xerox Secure Hash Function. XSnefru is a one-way hash function that provides authentication. XIt does not provide secrecy. X XSnefru is named after a Pharaoh of ancient Egypt. X XIt is based on code that is: X Copyright (c) Xerox Corporation 1989. All rights reserved. X X License to copy and use this software is granted provided that it X is identified as the 'Xerox Secure Hash Function' in all material X mentioning or referencing this software or this hash function. X X License is also granted to make and use derivative works provided X that such works are identified as 'derived from the Xerox Secure X Hash Function' in all material mentioning or referencing the X derived work. X X Xerox Corporation makes no representations concerning either the X merchantability of this software or the suitability of this X software for any particular purpose. It is provided "as is" X without express or implied warranty of any kind. X X These notices must be retained in any copies of any part of this X software. X XBased on the reference implementation (no algorithm changes) of Xversion 2.0, July 31, 1989. Implementor: Ralph C. Merkle. XThis edition is by Rich $alz, <rsalz@bbn.com>. X$Header: HISTORY,v 1.1 90/03/22 12:57:43 rsalz Exp $ X X XREVISION HISTORY X---------------- XVersion 2.0 is algorithmically different from versions 1.4 and 1.3. X XIn particular, version 2.0 makes the following changes: X1) The S-boxes in version 2.0 have been computed in accordance with a X publicly known algorithm. X X2) The special case handling of inputs shorter than 64 bytes has been X deleted. This special case code offered little performance advantage X and increased the complexity of the algorithm. In addition, X Coppersmith noticed a weakness that affected the X 128-bit-input/128-bit-output version of Snefru (though not the 512-bit X input/128-bit or 256-bit output version). X X3) The parameters p0, p1, and p2 have been eliminated. There are several X reasons for this change. The principle reason is that they increase X the complexity both of the code and the conceptual complexity of the X hash function, and provide only modest improvement in security. X X4) Because the parameter mechanism was used to distinguish between inputs X that differ only in the number of trailing 0 bits, a different X mechanism has been adopted. This new mechanism simply counts the X number of bits in the input, and then places this 64-bit bit-count X into the rightmost 64-bits of the last block hashed. A slightly X different method of applying the hash also been adopted. X X5) Several people requested a larger output (to provide greater X security). Because this will not always be needed, the algorithm was X modified to generate either 128 bits or 256 bits of output, depending X on a command line option. Notice that 128 bits of output only X provides 64 "real" bits of security (because of square root attacks) X and similarly 256 bits of output provides only 128 "real" bits of X security. Use of the higher security 256-bit output will slow down the X algorithm by about 1/3 (32 bytes per application of Hash512 versus 48 X bytes per application of Hash512). X X A 128 bit output should provide adequate security for most commercial X applications (barring discovery of some unexpected weakness in the X algorithm). Where higher security is desired, the 256-bit output size X can be used. X X6) Other non-algorithmic changes have been made to the code, in keeping X with various criticisms and comments. X XVersion 1.4 X New wording of the export notice; 1.3 forbids export entirely. X XVersion 1.3 X Fixes a security bug in handling short files (64 bytes or less). Such X files should use the length of the file as a parameter to the hash, to X prevent two files of different lengths from producing the same hash X value if one file is a prefix of another. This had been done for long X files (greater than 64 bytes in length) but was overlooked for short X files. X X Improves the way in which the parameter is mixed into the hash. In X essence, the change mixes in the parameter one more time. Although a X similar effect can be achieved by increasing the security parameter by X 1 (e.g., from 2 to 3) this also increases the amount of computation X required by 50%. X X Make some more changes in the notices that accompany the code. X XVersion 1.2 X No changes in the code; only the notices that accompany the code have X changed, and some changes in the comments. X XVersion 1.1 X Added the 'convertBytes' to convert an array of 'char' into an array X of unsigned long int. This conversion is a no-op on the SUN and many X other computers, but will have an effect on the VAX and computers with X 'backwards' byte ordering. It will also SLOW DOWN THE HASH FUNCTION, X so it should be removed whenever possible if speed is an issue. END_OF_FILE if test 4975 -ne `wc -c <'HISTORY'`; then echo shar: \"'HISTORY'\" unpacked with wrong size! fi # end of 'HISTORY' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(1274 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X HISTORY 1 Revision history. X MANIFEST 1 This shipping list. X Makefile 1 Make control file. X README 1 Installation notes, etc. X TestArticle 1 Sample input to regression test. X checkhash.1 1 Manual page for checkhash. X checkhash.c 1 Check if an article matches its checksum. X hash512.c 2 Fast code to hash 512 bytes at a time. X hashn.c 1 Hash 2^N bytes at a time. X hashnews.1 1 Manual page for hashnews. X hashnews.c 1 Put a Snefru checksum in a news article. X patchlevel.h 1 Misteak recorder X pipeit.c 1 Routines to call Snefru as a filter. X sboxes.c 4 The S boxes. X snefru.1 1 Manual page for Snefru. X snefru.c 1 Main driver to hash some input. X snefru.h 1 Header file for the package. X testboxes.c1 3 Program to test the S boxes, part 1. X testboxes.c2 2 Program to test the S boxes, part 2. X tests.sh 1 Script to perform regression tests. END_OF_FILE if test 1274 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(2863 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X## X## This is Snefru, derived from the Xerox Secure Hash Function. X## Snefru is a one-way hash function that provides authentication. X## It does not provide secrecy. X## X## Snefru is named after a Pharaoh of ancient Egypt. X## X## It is based on code that is: X## Copyright (c) Xerox Corporation 1989. All rights reserved. X## X## License to copy and use this software is granted provided that it X## is identified as the 'Xerox Secure Hash Function' in all material X## mentioning or referencing this software or this hash function. X## X## License is also granted to make and use derivative works provided X## that such works are identified as 'derived from the Xerox Secure X## Hash Function' in all material mentioning or referencing the X## derived work. X## X## Xerox Corporation makes no representations concerning either the X## merchantability of this software or the suitability of this X## software for any particular purpose. It is provided "as is" X## without express or implied warranty of any kind. X## X## These notices must be retained in any copies of any part of this X## software. X## X## Based on the reference implementation (no algorithm changes) of X## version 2.0, July 31, 1989. Implementor: Ralph C. Merkle. X## This edition is by Rich $alz, <rsalz@bbn.com>. X## $Header: Makefile,v 1.1 90/03/22 12:57:52 rsalz Exp $ X## X X## Add -DUSE_STRCHR here if you use strchr/strrchr. X## Add -DCHARPSPRINTF here if you need "extern char *sprinf();" XDEFS = -DCHARPSPRINTF XCFLAGS = $(DEFS) -O X#CFLAGS = $(DEFS) -g X X X## Xall: snefru testboxes hashnews checkhash X Xinstall: all X @echo Install according to local convention X Xclean: X rm -f foo core tags lint* a.out tests *.o Part0? X rm -f snefru testboxes hashnews checkhash testboxes.c X Xtests: all tests.sh lint X @rm -f $@ X sh ./tests.sh | tee tests X Xshar: X makekit -m -t "Now see the README" X X## Xsnefru.o hash512.o sboxes.o: snefru.h Xtestboxes.o hashn.o hash512.o: snefru.h Xcheckhash.o hashnews.o pipeit.o: snefru.h X Xtestboxes.c: testboxes.c1 testboxes.c2 X @rm -f $@ X cat testboxes.c1 testboxes.c2 >$@ X X## Xsnefru: snefru.o hash512.o sboxes.o X @rm -f $@ X $(CC) $(CFLAGS) -o $@ snefru.o hash512.o sboxes.o X Xtestboxes: testboxes.o hashn.o hash512.o sboxes.o X @rm -f $@ X $(CC) $(CFLAGS) -o $@ testboxes.o hashn.o hash512.o sboxes.o X Xcheckhash: checkhash.o pipeit.o X $(CC) $(CFLAGS) -o $@ checkhash.o pipeit.o X Xhashnews: hashnews.o pipeit.o X $(CC) $(CFLAGS) -o $@ hashnews.o pipeit.o X X## Xlint: lint.s lint.t lint.h lint.c X Xlint.s: snefru X @rm -f $@ X lint -b -h $(DEFS) snefru.c hash512.c sboxes.c >$@ Xlint.t: testboxes X @rm -f $@ X lint -b -h $(DEFS) testboxes.c hashn.c hash512.c sboxes.c >$@ Xlint.c: checkhash X @rm -f $@ X lint -b -h $(DEFS) checkhash.c pipeit.c >$@ Xlint.h: hashnews X @rm -f $@ X lint -b -h $(DEFS) hashnews.c pipeit.c >$@ END_OF_FILE if test 2863 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(1533 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X XThis is my revision of Ralph Merkle's SNEFRU program. Snefru is a one-way Xhash algorithm: given some input text, Snefru will come up with a single Xnumber such that no two texts will hash down to the same number. In this Xway, Snefru can tell you whether an article has been corrupted, but not if Xit is authentic or not -- think of it as a super-strong checksum. X XStarting with this posting, I am going to be using hashnews on all my Xc.s.u articles. While I don't think that this is worth doing for most Xgeneral Usenix articles, I think it will be an interesting experiment for Xarchives. X XI completely rewrote and reorganized the code that Ralph has made Xavailable. For example, I split the comments out into manual pages, and Xput all the tests out into a separate program. What I'm making available Xis a derived work, and therefore must be distributed under the same terms Xas Ralph's original code. Thanks to him and Xerox for making his work Xavailable. Some of the programs and manual pages are my original work, Xand therefore don't contain the Xerox copyright. They are in the public Xdomain, and feel free to do what you want with them. X XThis code needs a 32bit machine; good luck if you've only got 16 bits! X XTo compile, edit the Makefile if you use strchr/strrchr rather than Xindex/rindex. Also edit snefru.c to determine the byte order of your Xmachine. Once that's done, do "make tests" to verify the output. If you Xget wrong answers, the first thing to suspect is the byte order. X XEnjoy, X Rich $alz <rsalz@bbn.com> END_OF_FILE if test 1533 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'TestArticle' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'TestArticle'\" else echo shar: Extracting \"'TestArticle'\" \(1456 characters\) sed "s/^X//" >'TestArticle' <<'END_OF_FILE' XPath: papaya.bbn.com!rsalz XFrom: rsalz@bbn.com (Rich Salz) XNewsgroups: bbn.test XSubject: This is a test of the hashing function XMessage-ID: <2340@litchi.bbn.com> XDate: 22 Mar 90 15:53:47 GMT XDistribution: bbn XOrganization: BBN Systems and Technology, Inc. XLines: 24 X XThis is my revision of Ralph Merkle's SNEFRU program. Snefru is a one-way Xhash algorithm: given some input text, Snefru will come up with a single Xnumber. No two texts will hash down to the same number. (Think of it as Xa super-strong checksum.) X XI completely rewrote and reorganized the code that Ralph has made Xavailable. For example, I split the comments out into manual pages, and Xput all the tests out into a separate program. What I'm making available Xis a derived work, and therefore must be distributed under the same terms Xas Ralph's original code. Thanks to him and Xerox for making his work Xavailable. Some of the programs and manual pages are my work, and Xtherefore don't contain the Xerox copyright. They are in the public Xdomain, and feel free to do what you want with them. X XThis code needs a 32bit machine; good luck trying to port it elsewhere! XTo compile, edit the Makefile if you use strchr/strrchr rather than Xindex/rindex. Also edit snefru.c to determine the byte order of your Xmachine. X X /rich $alz <rsalz@bbn.com> X-- XPlease send comp.sources.unix-related mail to rsalz@uunet.uu.net. XUse a domain-based address or give alternate paths, or you may lose out. END_OF_FILE if test 1456 -ne `wc -c <'TestArticle'`; then echo shar: \"'TestArticle'\" unpacked with wrong size! fi # end of 'TestArticle' fi if test -f 'checkhash.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'checkhash.1'\" else echo shar: Extracting \"'checkhash.1'\" \(972 characters\) sed "s/^X//" >'checkhash.1' <<'END_OF_FILE' X.TH HASHNEWS 1 LOCAL X.SH NAME Xcheckhash \- Check the Snefru hash code on a Usenet article X.SH SYNOPSIS X.B checkhash X[ X.B \-n X] [ X.I input X] X.SH DESCRIPTION X.I Checkhash Xreads a Usenet article from the named file, or standard input if no file Xis given. XIt filters out the headers and calls X.IR snefru (1L) Xto generate a one-way hash code for the article. XIt compares this with the hash given in the header, and prints a message Xindicating whether they match or not. XTo suppress the message, use the ``\-s'' flag. X.PP XThe program will exit with status zero if the article is okay, a Xone if the hash codes don't match, or a two if no checksum header Xcan be found. X.SH WARNING X.I Checkhash Xwill only prove if an article has been tampered with; it does not Xprovide any authentication. XAlso, see the warnings in the X.I snefru Xmanpage. X.SH AUTHOR X.nf XRich $alz <rsalz@bbn.com> X$Header: checkhash.1,v 1.1 90/03/22 12:58:13 rsalz Exp $ X.fi X.SH "SEE ALSO" Xhashnews(1L), snefru(1L). END_OF_FILE if test 972 -ne `wc -c <'checkhash.1'`; then echo shar: \"'checkhash.1'\" unpacked with wrong size! fi # end of 'checkhash.1' fi if test -f 'checkhash.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'checkhash.c'\" else echo shar: Extracting \"'checkhash.c'\" \(2841 characters\) sed "s/^X//" >'checkhash.c' <<'END_OF_FILE' X/* X** Verify a Usenet article with a Snefru hash header. X*/ X#include <stdio.h> X#include <ctype.h> X#include "snefru.h" X#ifdef RCSID Xstatic char RCS[] = X "$Header: checkhash.c,v 1.1 90/03/22 12:58:18 rsalz Exp $"; X#endif /* RCSID */ X X#ifndef isascii X#define isascii(c) (1) X#endif /* isascii */ X Xextern char *optarg; Xextern int optind; X Xextern char *mktemp(); Xextern char *SnefruClose(); Xextern char *strcpy(); Xextern FILE *SnefruOpen(); X X Xstatic void XUsage() X{ X (void)fprintf(stderr, "Usage: checkhash [filename]\n"); X exit(1); X} X X Xmain(ac, av) X int ac; X char *av[]; X{ X char *p; X char buff[BUFSIZ]; X char Checksum[40]; X FILE *Input; X FILE *Snefru; X int i; X int Silent; X X /* Set defaults. */ X Silent = FALSE; X X /* Parse JCL. */ X while ((i = getopt(ac, av, "s")) != EOF) X switch (i) { X default: X Usage(); X /* NOTREACHED */ X case 's': X Silent = TRUE; X break; X } X X /* Get input. */ X ac -= optind; X av += optind; X switch (ac) { X default: X Usage(); X case 0: X Input = stdin; X break; X case 1: X if ((Input = fopen(av[0], "r")) == NULL) { X perror("No input"); X (void)fprintf(stderr, "Can't open \"%s\" for reading.\n", av[0]); X exit(1); X } X break; X } X X /* Read headers, looking for the checksum. */ X Checksum[0] = '\0'; X while (fgets(buff, sizeof buff, Input)) { X if (buff[0] == '\n') X break; X if (buff[0] == HDRFIRSTCHAR X && strncmp(buff, CHECKSUMHDR, sizeof CHECKSUMHDR - 1) == 0) { X p = &buff[sizeof CHECKSUMHDR] + 1; X /* Right length, allowing for the newline? */ X if (strlen(p) != HDRTEXTSIZE + 1) { X if (!Silent) X (void)printf("Wrong length:\n\t%s", buff); X continue; X } X (void)strcpy(Checksum, p); X Checksum[HDRTEXTSIZE] = '\0'; X for (p = Checksum; *p; p++) X if (*p != ' ' && !(isascii(*p) && isxdigit(*p))) X break; X if (*p) { X if (!Silent) X (void)printf("Bad character '%c':\n\t%s", *p, buff); X /* Broke out before reaching the end, invalid header. */ X Checksum[0] = '\0'; X } X } X } X X if (Checksum[0] == '\0') { X if (!Silent) X (void)printf("No valid checksum header found.\n"); X exit(2); X } X X /* Call up Snefru. */ X if ((Snefru = SnefruOpen()) == NULL) { X if (!Silent) X perror("Can't open pipe to snefru"); X exit(2); X } X X /* Send the rest of the article down the pipe. */ X while (fgets(buff, sizeof buff, Input)) X (void)fputs(buff, Snefru); X (void)fclose(Input); X X if ((p = SnefruClose()) == NULL) { X if (!Silent) X perror("Can't open tempfile"); X exit(2); X } X X /* Compare them. */ X if (strcmp(p, Checksum) == 0) { X if (!Silent) X (void)printf("Valid.\n"); X exit(0); X } X if (!Silent) { X (void)printf("Invalid!\n"); X (void)printf("Computed: %s\n", p); X (void)printf(" Posted: %s\n", Checksum); X } X exit(1); X} END_OF_FILE if test 2841 -ne `wc -c <'checkhash.c'`; then echo shar: \"'checkhash.c'\" unpacked with wrong size! fi # end of 'checkhash.c' fi if test -f 'hashn.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hashn.c'\" else echo shar: Extracting \"'hashn.c'\" \(3463 characters\) sed "s/^X//" >'hashn.c' <<'END_OF_FILE' X/* X** This is Snefru, derived from the Xerox Secure Hash Function. X** Snefru is a one-way hash function that provides authentication. X** It does not provide secrecy. X** X** Snefru is named after a Pharaoh of ancient Egypt. X** X** It is based on code that is: X** Copyright (c) Xerox Corporation 1989. All rights reserved. X** X** License to copy and use this software is granted provided that it X** is identified as the 'Xerox Secure Hash Function' in all material X** mentioning or referencing this software or this hash function. X** X** License is also granted to make and use derivative works provided X** that such works are identified as 'derived from the Xerox Secure X** Hash Function' in all material mentioning or referencing the X** derived work. X** X** Xerox Corporation makes no representations concerning either the X** merchantability of this software or the suitability of this X** software for any particular purpose. It is provided "as is" X** without express or implied warranty of any kind. X** X** These notices must be retained in any copies of any part of this X** software. X** X** Based on the reference implementation (no algorithm changes) of X** version 2.0, July 31, 1989. Implementor: Ralph C. Merkle. X** This edition is by Rich $alz, <rsalz@bbn.com>. X*/ X#include "snefru.h" X#ifdef RCSID Xstatic char RCS[] = X "$Header: hashn.c,v 1.1 90/03/22 12:58:33 rsalz Exp $"; X#endif /* RCSID */ X X Xstatic int ShiftTable[4] = { 16, 8, 16, 24 }; X X/* X** Compute the hash. X** Note that we are computing level * wordCount * 4 rounds. X*/ XHashN(output, wordCount, input, level, OutputBlockSize) X WORD32 output[OUTPUTBLOCKSIZE]; X int wordCount; X WORD32 input[]; X int level; X int OutputBlockSize; X{ X WORD32 mask; X WORD32 block[WORDCOUNT]; /* array of data being hashed */ X WORD32 SBoxEntry; X int shift; X int i; X int index; X int next; X int last; X int ByteInWord; X X /* wordCount is a power of two. */ X mask = wordCount - 1; X X#if 0 X /* Test for various error conditions and logic problems. */ X if (level * 2 > SBOXCOUNT) X abort("Too few S-boxes"); X if (wordCount > WORDCOUNT) X abort("Logic error, wordCount > WORDCOUNT"); X if (wordCount != 16) X abort("Security warning, input size not equal to 512 bits"); X /* Spectacularly insecure for small blocks, so... */ X if (wordCount < 4) X abort("wordCount too small"); X if ((wordCount & mask) != 0) X abort("Logic error, wordCount not a power of 2"); X if (OutputBlockSize > wordCount) X abort("Logic error, OutputBlockSize is too big"); X if (OutputBlockSize != 4 && OutputBlockSize != 8) X abort("Output size neither 128 nor 256 bits"); X#endif /* 0 */ X X /* Initialize the block to be encrypted from the input */ X for (i = 0; i < wordCount; i++) X block[i] = input[i]; X X for (index = 0; index < level; index++) { X for (ByteInWord = 0; ByteInWord < 4; ByteInWord++) { X for (i = 0; i < wordCount; i++) { X next = (i + 1) & mask; X last = (i + mask) & mask; /* last = (i-1) MOD wordCount */ X SBoxEntry = X SnefruSBoxes[2 * index + ((i / 2) & 1)][block[i] & 0xFF]; X block[next] ^= SBoxEntry; X block[last] ^= SBoxEntry; X } X /* Rotate right all 32-bit words in the entire block at once. */ X for (shift = ShiftTable[ByteInWord], i = 0; i < wordCount; i++) X block[i] = (block[i] >> shift) | (block[i] << (32 - shift)); X } X } X X for (i = 0; i < OutputBlockSize; i++) X output[i] = input[i] ^ block[mask - i]; X} END_OF_FILE if test 3463 -ne `wc -c <'hashn.c'`; then echo shar: \"'hashn.c'\" unpacked with wrong size! fi # end of 'hashn.c' fi if test -f 'hashnews.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hashnews.1'\" else echo shar: Extracting \"'hashnews.1'\" \(1229 characters\) sed "s/^X//" >'hashnews.1' <<'END_OF_FILE' X.TH HASHNEWS 1 LOCAL X.SH NAME Xhashnews \- add a Snefru hash to a Usenet article X.SH SYNOPSIS X.B hashnews X[ X.B \-n X] [ X.I input X] X.SH DESCRIPTION X.I Hashnews Xreads an article intended for Usenet posting and calls X.IR snefru (1L) Xto generate a one-way hash code for the article. X.PP XIf a file is named on the command line, then X.I hashnews Xwill overwrite the named file after inserting the Snefru hashcode. XIf no file is named, the program will read the article from standard Xinput, and write the new article on standard output; this makes it Xconvenient to do ``:%!hashnews'' from X.IR vi (1) Xjust before exiting the editor with your article in it. X.PP XBy default, X.I hashnews Xwill try to read the file ``.signature'' in your home directory and Xappend it to the article. XIt tries to simulate the actions of B2.11 X.IR inews (8). XTo suppress this check (for example, if you append your own signature), Xuse the ``\-n'' flag. X.SH WARNING X.I Hashnews Xwill only prove if an article has been tampered with; it does not Xprovide any authentication. XAlso, see the warnings in the X.I snefru Xmanpage. X.SH AUTHOR X.nf XRich $alz <rsalz@bbn.com> X$Header: hashnews.1,v 1.1 90/03/22 12:58:39 rsalz Exp $ X.fi X.SH "SEE ALSO" Xcheckhash(1L), snefru(1L). END_OF_FILE if test 1229 -ne `wc -c <'hashnews.1'`; then echo shar: \"'hashnews.1'\" unpacked with wrong size! fi # end of 'hashnews.1' fi if test -f 'hashnews.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hashnews.c'\" else echo shar: Extracting \"'hashnews.c'\" \(5078 characters\) sed "s/^X//" >'hashnews.c' <<'END_OF_FILE' X/* X** Call SNEFRU on something about to be feed into INEWS. Then, rewrite X** the file to add the X-Snefru-Checksum header. X*/ X#include <stdio.h> X#include <pwd.h> X#include "snefru.h" X#ifdef RCSID Xstatic char RCS[] = X "$Header: hashnews.c,v 1.1 90/03/22 12:58:44 rsalz Exp $"; X#endif /* RCSID */ X X#ifdef USE_STRCHR X#define IDX strchr X#else X#define IDX index X#endif /* USE_STRCHR */ X X#ifndef SEEK_ABS X#define SEEK_ABS 0 X#endif /* SEEK_ABS */ X Xextern char *optarg; Xextern int optind; X Xextern char *getenv(); Xextern char *IDX(); Xextern char *mktemp(); Xextern char *SnefruClose(); Xextern char *strcpy(); Xextern FILE *SnefruOpen(); Xextern long ftell(); Xextern struct passwd *getpwuid(); X#ifdef CHARPSPRINTF Xextern char *sprintf(); X#endif /* CHARPSPRINTF */ X Xstatic void XUsage() X{ X (void)fprintf(stderr, "Usage: snefru_news articlename\n"); X exit(1); X} X X X/* X** Simulate what B2.11 inews does for appeneding signatures. X*/ Xstatic int XAppendSignature(Snefru) X FILE *Snefru; X{ X char *p; X char buff[256]; X FILE *F; X int i; X struct passwd *pwd; X X if ((p = getenv("HOME")) == NULL X && (p = getenv("LOGDIR")) == NULL) { X if ((pwd = getpwuid(getuid())) == NULL) X return 0; X p = pwd->pw_dir; X } X (void)sprintf(buff, "%s/.signature", p); X if ((F = fopen(buff, "r")) == NULL) X return 0; X for (i = 0; fgets(buff, sizeof buff, F); i++) X if (IDX(buff, '\n') == NULL) { X i = 0; X break; X } X if (i > 4 || i == 0) { X (void)fclose(F); X return 0; X } X (void)fprintf(Snefru, "-- \n"); X rewind(F); X while (fgets(buff, sizeof buff, F)) X (void)fputs(buff, Snefru); X (void)fclose(F); X return i; X} X X Xmain(ac, av) X int ac; X char *av[]; X{ X int i; X int CheckSignature; X FILE *Input; X FILE *Snefru; X FILE *Output; X FILE *Body; X char buff[BUFSIZ]; X char *p; X char tempfile[20]; X char bodyfile[20]; X long cookie; X X /* Set defaults. */ X CheckSignature = TRUE; X X /* Parse JCL. */ X while ((i = getopt(ac, av, "n")) != EOF) X switch (i) { X default: X Usage(); X case 'n': X CheckSignature = FALSE; X break; X } X X /* Get input. */ X ac -= optind; X av += optind; X switch (ac) { X default: X Usage(); X /* NOTREACHED */ X case 0: X /* We're being piped into. Create a temp file to hold the X * article body. */ X Input = stdin; X (void)strcpy(bodyfile, "/tmp/hashBXXXXXX"); X (void)mktemp(bodyfile); X if ((Body = fopen(bodyfile, "w")) == NULL) { X perror("No temporary"); X (void)fprintf(stderr, "Can't open \"%s\" for writing.\n", X bodyfile); X exit(1); X } X break; X case 1: X if ((Input = fopen(av[0], "r")) == NULL) { X perror("No input"); X (void)fprintf(stderr, "Can't open \"%s\" for reading.\n", av[0]); X exit(1); X } X Body = NULL; X break; X } X X /* Get output file. */ X (void)strcpy(tempfile, "/tmp/hashHXXXXXX"); X (void)mktemp(tempfile); X if ((Output = fopen(tempfile, "w")) == NULL) { X perror("No output"); X (void)fprintf(stderr, "Can't open \"%s\" for writing.\n", tempfile); X exit(1); X } X X /* Open stream to snefru. */ X if ((Snefru = SnefruOpen()) == NULL) { X perror("Can't open pipe to snefru"); X (void)fclose(Output); X (void)unlink(tempfile); X exit(1); X } X X /* Read article, skipping headers. */ X while (fgets(buff, sizeof buff, Input)) { X if (buff[strlen(buff) - 1] != '\n') X (void)fprintf(stderr, "Warning, line truncated:\n%s\n", X buff); X if (buff[0] == '\n') X break; X (void)fputs(buff, Output); X } X X /* If not from stdin we can seek, so remember where the headers end. */ X if (Body == NULL) X cookie = ftell(Input); X X /* Send rest of article to snefru. */ X while (fgets(buff, sizeof buff, Input)) { X if (buff[strlen(buff) - 1] != '\n') X (void)fprintf(stderr, "Warning, line truncated:\n%s\n", X buff); X (void)fputs(buff, Snefru); X if (Body) X (void)fputs(buff, Body); X } X X /* Do the signature? */ X if (CheckSignature) { X if ((i = AppendSignature(Snefru)) == 0) X (void)fprintf(stderr, ".signature unreadable or too long...\n"); X } X X (void)fclose(Input); X X /* Write the checksum. */ X if (p = SnefruClose()) X (void)fprintf(Output, "%s: %s\n", CHECKSUMHDR, p); X else X (void)fprintf(stderr, "Snefru checksum lost!?\n"); X X /* Send the article body. */ X if (Body) { X (void)fclose(Body); X Input = fopen(bodyfile, "r"); X } X else { X Input = fopen(av[0], "r"); X (void)fseek(Input, cookie, SEEK_ABS); X } X (void)fputs("\n", Output); X while (fgets(buff, sizeof buff, Input)) X (void)fputs(buff, Output); X (void)fclose(Output); X X if (Input == stdin) X /* Input is stdin, so send output to stdout. */ X Output = stdout; X else if ((Output = fopen(av[0], "w")) == NULL) { X perror("Can't rewrite file"); X (void)fprintf(stderr, X "Can't overwrite \"%s\", output is in \"%s\".\n", X av[0], tempfile); X exit(1); X } X X Input = fopen(tempfile, "r"); X while (fgets(buff, sizeof buff, Input)) X (void)fputs(buff, Output); X X if (Output != stdout); X (void)unlink(tempfile); X (void)fclose(Output); X exit(0); X} END_OF_FILE if test 5078 -ne `wc -c <'hashnews.c'`; then echo shar: \"'hashnews.c'\" unpacked with wrong size! fi # end of 'hashnews.c' fi if test -f 'patchlevel.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'patchlevel.h'\" else echo shar: Extracting \"'patchlevel.h'\" \(408 characters\) sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE' X/* X** Header file for Snefru package. X** Based on the reference implementation (no algorithm changes) of X** version 2.0, July 31, 1989. Implementor: Ralph C. Merkle. X** This edition is by Rich $alz, <rsalz@bbn.com>. X** X** $Log: patchlevel.h,v $ X** Revision 1.1 90/03/22 13:34:53 rsalz X** Initial revision X** X** $Header: patchlevel.h,v 1.1 90/03/22 13:34:53 rsalz Exp $ X*/ X#define PATCHLEVEL 0 END_OF_FILE if test 408 -ne `wc -c <'patchlevel.h'`; then echo shar: \"'patchlevel.h'\" unpacked with wrong size! fi # end of 'patchlevel.h' fi if test -f 'pipeit.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pipeit.c'\" else echo shar: Extracting \"'pipeit.c'\" \(1397 characters\) sed "s/^X//" >'pipeit.c' <<'END_OF_FILE' X/* X** Utility routines to interface to the Snefru program as a filter. X*/ X#include <stdio.h> X#include "snefru.h" X#ifdef RCSID Xstatic char RCS[] = X "$Header: pipeit.c,v 1.1 90/03/22 12:59:01 rsalz Exp $"; X#endif /* RCSID */ X X X#ifdef USE_STRCHR X#define RDX strrchr X#else X#define RDX rindex X#endif /* USE_STRCHR */ X Xstatic char OutputFile[] = "/tmp/hashcodeXXXXXX"; Xstatic char ChecksumBuffer[HDRTEXTSIZE + 2]; Xstatic FILE *Stream; X Xextern char *RDX(); Xextern char *mktemp(); X#ifdef CHARPSPRINTF Xextern char *sprintf(); X#endif /* CHARPSPRINTF */ X X X/* X** Spawn a Snefru that has its output redirected. X*/ XFILE * XSnefruOpen() X{ X char buff[sizeof OutputFile + 20]; X X /* Open stream to snefru. */ X (void)mktemp(OutputFile); X (void)sprintf(buff, "snefru >%s", OutputFile); X if ((Stream = popen(buff, "w")) == NULL) X (void)unlink(OutputFile); X return Stream; X} X X X/* X** Close the pipe and read in the Snefru's output. X*/ Xchar * XSnefruClose() X{ X FILE *F; X char *p; X X (void)pclose(Stream); X X /* Open the output file, read the one line. */ X if ((F = fopen(OutputFile, "r")) == NULL) X return NULL; X p = fgets(ChecksumBuffer, sizeof ChecksumBuffer, F); X (void)fclose(F); X (void)unlink(OutputFile); X if (p == NULL) X return NULL; X X /* Kill the newline. */ X if ((p = RDX(ChecksumBuffer, '\n')) == NULL) X return NULL; X *p = '\0'; X return ChecksumBuffer; X} END_OF_FILE if test 1397 -ne `wc -c <'pipeit.c'`; then echo shar: \"'pipeit.c'\" unpacked with wrong size! fi # end of 'pipeit.c' fi if test -f 'snefru.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'snefru.1'\" else echo shar: Extracting \"'snefru.1'\" \(3886 characters\) sed "s/^X//" >'snefru.1' <<'END_OF_FILE' X.TH SNEFRU 1 LOCAL X.SH NAME Xsnefru \- Experimental secure one-way hash function X.SH SYNOPSIS X.B snefru X[ X.BI \-l # X] [ X.BI \-o # X] X.SH DESCRIPTION X.I Snefru Xreads standard input, hashes it with a cryptographically secure one-way Xhash function, and prints the hash code on the standard output. XThe input can be any size. XThe output can be either 128 bits, printed as four 32-byte hexadecimal Xnumbers, or 256 bits, printed as eight numbers. XTo set the output, use the ``\-o'' flag, with either the value four or Xeight. X.PP XThe security level is set by the ``\-l'' flag, which determines the number Xof iterations in the hash. XPick a number between two and four, inclusive. X.PP XThe primary use of one-way hash functions is to determine if there have Xbeen any unauthorized, malicious, or accidental changes made to a file. XFor example, if an executable program file produces the following hash: X.RS X209884c4 2e89d967 5456ac0e 61269550 X.RE Xthen any change to that program file will cause the hash to be changed. XThus, the tampering can be detected by comparing the current output value Xwith the previously computed (and presumably correct) output value. X.SH INTERNALS X.I Hash512 Xis the central routine in this program. XIt is used in this Xprogram in a linear fashion \(em i.e., a sequential file is hashed down by Xrepeated applications of X.IR Hash512 . XChanging a single bit in the file would then require completely Xre-computing the hash from the point of change onward. X.PP X.I Hash512 Xcan be used in a tree-structured fashion to authenticate a large Xtable of data. XThis would imply that changing a single bit would not force a complete Xre-computation of the hash value, but would instead require only X.I "log n" Xre-computations of X.I Hash512 Xto ``patch up'' the changes along the path from the root to the Xchanged leaf entry. XA tree-structured application also has the advantage that any single entry Xin the table can subsequently be authenticated by someone who knows only Xthe ``authentication path'' from the root of the tree to the leaf entry. XThese concepts are discussed more thoroughly in X.I "Secrecy, Authentication, and Public Key Systems" Xby Ralph C. Merkle, UMI Research Press, 1982 (see particularly Chapter 2, X.IR "One Way Hash Functions" ). XThe use of a tree-structured pattern of applications of a one-way hash Xfunction is covered by U.S. Patent #4,309,569, X.I "Method of Providing Digital Signatures" X(contact Stanford University, Office of Technology Licensing). X.PP XAt the present time (July 31, 1989) the author knows of no method for Xbreaking this one-way function, (i.e., finding two input files that Xproduce the same output value). XThe algorithm has undergone some review for security. XFurther review is expected. Use of this algorithm for production use is Xnot recomended at this time. XNote that we are specifically examining the security of X.I Hash512 Xwith a 512-bit input and a 128-bit output, and X.I Hash512 Xwith a 512-bit input and a 256-bit output. XUse of other sizes is not recomended at this time. XIn particular, we recomend against the use of output sizes smaller than X128 bits, and recomend against the use of an input that is less than two Xtimes the size of the output. XWhen the input size equals the output size, X.I Snefru Xsuffers a serious degradation in security (an observation due to XCoppersmith). X.SH WARNINGS XIf anyone using this program finds two different inputs that produce the Xsame output, please contact X.RS X.nf XRalph C. Merkle, <merkle@xerox.com> XXerox PARC X3333 Coyote Hill Road XPalo Alto, CA 94304 X(415) 494\-4000 X.fi X.RE X.SH AUTHOR X.nf XBased on the reference implementation (no algorithm changes) of Xversion 2.0, July 31, 1989. Implementor: Ralph C. Merkle. XThis edition is by Rich $alz, <rsalz@bbn.com>. X$Header: snefru.1,v 1.1 90/03/22 13:00:08 rsalz Exp $ X.fi X.SH "SEE ALSO" X.IR "A Software One Way Hash Function" , Xby Ralph C. Merkle. END_OF_FILE if test 3886 -ne `wc -c <'snefru.1'`; then echo shar: \"'snefru.1'\" unpacked with wrong size! fi # end of 'snefru.1' fi if test -f 'snefru.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'snefru.c'\" else echo shar: Extracting \"'snefru.c'\" \(8565 characters\) sed "s/^X//" >'snefru.c' <<'END_OF_FILE' X/* X** This is Snefru, derived from the Xerox Secure Hash Function. X** Snefru is a one-way hash function that provides authentication. X** It does not provide secrecy. X** X** Snefru is named after a Pharaoh of ancient Egypt. X** X** It is based on code that is: X** Copyright (c) Xerox Corporation 1989. All rights reserved. X** X** License to copy and use this software is granted provided that it X** is identified as the 'Xerox Secure Hash Function' in all material X** mentioning or referencing this software or this hash function. X** X** License is also granted to make and use derivative works provided X** that such works are identified as 'derived from the Xerox Secure X** Hash Function' in all material mentioning or referencing the X** derived work. X** X** Xerox Corporation makes no representations concerning either the X** merchantability of this software or the suitability of this X** software for any particular purpose. It is provided "as is" X** without express or implied warranty of any kind. X** X** These notices must be retained in any copies of any part of this X** software. X** X** Based on the reference implementation (no algorithm changes) of X** version 2.0, July 31, 1989. Implementor: Ralph C. Merkle. X** This edition is by Rich $alz, <rsalz@bbn.com>. X*/ X#include <stdio.h> X#include "snefru.h" X#ifdef RCSID Xstatic char RCS[] = X "$Header: snefru.c,v 1.1 90/03/22 13:00:13 rsalz Exp $"; X#endif /* RCSID */ X X#define SIZEOF(s) (sizeof s / sizeof s[0]) X X X/* X** Get the byte order. If the four bytes 1 2 3 4 are stored as 1234, X** then we can do punning on the byte/word buffers, and just quickly X** copy things. If not, we have to shuffle between buffers. X*/ X#if defined(sun) && !defined(i386) X /* All Sun's except the 386i. */ X#define BYTESHILO X#endif /* .. */ X X#if defined(mc300) || defined(mc500) || defined(u3b2) X /* The Masscomp MC5500 and MC5500-PEP and the ATT3b2. */ X#define BYTESHILO X#endif /* .. */ X Xextern char *optarg; Xextern int optind; X X X/* X** Convert a byte array to an array of WORD32. Primarily intended to X** eliminate the byte-ordering problem (e.g., a Vax orders the bytes in a X** character array differently than a Sun does). Using this will slow the X** hash function! This is only needed on Vax-like machines, and can be X** removed for Sun3-like byteorders. X*/ Xstatic void XBytesToWords(Cbuffer, Wbuffer) X register char *Cbuffer; X register WORD32 *Wbuffer; X{ X#ifdef BYTESHILO X register WORD32 *pun; X register int i; X X for (pun = (WORD32 *)Cbuffer, i = BUFFERSIZEINWORDS; --i >= 0; ) X *Wbuffer++ = *pun++; X#else /* BYTESHILO */ X register int i; X register WORD32 t0; X register WORD32 t1; X register WORD32 t2; X register WORD32 t3; X X for (i = BUFFERSIZEINWORDS; --i >= 0; Cbuffer += 4) { X t0 = Cbuffer[0] & 0xFF; X t1 = Cbuffer[1] & 0xFF; X t2 = Cbuffer[2] & 0xFF; X t3 = Cbuffer[3] & 0xFF; X *Wbuffer++ = (t0 << 24) | (t1 << 16) | (t2 << 8) | t3; X } X#endif /* BYTESHILO */ X} X X Xstatic void XUsage() X{ X (void)fprintf(stderr, "Usage: snefru [-l#] [-o#] [inputfile]\n"); X (void)fprintf(stderr, "Where %s and %s.\n", X "-l takes 2, 3, or 4", "-o takes 4 or 8"); X exit(1); X} X X X/* X** Read the input, hashes it, and prints the result. Much of the logic X** in the main program is taken up with the trivia of buffer management, X** error checking, command-line parameter checking, self-tests, and the X** like. The actual use of the hash function occupies a modest portion of X** the overall program. X** X** The basic idea is simple. As an example, if H is the hash function X** that produces either 128-bit (or 256-bit) outputs, and if we pick an X** input string that is 3 "chunks" long then we are computing: X** X** output = H( H( H( H(0 || chunk[0]) || chunk[1]) || chunk[2]) || bit-length) X** X** "||" is the concatenation operator, and is used to concatenate the X** output field of the preceding computation of H with the next "chunk" X** of bits from the input. X** X** "bit-length" is a "chunk" sized field into which has been put the X** length of the input, in bits, right justified. Note that the size of X** a "chunk" is just the input size minus the output size. X** X** "0" is a vector of 0 bits of the same size (in bits) as the output of X** H (i.e., either 128 or 256 bits). X** X** "chunk" is an array which holds the input string. The final element of X** the array is left justified and zero-filled on the right. X** X*/ Xmain(ac, av) X int ac; X char *av[]; X{ X WORD32 BitCount[2]; X WORD32 hashArray[INPUTBLOCKSIZE]; X WORD32 hash[OUTPUTBLOCKSIZE]; X WORD32 Wbuffer[BUFFERSIZEINWORDS]; X char Cbuffer[BUFFERSIZE]; X int OutputBlockSize; X int ChunkSize; X int ByteCount; X int Index; X int GotEOF; X int i; X int level; X X /* Set up defaults. Four 32-bit word (128 bits) with two iterations. */ X OutputBlockSize = 4; X ChunkSize = INPUTBLOCKSIZE - 4; X level = 2; X X /* Parse JCL. */ X while ((i = getopt(ac, av, "l:o:")) != EOF) X switch (i) { X default: X Usage(); X /* NOTREACHED */ X case 'l': X level = atoi(optarg); X if (level != 2 && level != 3 && level != 4) X Usage(); X break; X case 'o': X OutputBlockSize = atoi(optarg); X if (OutputBlockSize != 4 && OutputBlockSize != 8) X Usage(); X ChunkSize = INPUTBLOCKSIZE - OutputBlockSize; X if ((BUFFERSIZEINWORDS % ChunkSize) != 0) { X (void)fprintf(stderr, "Buffer size is fouled up\n"); X exit(1); X } X break; X } X X /* Get input. */ X ac -= optind; X av += optind; X switch (ac) { X default: X Usage(); X /* NOTREACHED */ X case 0: X break; X case 1: X if (freopen(av[0], "r", stdin) == NULL) { X perror("No input"); X (void)fprintf(stderr, "Can't open \"%s\" for reading.\n", av[0]); X Usage(); X } X break; X } X X /* Set up for the fast hash routine */ X SetupHash512(); X X BitCount[0] = 0; X BitCount[1] = 0; X X /* Get some input. */ X ByteCount = fread(Cbuffer, sizeof Cbuffer[0], SIZEOF(Cbuffer), stdin); X if (ByteCount < 0) { X perror("First read failed"); X exit(1); X } X GotEOF = ByteCount != SIZEOF(Cbuffer); X X /* Increment bit-count; bump upper 32 bits when lower 32 wraps. */ X BitCount[1] += ByteCount * 8; X if (BitCount[1] < ByteCount * 8) X BitCount[0]++; X X /* Zero out rest of buffer, convert to words, set readpoint. */ X for (i = ByteCount; i < SIZEOF(Cbuffer); i++) X Cbuffer[i] = 0; X BytesToWords(Cbuffer, Wbuffer); X X for (i = 0; i < SIZEOF(hashArray); i++) X hashArray[i] = 0; X X /* Hash each chunk in the input (either 48 byte chunks or 32 byte chunks) X * and keep the result in hashArray. Note that the first 16 (32) X * bytes of hashArray holds the output of the previous hash computation. */ X Index = 0; X while (ByteCount > 0) { X if (Index + ChunkSize > SIZEOF(Cbuffer)) { X (void)fprintf(stderr, "Can't happen, buffer overrun.\n"); X exit(1); X } X X /* Get next chunk and hash it in. */ X for (i = 0; i < ChunkSize; i++) X hashArray[OutputBlockSize + i] = Wbuffer[Index + i]; X Hash512(hashArray, hashArray, level, OutputBlockSize); X X /* Move to next chunk. */ X Index += ChunkSize; X ByteCount -= ChunkSize * 4; X X /* Out of data -- read some more */ X if (ByteCount <= 0) { X if (GotEOF == 1) X ByteCount = 0; X else { X if (ByteCount != 0) { X (void)fprintf(stderr, "Can't happen, error near EOF.\n"); X exit(1); X } X ByteCount = fread(Cbuffer, sizeof Cbuffer[0], X SIZEOF(Cbuffer), stdin); X if (ByteCount < 0) { X perror("Read failed"); X exit(1); X } X if (ByteCount != SIZEOF(Cbuffer)) X GotEOF = 1; X } X X /* Increment bit-count; bump upper 32 bits when lower 32 wraps. */ X BitCount[1] += ByteCount * 8; X if (BitCount[1] < ByteCount * 8) X BitCount[0] += 1; X X /* Zero out rest of buffer, convert to words, set readpoint. */ X for (i = ByteCount; i < SIZEOF(Cbuffer); i++) X Cbuffer[i] = 0; X BytesToWords(Cbuffer, Wbuffer); X Index = 0; X } X } X X X /* Zero out the remainder of hashArray. */ X for (i = 0; i < ChunkSize; i++) X hashArray[OutputBlockSize + i] = 0; X X /* Put the 64-bit bit-count into the final 64-bits of the block about to X * be hashed */ X hashArray[INPUTBLOCKSIZE - 2] = BitCount[0]; X hashArray[INPUTBLOCKSIZE - 1] = BitCount[1]; X X /* Final hash down. */ X Hash512(hash, hashArray, level, OutputBlockSize); X X /* 'hash' now holds the hashed result, which is printed on stdout. */ X for (i = 0; i < OutputBlockSize; i++) X (void)printf("%s%08x", i ? " " : "", hash[i]); X (void)printf("\n"); X exit(0); X} END_OF_FILE if test 8565 -ne `wc -c <'snefru.c'`; then echo shar: \"'snefru.c'\" unpacked with wrong size! fi # end of 'snefru.c' fi if test -f 'snefru.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'snefru.h'\" else echo shar: Extracting \"'snefru.h'\" \(2314 characters\) sed "s/^X//" >'snefru.h' <<'END_OF_FILE' X/* X** This is Snefru, derived from the Xerox Secure Hash Function. X** Snefru is a one-way hash function that provides authentication. X** It does not provide secrecy. X** X** Snefru is named after a Pharaoh of ancient Egypt. X** X** It is based on code that is: X** Copyright (c) Xerox Corporation 1989. All rights reserved. X** X** License to copy and use this software is granted provided that it X** is identified as the 'Xerox Secure Hash Function' in all material X** mentioning or referencing this software or this hash function. X** X** License is also granted to make and use derivative works provided X** that such works are identified as 'derived from the Xerox Secure X** Hash Function' in all material mentioning or referencing the X** derived work. X** X** Xerox Corporation makes no representations concerning either the X** merchantability of this software or the suitability of this X** software for any particular purpose. It is provided "as is" X** without express or implied warranty of any kind. X** X** These notices must be retained in any copies of any part of this X** software. X** X** Based on the reference implementation (no algorithm changes) of X** version 2.0, July 31, 1989. Implementor: Ralph C. Merkle. X** This edition is by Rich $alz, <rsalz@bbn.com>. X** $Header: snefru.h,v 1.1 90/03/22 13:00:52 rsalz Exp $ X*/ X#include "patchlevel.h" X X#if !defined(lint) && !defined(SABER) X#define RCSID X#endif /* .. */ X X /* Size in 32-bit words of an input block to the hash routine. */ X#define INPUTBLOCKSIZE 16 X /* Size in 32-bit words of largest output block from the hash routine. */ X#define OUTPUTBLOCKSIZE 8 X /* This MUST be 3 * 2**n, where n > 5. */ X#define BUFFERSIZE 3072 X /* Buffer size is normally in bytes, but sometimes we need it in words. */ X#define BUFFERSIZEINWORDS (BUFFERSIZE / 4) X /* Number of S boxes. */ X#define SBOXCOUNT 8 X /* Maximum valid value for wordCount. */ X#define WORDCOUNT 16 X X /* This MUST be 32 bits. */ Xtypedef unsigned long int WORD32; X /* An S-box. */ Xtypedef WORD32 SBOX[256]; X X /* The standard S boxes are defined in another file. */ Xextern SBOX SnefruSBoxes[SBOXCOUNT]; X X#define CHECKSUMHDR "X-Checksum-Snefru" X#define HDRFIRSTCHAR 'X' X#define TRUE 1 X#define FALSE 0 X#define HDRTEXTSIZE (8 + 1 + 8 + 1 + 8 + 1 + 8) END_OF_FILE if test 2314 -ne `wc -c <'snefru.h'`; then echo shar: \"'snefru.h'\" unpacked with wrong size! fi # end of 'snefru.h' fi if test -f 'tests.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tests.sh'\" else echo shar: Extracting \"'tests.sh'\" \(4334 characters\) sed "s/^X//" >'tests.sh' <<'END_OF_FILE' X#! /bin/sh X## X## This is Snefru, derived from the Xerox Secure Hash Function. X## Snefru is a one-way hash function that provides authentication. X## It does not provide secrecy. X## X## Snefru is named after a Pharaoh of ancient Egypt. X## X## It is based on code that is: X## Copyright (c) Xerox Corporation 1989. All rights reserved. X## X## License to copy and use this software is granted provided that it X## is identified as the 'Xerox Secure Hash Function' in all material X## mentioning or referencing this software or this hash function. X## X## License is also granted to make and use derivative works provided X## that such works are identified as 'derived from the Xerox Secure X## Hash Function' in all material mentioning or referencing the X## derived work. X## X## Xerox Corporation makes no representations concerning either the X## merchantability of this software or the suitability of this X## software for any particular purpose. It is provided "as is" X## without express or implied warranty of any kind. X## X## These notices must be retained in any copies of any part of this X## software. X## X## Based on the reference implementation (no algorithm changes) of X## version 2.0, July 31, 1989. Implementor: Ralph C. Merkle. X## This edition is by Rich $alz, <rsalz@bbn.com>. X## $Header: tests.sh,v 1.1 90/03/22 13:01:34 rsalz Exp $ X## X## Script to test SNEFRU one-way hash program. X## X X## This is a pain in the neck; we (portably) want a file with only a newline X## in it. XT=snefruT$$ Xcat <<\EOF >$T X XEOF X Xtrap 'exec rm -f snefru?$$' 1 2 3 15 XI=snefruI$$ XO=snefruO$$ X Xecho 'Testing SNEFRU...' Xecho 'If you see any unusual output, examine this script to see what failed.' Xecho '' X./testboxes X Xecho '' Xecho 'Testing known hashes...' X./snefru <$T >$O Xecho '13af7619 ab98d4b5 f5e0a9e6 b26b5452' >$I Xdiff $O $I X Xecho 1 | ./snefru >$O Xecho '578c83f8 8fe1f6a8 c119d2ba 3a9256c2' >$I Xdiff $O $I X Xecho 12 | ./snefru >$O Xecho '255468d4 b4bd985b 696a7313 6027fc80' >$I Xdiff $O $I X Xecho 123 | ./snefru >$O Xecho 'f5339a52 9c4dafc5 34fe3f0d 7a66baf7' >$I Xdiff $O $I X Xecho 1234 | ./snefru >$O Xecho '2645ff86 9a6c0ec6 5c49c20d d9050165' >$I Xdiff $O $I X Xecho 12345 | ./snefru >$O Xecho '387d2929 8ed52ece 88e64f38 fe4fdb11' >$I Xdiff $O $I X Xecho 123456 | ./snefru >$O Xecho 'f29f8915 d23a0e02 838cc2e2 75f5dfe7' >$I Xdiff $O $I X Xecho 1234567 | ./snefru >$O Xecho '4fb0f76e 9af16a2d 61844b9c e833e18f' >$I Xdiff $O $I X Xecho 12345678 | ./snefru >$O Xecho 'aacc56fc 85910fef e81fc697 6b061f4e' >$I Xdiff $O $I X Xecho 123456789 | ./snefru >$O Xecho 'e6997849 44ed68a1 c762ea1e 90c77967' >$I Xdiff $O $I X X./snefru -l4 -o8 <$T >$O Xecho \ X '6c504351 ce7f4b7a 93adb29a f9781ff9 2150f157 fee18661 eef511a3 0fc83ddf' >$I Xdiff $O $I X Xecho '1' | ./snefru -l4 -o8 >$O Xecho \ X '65d657f8 85ad8b4a b35999cc 3ded8b82 7cf71fa4 25424750 35778910 d6c2e320' >$I Xdiff $O $I X Xecho '12' | ./snefru -l4 -o8 >$O Xecho \ X '7636f3d1 af139cf9 58f46f99 66221282 a444732a 7de59da5 d3481c6b bd6e7092' >$I Xdiff $O $I X Xecho '123' | ./snefru -l4 -o8 >$O Xecho \ X 'cd3c7163 5b14c7c2 c24be864 4baab592 b8ab5b99 91ee5ee5 b3cf7a7f c6426ad7' >$I Xdiff $O $I X Xecho '1234' | ./snefru -l4 -o8 >$O Xecho \ X '9ba783a1 290cb21e fe196a02 3286ece5 49394c75 1ddd607e 5d67c4dc 549c62eb' >$I Xdiff $O $I X Xecho '12345' | ./snefru -l4 -o8 >$O Xecho \ X 'c9680da8 ef00d2f8 4459a8e9 b50ada71 c63cae6f dcb6f774 f6998783 30a4a1f4' >$I Xdiff $O $I X Xecho '123456' | ./snefru -l4 -o8 >$O Xecho \ X '7656d389 f980bbe8 94152abe c6dc5f16 faf21c60 3b8f5098 861acf3c c059467b' >$I Xdiff $O $I X Xecho '1234567' | ./snefru -l4 -o8 >$O Xecho \ X 'd96eb599 8377bb1d 74a02a2f 00ac9a85 3175250e 4796af36 36609747 372bba80' >$I Xdiff $O $I X Xecho '12345678' | ./snefru -l4 -o8 >$O Xecho \ X 'b7818f09 2118e98a 140af09a 6cca4e6f 1eba88e7 52c20174 653637c9 d628f33f' >$I Xdiff $O $I X Xecho '123456789' | ./snefru -l4 -o8 >$O Xecho \ X 'c2242249 1187baaa 94725400 08dffd5b 38f01557 9f3f2390 50969991 fdc1a810' >$I Xdiff $O $I X X Xecho '' Xecho 'Testing hashnews...' Xcat TestArticle >snefruA$$ X./hashnews -n snefruA$$ Xecho 'X-Checksum-Snefru: 1cb551db 1a84ad94 3d5d4267 571a9efd' >$I Xgrep '^X-Checksum-Snefru: ' snefruA$$ >$O Xdiff $O $I X./hashnews -n <TestArticle >$O Xdiff snefruA$$ $O X Xecho '' Xecho 'Testing checkhash...' Xcheckhash snefruA$$ X Xrm -f snefru?$$ Xecho '' Xecho 'Done.' END_OF_FILE if test 4334 -ne `wc -c <'tests.sh'`; then echo shar: \"'tests.sh'\" unpacked with wrong size! fi # end of 'tests.sh' fi echo shar: End of archive 1 \(of 4\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. echo "Now see the README" rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.