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