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