1    package org.bouncycastle.crypto.digests;
2    
3    import org.bouncycastle.crypto.Digest;
4    
5    /**
6     * base implementation of MD4 family style digest as outlined in
7     * "Handbook of Applied Cryptography", pages 344 - 347.
8     */
9    public abstract class GeneralDigest
10       implements Digest
11   {
12       private byte[]  xBuf;
13       private int     xBufOff;
14   
15       private long    byteCount;
16   
17           /**
18            * Standard constructor
19            */
20           protected GeneralDigest()
21           {
22                   xBuf = new byte[4];
23                   xBufOff = 0;
24           }
25   
26           /**
27            * Copy constructor.  We are using copy constructors in place
28            * of the Object.clone() interface as this interface is not
29            * supported by J2ME.
30            */
31           protected GeneralDigest(GeneralDigest t)
32           {
33           xBuf = new byte[t.xBuf.length];
34                   System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
35   
36                   xBufOff = t.xBufOff;
37                   byteCount = t.byteCount;
38           }
39   
40       public void update(
41           byte in)
42       {
43           xBuf[xBufOff++] = in;
44   
45           if (xBufOff == xBuf.length)
46           {
47               processWord(xBuf, 0);
48               xBufOff = 0;
49           }
50   
51           byteCount++;
52       }
53   
54       public void update(
55           byte[]  in,
56           int     inOff,
57           int     len)
58       {
59           //
60           // fill the current word
61           //
62           while ((xBufOff != 0) && (len > 0))
63           {
64               update(in[inOff]);
65   
66               inOff++;
67               len--;
68           }
69   
70           //
71           // process whole words.
72           //
73           while (len > xBuf.length)
74           {
75               processWord(in, inOff);
76   
77               inOff += xBuf.length;
78               len -= xBuf.length;
79               byteCount += xBuf.length;
80           }
81   
82           //
83           // load in the remainder.
84           //
85           while (len > 0)
86           {
87               update(in[inOff]);
88   
89               inOff++;
90               len--;
91           }
92       }
93   
94       public void finish()
95       {
96           long    bitLength = (byteCount << 3);
97   
98           //
99           // add the pad bytes.
100          //
101          update((byte)128);
102  
103          while (xBufOff != 0)
104          {
105              update((byte)0);
106          }
107  
108          processLength(bitLength);
109  
110          processBlock();
111      }
112  
113      public void reset()
114      {
115          byteCount = 0;
116  
117          xBufOff = 0;
118                  for ( int i = 0; i < xBuf.length; i++ ) {
119                          xBuf[i] = 0;
120                  }
121      }
122  
123      protected abstract void processWord(byte[] in, int inOff);
124  
125      protected abstract void processLength(long bitLength);
126  
127      protected abstract void processBlock();
128  }
129