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 class for SHA-384 and SHA-512.
      9  */
     10 public abstract class LongDigest
     11     implements ExtendedDigest, Memoable, EncodableDigest
     12 {
     13     private static final int BYTE_LENGTH = 128;
     14 
     15     private byte[] xBuf = new byte[8];
     16     private int     xBufOff;
     17 
     18     private long    byteCount1;
     19     private long    byteCount2;
     20 
     21     protected long    H1, H2, H3, H4, H5, H6, H7, H8;
     22 
     23     private long[]  W = new long[80];
     24     private int     wOff;
     25 
     26     /**
     27      * Constructor for variable length word
     28      */
     29     protected LongDigest()
     30     {
     31         xBufOff = 0;
     32 
     33         reset();
     34     }
     35 
     36     /**
     37      * Copy constructor.  We are using copy constructors in place
     38      * of the Object.clone() interface as this interface is not
     39      * supported by J2ME.
     40      */
     41     protected LongDigest(LongDigest t)
     42     {
     43         copyIn(t);
     44     }
     45 
     46     protected void copyIn(LongDigest t)
     47     {
     48         System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
     49 
     50         xBufOff = t.xBufOff;
     51         byteCount1 = t.byteCount1;
     52         byteCount2 = t.byteCount2;
     53 
     54         H1 = t.H1;
     55         H2 = t.H2;
     56         H3 = t.H3;
     57         H4 = t.H4;
     58         H5 = t.H5;
     59         H6 = t.H6;
     60         H7 = t.H7;
     61         H8 = t.H8;
     62 
     63         System.arraycopy(t.W, 0, W, 0, t.W.length);
     64         wOff = t.wOff;
     65     }
     66 
     67     protected void populateState(byte[] state)
     68     {
     69         System.arraycopy(xBuf, 0, state, 0, xBufOff);
     70         Pack.intToBigEndian(xBufOff, state, 8);
     71         Pack.longToBigEndian(byteCount1, state, 12);
     72         Pack.longToBigEndian(byteCount2, state, 20);
     73         Pack.longToBigEndian(H1, state, 28);
     74         Pack.longToBigEndian(H2, state, 36);
     75         Pack.longToBigEndian(H3, state, 44);
     76         Pack.longToBigEndian(H4, state, 52);
     77         Pack.longToBigEndian(H5, state, 60);
     78         Pack.longToBigEndian(H6, state, 68);
     79         Pack.longToBigEndian(H7, state, 76);
     80         Pack.longToBigEndian(H8, state, 84);
     81 
     82         Pack.intToBigEndian(wOff, state, 92);
     83         for (int i = 0; i < wOff; i++)
     84         {
     85             Pack.longToBigEndian(W[i], state, 96 + (i * 8));
     86         }
     87     }
     88 
     89     protected void restoreState(byte[] encodedState)
     90     {
     91         xBufOff = Pack.bigEndianToInt(encodedState, 8);
     92         System.arraycopy(encodedState, 0, xBuf, 0, xBufOff);
     93         byteCount1 = Pack.bigEndianToLong(encodedState, 12);
     94         byteCount2 = Pack.bigEndianToLong(encodedState, 20);
     95 
     96         H1 = Pack.bigEndianToLong(encodedState, 28);
     97         H2 = Pack.bigEndianToLong(encodedState, 36);
     98         H3 = Pack.bigEndianToLong(encodedState, 44);
     99         H4 = Pack.bigEndianToLong(encodedState, 52);
    100         H5 = Pack.bigEndianToLong(encodedState, 60);
    101         H6 = Pack.bigEndianToLong(encodedState, 68);
    102         H7 = Pack.bigEndianToLong(encodedState, 76);
    103         H8 = Pack.bigEndianToLong(encodedState, 84);
    104 
    105         wOff = Pack.bigEndianToInt(encodedState, 92);
    106         for (int i = 0; i < wOff; i++)
    107         {
    108             W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8));
    109         }
    110     }
    111 
    112     protected int getEncodedStateSize()
    113     {
    114         return 96 + (wOff * 8);
    115     }
    116 
    117     public void update(
    118         byte in)
    119     {
    120         xBuf[xBufOff++] = in;
    121 
    122         if (xBufOff == xBuf.length)
    123         {
    124             processWord(xBuf, 0);
    125             xBufOff = 0;
    126         }
    127 
    128         byteCount1++;
    129     }
    130 
    131     public void update(
    132         byte[]  in,
    133         int     inOff,
    134         int     len)
    135     {
    136         //
    137         // fill the current word
    138         //
    139         while ((xBufOff != 0) && (len > 0))
    140         {
    141             update(in[inOff]);
    142 
    143             inOff++;
    144             len--;
    145         }
    146 
    147         //
    148         // process whole words.
    149         //
    150         while (len > xBuf.length)
    151         {
    152             processWord(in, inOff);
    153 
    154             inOff += xBuf.length;
    155             len -= xBuf.length;
    156             byteCount1 += xBuf.length;
    157         }
    158 
    159         //
    160         // load in the remainder.
    161         //
    162         while (len > 0)
    163         {
    164             update(in[inOff]);
    165 
    166             inOff++;
    167             len--;
    168         }
    169     }
    170 
    171     public void finish()
    172     {
    173         adjustByteCounts();
    174 
    175         long    lowBitLength = byteCount1 << 3;
    176         long    hiBitLength = byteCount2;
    177 
    178         //
    179         // add the pad bytes.
    180         //
    181         update((byte)128);
    182 
    183         while (xBufOff != 0)
    184         {
    185             update((byte)0);
    186         }
    187 
    188         processLength(lowBitLength, hiBitLength);
    189 
    190         processBlock();
    191     }
    192 
    193     public void reset()
    194     {
    195         byteCount1 = 0;
    196         byteCount2 = 0;
    197 
    198         xBufOff = 0;
    199         for (int i = 0; i < xBuf.length; i++)
    200         {
    201             xBuf[i] = 0;
    202         }
    203 
    204         wOff = 0;
    205         for (int i = 0; i != W.length; i++)
    206         {
    207             W[i] = 0;
    208         }
    209     }
    210 
    211     public int getByteLength()
    212     {
    213         return BYTE_LENGTH;
    214     }
    215 
    216     protected void processWord(
    217         byte[]  in,
    218         int     inOff)
    219     {
    220         W[wOff] = Pack.bigEndianToLong(in, inOff);
    221 
    222         if (++wOff == 16)
    223         {
    224             processBlock();
    225         }
    226     }
    227 
    228     /**
    229      * adjust the byte counts so that byteCount2 represents the
    230      * upper long (less 3 bits) word of the byte count.
    231      */
    232     private void adjustByteCounts()
    233     {
    234         if (byteCount1 > 0x1fffffffffffffffL)
    235         {
    236             byteCount2 += (byteCount1 >>> 61);
    237             byteCount1 &= 0x1fffffffffffffffL;
    238         }
    239     }
    240 
    241     protected void processLength(
    242         long    lowW,
    243         long    hiW)
    244     {
    245         if (wOff > 14)
    246         {
    247             processBlock();
    248         }
    249 
    250         W[14] = hiW;
    251         W[15] = lowW;
    252     }
    253 
    254     protected void processBlock()
    255     {
    256         adjustByteCounts();
    257 
    258         //
    259         // expand 16 word block into 80 word blocks.
    260         //
    261         for (int t = 16; t <= 79; t++)
    262         {
    263             W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
    264         }
    265 
    266         //
    267         // set up working variables.
    268         //
    269         long     a = H1;
    270         long     b = H2;
    271         long     c = H3;
    272         long     d = H4;
    273         long     e = H5;
    274         long     f = H6;
    275         long     g = H7;
    276         long     h = H8;
    277 
    278         int t = 0;
    279         for(int i = 0; i < 10; i ++)
    280         {
    281           // t = 8 * i
    282           h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
    283           d += h;
    284           h += Sum0(a) + Maj(a, b, c);
    285 
    286           // t = 8 * i + 1
    287           g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
    288           c += g;
    289           g += Sum0(h) + Maj(h, a, b);
    290 
    291           // t = 8 * i + 2
    292           f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
    293           b += f;
    294           f += Sum0(g) + Maj(g, h, a);
    295 
    296           // t = 8 * i + 3
    297           e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
    298           a += e;
    299           e += Sum0(f) + Maj(f, g, h);
    300 
    301           // t = 8 * i + 4
    302           d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
    303           h += d;
    304           d += Sum0(e) + Maj(e, f, g);
    305 
    306           // t = 8 * i + 5
    307           c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
    308           g += c;
    309           c += Sum0(d) + Maj(d, e, f);
    310 
    311           // t = 8 * i + 6
    312           b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
    313           f += b;
    314           b += Sum0(c) + Maj(c, d, e);
    315 
    316           // t = 8 * i + 7
    317           a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
    318           e += a;
    319           a += Sum0(b) + Maj(b, c, d);
    320         }
    321 
    322         H1 += a;
    323         H2 += b;
    324         H3 += c;
    325         H4 += d;
    326         H5 += e;
    327         H6 += f;
    328         H7 += g;
    329         H8 += h;
    330 
    331         //
    332         // reset the offset and clean out the word buffer.
    333         //
    334         wOff = 0;
    335         for (int i = 0; i < 16; i++)
    336         {
    337             W[i] = 0;
    338         }
    339     }
    340 
    341     /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
    342     private long Ch(
    343         long    x,
    344         long    y,
    345         long    z)
    346     {
    347         return ((x & y) ^ ((~x) & z));
    348     }
    349 
    350     private long Maj(
    351         long    x,
    352         long    y,
    353         long    z)
    354     {
    355         return ((x & y) ^ (x & z) ^ (y & z));
    356     }
    357 
    358     private long Sum0(
    359         long    x)
    360     {
    361         return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
    362     }
    363 
    364     private long Sum1(
    365         long    x)
    366     {
    367         return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
    368     }
    369 
    370     private long Sigma0(
    371         long    x)
    372     {
    373         return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7);
    374     }
    375 
    376     private long Sigma1(
    377         long    x)
    378     {
    379         return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6);
    380     }
    381 
    382     /* SHA-384 and SHA-512 Constants
    383      * (represent the first 64 bits of the fractional parts of the
    384      * cube roots of the first sixty-four prime numbers)
    385      */
    386     static final long K[] = {
    387 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
    388 0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
    389 0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
    390 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
    391 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
    392 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
    393 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
    394 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
    395 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
    396 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
    397 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
    398 0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
    399 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
    400 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
    401 0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
    402 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
    403 0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
    404 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
    405 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
    406 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
    407     };
    408 
    409 }
    410