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