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