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