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