Cryptography-Digest Digest #413, Volume #9       Sun, 18 Apr 99 02:13:04 EDT

Contents:
  Re: Thought question:  why do public ciphers use only simple ops like shift and XOR?
  Re: Thought question:  why do public ciphers use only simple ops like shift and XOR?
  Re: New drop in cipher in the spirit of TEA (David Wagner)
  Re: Thought question:  why do public ciphers use only simple ops like shift and XOR?
  Re: Extreme lossy text compression (David Wagner)
  IEEE P1363 June Meeting Announcement (IEEE P1363)
  Re: Adequacy of FIPS-140 (wtshaw)
  Re: Question on confidence derived from cryptanalysis. (Terry Ritter)
  Re: Extreme lossy text compression (Boris Kazak)

----------------------------------------------------------------------------

From: [EMAIL PROTECTED] ()
Subject: Re: Thought question:  why do public ciphers use only simple ops like shift 
and XOR?
Date: 18 Apr 99 02:10:22 GMT

Bruce Schneier ([EMAIL PROTECTED]) wrote:
: For a standard cipher at least, sticking to the RISC subset is just
: smart.

My comment on that paragraph is that he forgot S-boxes, which, if one is
using the RISC subset, one cannot omit. But looking at the rest of his
post, I don't think he was thinking of things like data-dependent
rotations, multiplication, and so on, as much as he was thinking of more
creative use of S-boxes or more creative combinations of RISC-subset
operations.

Think FROG. Or recall my "Mishmash" posting. This, I think, is the kind of
thing he is talking about.

John Savard

------------------------------

From: [EMAIL PROTECTED] ()
Subject: Re: Thought question:  why do public ciphers use only simple ops like shift 
and XOR?
Date: 18 Apr 99 01:49:42 GMT

Terry Ritter ([EMAIL PROTECTED]) wrote:
: This is seriously disturbing:  The issue is not who makes a thing, but
: instead what the thing actually is.  Deliberately judging a design in
: the context of who made it is actually anti-scientific, and should be
: widely denounced as the superstition it is.  

That's true *if* judging a cipher that way is used as a substitute for
actual analytical study of the cipher itself by a competent individual.
Where the services of an expert are not available, or there is
insufficient time to fully evaluate all candidate ciphers for an
application, choosing a cipher from a respected source is not
"superstition", and it is the kind of choice people make all the time:
i.e., when shopping for a new computer.

John Savard

------------------------------

From: [EMAIL PROTECTED] (David Wagner)
Subject: Re: New drop in cipher in the spirit of TEA
Date: 17 Apr 1999 19:53:36 -0700

In article <7fau68$mv1$[EMAIL PROTECTED]>,
 <[EMAIL PROTECTED]> wrote:
