1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.digests;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
4a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstromimport org.bouncycastle.util.Memoable;
5a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class MD5Digest
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    extends GeneralDigest
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int    DIGEST_LENGTH = 16;
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int     H1, H2, H3, H4;         // IV's
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int[]   X = new int[16];
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int     xOff;
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Standard constructor
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public MD5Digest()
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        reset();
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Copy constructor.  This will copy the state of the provided
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * message digest.
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public MD5Digest(MD5Digest t)
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super(t);
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
35a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        copyIn(t);
36a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
37a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
38a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    private void copyIn(MD5Digest t)
39a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
40a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        super.copyIn(t);
41a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H1 = t.H1;
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H2 = t.H2;
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H3 = t.H3;
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H4 = t.H4;
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        System.arraycopy(t.X, 0, X, 0, t.X.length);
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        xOff = t.xOff;
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String getAlgorithmName()
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return "MD5";
54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public int getDigestSize()
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return DIGEST_LENGTH;
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void processWord(
62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  in,
63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     inOff)
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (xOff == 16)
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            processBlock();
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void processLength(
75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        long    bitLength)
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (xOff > 14)
78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            processBlock();
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        X[14] = (int)(bitLength & 0xffffffff);
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        X[15] = (int)(bitLength >>> 32);
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private void unpackWord(
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     word,
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  out,
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     outOff)
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out[outOff]     = (byte)word;
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out[outOff + 1] = (byte)(word >>> 8);
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out[outOff + 2] = (byte)(word >>> 16);
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out[outOff + 3] = (byte)(word >>> 24);
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public int doFinal(
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  out,
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     outOff)
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        finish();
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        unpackWord(H1, out, outOff);
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        unpackWord(H2, out, outOff + 4);
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        unpackWord(H3, out, outOff + 8);
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        unpackWord(H4, out, outOff + 12);
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        reset();
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return DIGEST_LENGTH;
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * reset the chaining variables to the IV values.
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void reset()
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super.reset();
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H1 = 0x67452301;
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H2 = 0xefcdab89;
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H3 = 0x98badcfe;
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H4 = 0x10325476;
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        xOff = 0;
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != X.length; i++)
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            X[i] = 0;
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // round 1 left rotates
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S11 = 7;
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S12 = 12;
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S13 = 17;
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S14 = 22;
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // round 2 left rotates
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S21 = 5;
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S22 = 9;
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S23 = 14;
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S24 = 20;
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // round 3 left rotates
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S31 = 4;
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S32 = 11;
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S33 = 16;
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S34 = 23;
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    // round 4 left rotates
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    //
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S41 = 6;
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S42 = 10;
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S43 = 15;
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private static final int S44 = 21;
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /*
166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * rotate int x left n bits.
167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int rotateLeft(
169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int x,
170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int n)
171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (x << n) | (x >>> (32 - n));
173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /*
176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * F, G, H and I are the basic MD5 functions.
177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int F(
179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int u,
180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int v,
181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int w)
182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (u & v) | (~u & w);
184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int G(
187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int u,
188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int v,
189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int w)
190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return (u & w) | (v & ~w);
192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int H(
195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int u,
196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int v,
197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int w)
198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return u ^ v ^ w;
200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private int K(
203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int u,
204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int v,
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int w)
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return v ^ (u | ~w);
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void processBlock()
211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int a = H1;
213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int b = H2;
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int c = H3;
215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int d = H4;
216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // Round 1 - F cycle, 16 times.
219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + F(b, c, d) + X[ 0] + 0xd76aa478, S11) + b;
221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + F(a, b, c) + X[ 1] + 0xe8c7b756, S12) + a;
222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + F(d, a, b) + X[ 2] + 0x242070db, S13) + d;
223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + F(c, d, a) + X[ 3] + 0xc1bdceee, S14) + c;
224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + F(b, c, d) + X[ 4] + 0xf57c0faf, S11) + b;
225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + F(a, b, c) + X[ 5] + 0x4787c62a, S12) + a;
226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + F(d, a, b) + X[ 6] + 0xa8304613, S13) + d;
227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + F(c, d, a) + X[ 7] + 0xfd469501, S14) + c;
228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + F(b, c, d) + X[ 8] + 0x698098d8, S11) + b;
229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + F(a, b, c) + X[ 9] + 0x8b44f7af, S12) + a;
230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // Round 2 - G cycle, 16 times.
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + G(b, c, d) + X[ 1] + 0xf61e2562, S21) + b;
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + G(a, b, c) + X[ 6] + 0xc040b340, S22) + a;
242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + G(c, d, a) + X[ 0] + 0xe9b6c7aa, S24) + c;
244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + G(b, c, d) + X[ 5] + 0xd62f105d, S21) + b;
245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + G(c, d, a) + X[ 4] + 0xe7d3fbc8, S24) + c;
248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + G(b, c, d) + X[ 9] + 0x21e1cde6, S21) + b;
249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + G(d, a, b) + X[ 3] + 0xf4d50d87, S23) + d;
251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + G(c, d, a) + X[ 8] + 0x455a14ed, S24) + c;
252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + G(a, b, c) + X[ 2] + 0xfcefa3f8, S22) + a;
254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + G(d, a, b) + X[ 7] + 0x676f02d9, S23) + d;
255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
258b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // Round 3 - H cycle, 16 times.
259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + H(b, c, d) + X[ 5] + 0xfffa3942, S31) + b;
261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x8771f681, S32) + a;
262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + H(b, c, d) + X[ 1] + 0xa4beea44, S31) + b;
265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + H(a, b, c) + X[ 4] + 0x4bdecfa9, S32) + a;
266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + H(d, a, b) + X[ 7] + 0xf6bb4b60, S33) + d;
267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + H(a, b, c) + X[ 0] + 0xeaa127fa, S32) + a;
270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + H(d, a, b) + X[ 3] + 0xd4ef3085, S33) + d;
271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + H(c, d, a) + X[ 6] + 0x04881d05, S34) + c;
272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + H(b, c, d) + X[ 9] + 0xd9d4d039, S31) + b;
273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + H(c, d, a) + X[ 2] + 0xc4ac5665, S34) + c;
276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // Round 4 - K cycle, 16 times.
279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + K(b, c, d) + X[ 0] + 0xf4292244, S41) + b;
281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + K(a, b, c) + X[ 7] + 0x432aff97, S42) + a;
282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + K(c, d, a) + X[ 5] + 0xfc93a039, S44) + c;
284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + K(a, b, c) + X[ 3] + 0x8f0ccc92, S42) + a;
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + K(c, d, a) + X[ 1] + 0x85845dd1, S44) + c;
288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + K(b, c, d) + X[ 8] + 0x6fa87e4f, S41) + b;
289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + K(d, a, b) + X[ 6] + 0xa3014314, S43) + d;
291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        a = rotateLeft(a + K(b, c, d) + X[ 4] + 0xf7537e82, S41) + b;
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        c = rotateLeft(c + K(d, a, b) + X[ 2] + 0x2ad7d2bb, S43) + d;
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        b = rotateLeft(b + K(c, d, a) + X[ 9] + 0xeb86d391, S44) + c;
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H1 += a;
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H2 += b;
299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H3 += c;
300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        H4 += d;
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // reset the offset and clean out the word buffer.
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        xOff = 0;
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != X.length; i++)
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            X[i] = 0;
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
311a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
312a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public Memoable copy()
313a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
314a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        return new MD5Digest(this);
315a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
316a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
317a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    public void reset(Memoable other)
318a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    {
319a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        MD5Digest d = (MD5Digest)other;
320a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom
321a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom        copyIn(d);
322a198e1ecc615e26a167d0f2dca9fa7e5fc62de10Brian Carlstrom    }
323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
324