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