> > You might want to look at it a little more closely.
> >
> > If I understand the algorithm, I think even a million rounds of
> > it can be broken with a handful of chosen texts.
> > (But I'm not sure; you should check the details.)
> 
> Maybe, but I would have to check myself.  Thanks for the feedback.

A hint: flipping the 11th bit of either register doesn't ever seem
to affect the low 10 bits.
Thus, the low 10 bits of each half of the ciphertext (20 bits in all)
is a function of only 20 bits of the plaintext.
This is very poor avalanche.

------------------------------

From: [EMAIL PROTECTED] ()
Subject: Re: Thought question:  why do public ciphers use only simple ops like shift 
and XOR?
Date: 18 Apr 99 02:05:37 GMT

Terry Ritter ([EMAIL PROTECTED]) wrote:
: As I see it, the real opportunity for
: cryptanalysis is as part of a dynamic and interactive cipher design
: process, as opposed to final certification.  

Two comments are warranted here.

- Since cryptanalysis represents the "hard" part of the work in designing
a cipher, this is why cipher designers should themselves know something
about cryptanalysis;

- And I think you can see why this design process actually _increases_ the
probability of a design which is strong against known attacks, but weak
against a future attack someone might discover.

John Savard

------------------------------

From: [EMAIL PROTECTED] (David Wagner)
Subject: Re: Extreme lossy text compression
Date: 17 Apr 1999 19:24:38 -0700

In article <[EMAIL PROTECTED]>,
D. J. Bernstein <[EMAIL PROTECTED]> wrote:
> Actually, a 128-bit CRC _with a random polynomial_ guarantees an
> extremely low collision probability for any fixed set of inputs.

I'm confused.  Isn't it true that CRC(x) = CRC(0||x), for
any polynomial?  ("||" represents concatenation of bits.)

------------------------------

From: IEEE P1363 <[EMAIL PROTECTED]>
Subject: IEEE P1363 June Meeting Announcement
Date: Sat, 17 Apr 1999 23:55:30 -0400

                  IEEE P1363 Working Group:
     Standard Specifications for Public-Key Cryptography


                       MEETING NOTICE

             Monday, June 7, 1999, 8:30am-5:00pm
            Tuesday, June 8, 1999, 8:30am-5:00pm
           Wednesday, June 9, 1999, 8:30am-5:00pm

                    Security Dynamics AB
                      Stockholm, Sweden

This meeting of the P1363 working group, open to the public,
will receive new contributions to the IEEE P1363a addendum,
make a preliminary selection of encryption and signature
schemes for inclusion in the addendum, review candidate
key agreement and identification schemes, and address some
organizational matters.

The IEEE P1363 document is currently in ballot resolution.
The status of the ballot will be discussed for informational
purposes only at this meeting. Formal discussion is taking
place via the mailing list.

Security Dynamics AB is the meeting's host.


AGENDA

  1. Approval of agenda
  2. Approval of minutes from previous meeting
  3. Officers' reports
  4. Nomination and election procedures for new officers;
     terms of office; membership criteria
  5. Discussion of P1363 ballot (information only)
  6. New P1363a contributions
  7. Preliminary selection of encryption and signature
     schemes for P1363a
  8. Review of key agreement and identification schemes
  9. Other P1363a planning
  10. Work assignments
  11. Meeting schedule

There will be an IEEE meeting fee of US$60 for the three
days.

Information on the working group is available through
http://grouper.ieee.org/groups/1363/. To join the working
group's electronic mailing list, send e-mail with the text
"subscribe stds-p1363" to <[EMAIL PROTECTED]>.


REGISTRATION

Although formal registration is not required for IEEE P1363
meetings, for planning purposes, please contact Emma
Lindberg <[EMAIL PROTECTED]> if you would like
to attend. Emma can also help arrange hotel accommodations
and has reserved a block of rooms at the Sjöfartshotellet
Hotel. As hotel availability in Stockholm is limited, please
make arrangements as early as possible.



------------------------------

From: [EMAIL PROTECTED] (wtshaw)
Subject: Re: Adequacy of FIPS-140
Date: Sat, 17 Apr 1999 23:12:35 -0600

In article <[EMAIL PROTECTED]>, "Douglas A. Gwyn"
<[EMAIL PROTECTED]> wrote:

> wtshaw wrote:

> > Precisely, you need only make it so costly or unreasonable to attempt to
> > dissuade attempts to do it.  That seems an obtainable goal.
> 
> If I understand your response, you have missed an important
> point:  What you say would be true *if* there were no better
> attack than brute-force search.  However, we know that often
> there *is* a much better attack.

Then, don't use such an algorithm if you can help it. 

> Unless we somehow know the
> *best possible* attack, we can't be sure how costly it would
> be.  (Actually I exaggerated slightly to make the point.  We
> don't have to know the optimal attack itself, if we have some
> other way to compute the equivalent cost.)

I would maintain that you do have open choices as to algorithms.  Why
people are so hung up on making favorites out of those that can be solved
by brute forcing one or two small blocks makes no sense to me.  Neither
should be aim for absurdl awkward algorithms either.  There is plenty of
room for more than adequate secuity in between these.
-- 
Too much of a good thing can be much worse than none.

------------------------------

From: [EMAIL PROTECTED] (Terry Ritter)
Subject: Re: Question on confidence derived from cryptanalysis.
Date: Sun, 18 Apr 1999 05:20:40 GMT


On Sun, 18 Apr 1999 00:35:46 GMT, in <[EMAIL PROTECTED]>, in
sci.crypt "Douglas A. Gwyn" <[EMAIL PROTECTED]> wrote:

>Terry Ritter wrote:
>> It is obvious that people are making the conclusion that cryptanalysis
>> is certification, for there has been no effort to construct protocols
>> which deal with the fact that we can have no confidence in the
>> resulting cipher.
>
>There is a difference between "less than total confidence" and
>"no confidence".  In many cases, one can reliably estimate the
>enemy's capabilities and be confident that he is not in as
>good a position to succeed in attacks against your system as
>your own tiger team is; so if your guys can't crack the system,
>it is more likely than not that the enemy can't crack it either.

But you know this can be skating pretty near the edge.  Sometimes it's
hard to know what "we" can do (and, presumably, we *know* our guys),
let alone predict what "they" can do.  But in the case of a
general-use crypto standard, this is a game we cannot play and could
not afford the risk of playing anyway.  

>Depending on the potential cost of being wrong, that might be
>good enough.  If not, then your idea of additional protection
>makes sense.  However, you need to prove that your protocols
>do add significant security; otherwise the new "protocolled"
>system is subject to the same argument you made about the
>original system, namely one doesn't know whether or not the
>enemy can crack it.

I've given the basic argument various times.  The argument for
multiple ciphering is well known.  The argument for using many ciphers
rests on partitioning the data into independently-protected channels
which compartmentalizes risk by reducing single-failure loss.  This
also reduces the motive for Opponents who might otherwise try to
attack a single standard cipher.  The argument for having a continuous
flow of new cipher designs rests on the cost implications to any
Opponent who tries to keep up with new designs.  

Of these three, the last two both depend upon having a substantial
number of ciphers, and the argument is made that these cannot be as
well constructed -- or as thoroughly certified -- as a single
standard.  My response is that we do not know, in general, that even a
"certified" cipher is strong enough.  If we did, we would not need all
this other stuff.  I think it very reasonable to leave it to each user
(or security office) to select the ciphers they want to use, and
modify that list based on the latest ciphers and academic results.  At
least that way everyone is in charge of their own fate.  


>> ...  As far as I could tell there had been no attempt to improve
>> the combiner itself, and there was some feeling that a reversible
>> nonlinear combiner was a contradiction in terms.
>
>I assume you're talking about the open literature, because it's
>not the case inside the fence.  That's one of the frustrating
>things about this business; there is a lot of (slow) reinvention
>of the wheel, due to extreme secrecy about what is known.

Yes, of course, I know only the open literature.  I have no idea what
was developed otherwise.  For example, after I developed Dynamic
Substitution, I realized that one could use a random Latin square as a
combiner.  I would expect that this was long known "inside," but am
unaware of any open literature about it.  (Shannon of course talks
about Latin squares, but does so in the context of entire cipher
transformations, and not stream-cipher combiners.)  


>> The fact that my work is not addressed probably has negative
>> consequences for me.  But it also means that academia has no
>> background for dealing with these structures beyond what I have
>> personally published.  That may be insufficient, but it is all
>> there is.
>
>Largely, academia studies what they already know how to study,
>because the expectation of producing something "publishable"
>is greater that way.  This is really sad, but understandable.
>
>Just so you know, I appreciate your work and especially your
>making useful information available via the Web.  Maybe self-
>publication will help mankind make progress in fields that
>are currently stagnating due to academic inbreeding.

Coming from you, that means a lot.  Thanks.  

---
Terry Ritter   [EMAIL PROTECTED]   http://www.io.com/~ritter/
Crypto Glossary   http://www.io.com/~ritter/GLOSSARY.HTM


------------------------------

From: Boris Kazak <[EMAIL PROTECTED]>
Subject: Re: Extreme lossy text compression
Date: Sat, 17 Apr 1999 22:26:52 -0400
Reply-To: [EMAIL PROTECTED]

Geoffrey Teabo wrote:
 
> That's right.  I really don't care about "attackers" at all.  I'm monitoring
> an independent system that doesn't even know it's being monitored.
> 
> Imagine if my program were collecting news articles over the wire services.
> I just want to be able to use a hash (or CRC) of each incoming plaintext to
> search a historical "list" of past hashes (or CRCs) to determine whether that
> particular IDENTICAL newsarticle was ever received previously.
> 
> As I pointed out in another post, news writers won't compose their news
> stories to try to hack my system!  They're just reporting the news.  They
> don't even know I have a system!!!
> 
> Can you point me toward source code for 128 bit CRC ???
> 
===========================
This should be adequate for your purposes, you can use it 
or throw it away, as you wish...
     I am not sure that you need the technical information,
but included it for completeness. For your application 
I would reduce the ROUNDS constant in the header to 2,
just to gain speed.
     BTW, your greatest concern will be in making the 
probability of "birthday paradox" as little as possible.
For rough estimate, the probability of 2 different messages 
hashing to the same value rises to 0.5 when the number 
of messages rises to 2^(n/2), where "n" is the number 
of bits in the hash. Thus, with a 128-bit hash you must
accumulate about 2^64 messages before you will start 
really worrying about hash collisions. With 10 million
messages a year it will take about 16 trillion years...
and you can always doublecheck the messages, should 
such an unlikely event happen once in a decade.
     The statistical tests indicate a uniform distribution 
of hex digits in the final hash with no noticeable biases
(6 runs by 1 million hashes each).

     This proposed function is based on multiplication 
(mod 2^32+1) with two "twists". First, however, some 
background information.


*************************
     The program takes the filename from the simple dialog 
and writes the hash into a new file with the name of the 
original file and extension "h32".

     Original message is divided into segments of the size
twice that of the final hash, e.g. if the final hash will 
be 160 bit, the segments will be 320 bit each. The size of 
the hash and segments is #defined by the HASHBLOCKSIZE 
constant and can be altered according to need.

    For each block, there are 3 rounds (for those 
paranoid among us, there is a #define, where one can 
change the ROUNDS constant to whatever desired).
*************************

     The function uses 256 different modular multipliers 
derived from one initial number "SEED". This number is 
0x6A09E667, which happens to be the first 8 hex digits of 
SQRT(2), less initial 1. The use of this number should 
dispel any suspicions about a "trap door" built into SEED.
The multipliers themselves are simply the powers of SEED, 
so that Mult[k] = SEED^(k+1), this way SEED^0 = 1 is 
avoided, we don't want any trivial multipliers. Also, this 
number produces a 33,502,080 long cycle of its powers 
until it comes back to 1, so there are no duplicate 
multipliers in the array.

     The multiplier array can be precomputed in advance or 
can be filled at the program start. The latter case saves 
some code (no need for a big data table), but implies a 
time penalty of 255 modular multiplications.

     Now about the "twists". The first twist boils down to 
the plaintext-dependent choice of the multiplier. If a 
certain 4-byte number is going to be hashed, the 
corresponding multiplier is chosen from the table with the 
index I = XOR(all 4 bytes of the number). 

     Second twist regards the progression along the block.
After the multiplication, when the bytes of the product 
are returned to their places and it is time to proceed 
with the subsequent multiplication, the two LS bytes of 
the previous product become the two MS bytes of the new 
number to be multiplied, and two adjacent bytes of 
the plaintext are appended to them in order to make this 
new 32-bit number. When the end of the block is reached,
the index wraps cyclically over the BlockLength.

       Graphically a round can be visualized in the 
following sketch:
          ( the index is circular mod "BlockLength" )
___________________________________________________________
                  1-st multiplication

        XXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        ( XXXX - 32-bit number to multiply, multiplier 
index is computed as X^X^X^X)
___________________________________________________________

                  2-nd multiplication

        ppPPXXxxxxxxxxxxxxxxxxxxxxxxxxxx

        (ppPP - product of the first multiplication,
     PPXX - 32-bit number to multiply, multiplier 
     index is computed as P^P^X^X)
___________________________________________________________

                  3-d multiplication

        ppppPPXXxxxxxxxxxxxxxxxxxxxxxxxx

        ( PPXX - 32-bit number to multiply, multiplier 
     index is computed as P^P^X^X)
...........................................................

                  Last multiplication

        XXppppppppppppppppppppppppppppPP

        ( The index is cyclically wrapped over -
     PPXX - 32-bit number to multiply, multiplier 
     index is computed as P^P^X^X)
___________________________________________________________

        This arrangement allows an ultra-rapid propagation 
of all changes across the entire block - there is complete 
avalanche after the 2-nd round and then after each 
subsequent round.

        It should be also noted that this arrangement 
effectively molds the entire hash into an inseparable 
entity, where the junctions between the adjacent bytes and 
words don't exist any more, they are all blurred by 
overlapping and by cyclical wrapover of the index. This 
strongly discourages any attacks based on different 
behavior of the distinct bytes and words during hashing. 
In this function the entire hash is just a circular 
sequence of bits without beginning or end, without the 
junctions between bytes or words, without any realistic 
possibility to trace the output changes back to the changes 
in any particular word or byte. The cryptanalyst would 
either be forced to attack the hash as a whole (128 or 
even 256 bits), or just give up, which I hope will 
precisely happen.

     After 3 rounds, the new subsequent block is read from 
the message and XOR-ed with the hash obtained in the previous 
cycles. Then the hashing procedure repeats again for 3 
rounds, and so on until the last message block is read. 
If the last message block is shorter than needed, it is 
padded with 0-s. Thereafter one more block is added to the 
hash, containing the full message length as a 64-bit binary 
number padded with 0-s. The final operation XOR-s the two 
halves of the hash buffer, producing the output hash value. 

     Since in each multiplication step the multiplicand is 
replaced with the product, there is no practical way of 
reconstructing the multiplier index (other than computing 
multiplicative inverses for all 256 multipliers and testing 
the product to find out the match for the index used, 
however, the final XOR-ing defeats this option).

     Initially the hash buffer contains either 0's or an 
appropriate IV. No hashing is done on this value, the first 
message block is just XOR-ed into the hash buffer. 

     If the secret key will be used as the IV, the function 
will produce a MAC.

     The source code was compiled under Borland C++ 4.52 
and should compile under any ANSI-compliant C compiler. 
The routines for breaking and making the 32-bit integers 
from 4 bytes should assure identical results on both big-
endian and little-endian platforms (not tested).

     No attempt has been made in order to optimize the 
program in any way. After all, it is supposed to be just 
a working model, not a racing car. One simple possible 
optimization might reverse the direction of scanning 
over the "text" block for little-endian Intel processors.

     Any comments would be appreciated.

/*********************   Start of code     ************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define byte unsigned char
#define word16 unsigned int
#define word32 unsigned long int

#define LO 0x0000FFFFUL
#define HI 0xFFFF0000UL
#define HASHBLOCKSIZE 16
#define ROUNDS  3
#define SEED  0x6A09E667UL  /* Modular Multiplier seed */
                /* First 8 hex digits of SQRT(2), less initial 1 */

/* variables */
word32 mult[256];                     /* multiplier array */
word32 message_length;                /* size of input file */
int end_of_file;
byte inbuffer[2*HASHBLOCKSIZE], outbuffer[HASHBLOCKSIZE];
byte text[2*HASHBLOCKSIZE];      /* the working array */

/*file handling functions*/
char read_char_from_file(FILE *fp);
void read_block_from_file(FILE *fp);
void write_char_to_file(char data,FILE *fp);

/* Functions */
word32 Mul (word32 x, word32 y)            /* Returns (x * y) mod
(2^32+1) */
                            /*  For the purposes of this algorithm 0 =
2^32 */

        /* Modular Multiplication "CORRECT BUT SLOW" (mod 2^32+1)
                If your compiler does not handle the "double long"
                integers (64 bit), you have to split the 32-bit words
                into 16-bit halves, multiply them, then juggle the
                intermediate products until you get the correct result.
        */
{
        word32 t[4]; word16 u[2], v[2];
                if (x == 0) return (1 - y);
                if (y == 0) return (1 - x);

        u[0] = (word16)(x & LO);
        v[0] = (word16)(y & LO);
        u[1] = (word16)((x >> 16) & LO);
        v[1] = (word16)((y >> 16) & LO);

        t[0] = (word32) u[0] *  (word32) v[0] ;
        t[1] = (word32) u[1] *  (word32) v[0] ;
        t[2] = (word32) u[0] *  (word32) v[1] ;
        t[3] = (word32) u[1] *  (word32) v[1] ;
                          /* intermediate 32-bit products */

        t[3] = t[3] + ((t[1] >> 16) & LO)
                                        + ((t[2] >> 16) & LO);
                                        /* no overflow possible here */

        t[1] = (t[1] & LO) + (t[2] & LO)
                                        + ((t[0] >> 16) & LO);
                                        /* collect them all in t[1]. Overflow into the
                                                17-th bit possible here */

        t[0] = (t[0] & LO) + ((t[1] << 16) & HI);
        t[3] = t[3] + ((t[1] >> 16) & LO); /* add eventual overflow */

        return (t[0] - t[3] + (t[3] > t[0]));

} /* Mul */
#define MUL(x,y) (x=Mul(x,y))

void MultSetup (word32 *mul)
{
  int k;
        *mul = SEED;   /* Initialize multiplier array */
        for (k = 1; k < 256; k++)        
          { 
            *(mul+k) = *(mul+k-1); /* Copy next <- previous */
            MUL (*(mul+k),SEED); /* Subsequent power */
          }
} /* MultSetup */

void DissH1( word32 H, byte *D )
/*
          Disassemble the given word32 into 4 bytes.
          We want it to work on all kinds of machines,
          Little-Endian or Big-Endian.
*/
{
  word32 T ;
         T = H ;
         *D++ = (byte)((T & 0xff000000UL) >> 24) ;
         *D++ = (byte)((T & 0x00ff0000UL) >> 16) ;
         *D++ = (byte)((T & 0x0000ff00UL) >>  8) ;
         *D   = (byte) (T & 0x000000ffUL)        ;
} /* DissH1 */

word32 MakeH1( byte *B )
/*
          Assemble a word32 from the four bytes provided.
          We want it to work on all kinds of machines,
          Little-Endian or Big-Endian.
*/
{
  word32 RetVal, temp ;
         temp = *B++ ;
         RetVal = (temp << 24) ;
         temp = *B++ ;
         RetVal += (temp << 16) ;
         temp = *B++ ;
         RetVal += (temp <<  8) ;
         RetVal += *B ;
         return RetVal ;
} /* MakeH1 */

void Scramble (void) /* This subroutine scrambles the "text" block */
                                /*  It uses the global variables */
                                /*  mult[], text[] and inbuffer[] */

{
int i,k,m;
word32 temp1, temp2;

                /* XOR-ing the input into the text array */
  for (m=0; m < 2*HASHBLOCKSIZE; m++) text[m] ^= inbuffer[m];

                /* Now we can start squashing the block */
  for (m=0; m<ROUNDS; m++)
  {
   for (k=0; k<2*HASHBLOCKSIZE; k+= 2)
    {
                                /* Build a 32-bit multiplicand and multiplier index */
                                /* We want this to produce same results on big-endian 
*/
                                /* and little-endian machines alike */
     temp2 = text[k % (2*HASHBLOCKSIZE)] ;     /* Essentially this
procedure */
     i = (int)temp2;                         /* is identical to MakeH2
function */
     temp1 = (temp2 << 24) ;                 /* However, it is
impossible to use */
     temp2 = text[(k+1)%(2*HASHBLOCKSIZE)] ; /* MakeH2 function
directly, because */
     i ^= (int)temp2;                        /* the loop index must be
wrapped */
     temp1 += (temp2 << 16) ;                /* mod 2*HASHBLOCKSIZE, and
also the */
     temp2 = text[(k+2) % (2*HASHBLOCKSIZE)] ; /* multiplier index is
computed, */
     i ^= (int)temp2;                        /* which is not provided in
MakeH2 */
     temp1 += (temp2 <<  8) ;
     temp1 += text[(k+3) % (2*HASHBLOCKSIZE)] ;
     i ^= (int)temp2;

                  /* Get the modular product into "temp1" */
                        MUL(temp1, mult[i]);

                 /* Return the bytes where they belong */
          text[k     % (2*HASHBLOCKSIZE)] = (byte)((temp1 & 0xff000000UL) >>
24) ;
          text[(k+1) % (2*HASHBLOCKSIZE)] = (byte)((temp1 & 0x00ff0000UL) >>
16) ;
          text[(k+2) % (2*HASHBLOCKSIZE)] = (byte)((temp1 & 0x0000ff00UL) >> 
8) ;
          text[(k+3) % (2*HASHBLOCKSIZE)] = (byte) (temp1 & 0x000000ffUL) ;
    }
  }
}    /* Scramble */

char read_char_from_file(FILE *fp)
{
  char temp=0;
    message_length++;
        if ((fread(&temp,sizeof(char),1,fp))!=1)
          {
                  end_of_file=1;
                  message_length--;
          }
    return (temp);
} /* read_char_from_file */

void read_block_from_file(FILE *fp)
{
  int i;
        for (i=0; i<2*HASHBLOCKSIZE; i++)
         {
                 inbuffer[i]=read_char_from_file(fp);
         }
} /* read_block_from_file */


void write_char_to_file(char data,FILE *fp)
{
        if ((fwrite(&data,sizeof(char),1,fp))!=1)
        {
                printf("Fatal Error writing output file!!!\n");
                exit(-1);
        }
} /* write_char_to_file */


void main()
{
        FILE *in,*out;
        char infile[100], outfile[100], *dot;
        int k;

                        /* Opening files */
        printf("\nEnter input filename:");
        gets(infile);

        if ((in=fopen(infile,"r+b"))==NULL)
        {
                printf("\nError opening input file: %s\n",infile);
                exit (-1);
        }

        strcpy(outfile,infile);
        dot=strrchr(outfile,'.'); dot++;
        *dot++='h'; *dot++='3';   /* Changing file extension */
        *dot++='2'; *dot='\0';    /* to .h32   */

        if ((out=fopen(outfile,"w+b"))==NULL)
        {
                printf("\nError opening output file: %s\n",outfile);
                exit(-1);
        }
        printf("\nOutput file is: %s\n",outfile);

                                         /* Setting up the multipliers */
        MultSetup(mult);

                                         /* Clearing the text buffer */
        for (k=0; k<2*HASHBLOCKSIZE; k++)  text[k]=0;

                /* Reading and squashing the input file */
        while(end_of_file != 1)
         {
                read_block_from_file(in);
                Scramble();
         }

                 /* Building up and squashing the final block */
        for (k=0; k<4; k++) inbuffer[k]=0;
        DissH1(message_length, (inbuffer+4));
        for (k=8; k<2*HASHBLOCKSIZE; k++) inbuffer[k]=0;
                        Scramble();

                                         /* Building and writing the final hash */
        for (k=0; k<HASHBLOCKSIZE; k++)
                                outbuffer[k] = text[k]^text[k+HASHBLOCKSIZE];

        for (k=0; k<HASHBLOCKSIZE; k++)
         {
                 write_char_to_file(outbuffer[k],out);
         }

        fclose(in); fclose(out);
}

------------------------------


** FOR YOUR REFERENCE **

The service address, to which questions about the list itself and requests
to be added to or deleted from it should be directed, is:

    Internet: [EMAIL PROTECTED]

You can send mail to the entire list (and sci.crypt) via:

    Internet: [EMAIL PROTECTED]

End of Cryptography-Digest Digest
******************************

Reply via email to