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