Home | History | Annotate | Download | only in digests
      1 package org.bouncycastle.crypto.digests;
      2 
      3 
      4 import org.bouncycastle.util.Memoable;
      5 import org.bouncycastle.util.Pack;
      6 
      7 
      8 /**
      9  * FIPS 180-2 implementation of SHA-256.
     10  *
     11  * <pre>
     12  *         block  word  digest
     13  * SHA-1   512    32    160
     14  * SHA-256 512    32    256
     15  * SHA-384 1024   64    384
     16  * SHA-512 1024   64    512
     17  * </pre>
     18  */
     19 public class SHA256Digest
     20     extends GeneralDigest
     21     implements EncodableDigest
     22 {
     23     private static final int    DIGEST_LENGTH = 32;
     24 
     25     private int     H1, H2, H3, H4, H5, H6, H7, H8;
     26 
     27     private int[]   X = new int[64];
     28     private int     xOff;
     29 
     30     /**
     31      * Standard constructor
     32      */
     33     public SHA256Digest()
     34     {
     35         reset();
     36     }
     37 
     38     /**
     39      * Copy constructor.  This will copy the state of the provided
     40      * message digest.
     41      */
     42     public SHA256Digest(SHA256Digest t)
     43     {
     44         super(t);
     45 
     46         copyIn(t);
     47     }
     48 
     49     private void copyIn(SHA256Digest t)
     50     {
     51         super.copyIn(t);
     52 
     53         H1 = t.H1;
     54         H2 = t.H2;
     55         H3 = t.H3;
     56         H4 = t.H4;
     57         H5 = t.H5;
     58         H6 = t.H6;
     59         H7 = t.H7;
     60         H8 = t.H8;
     61 
     62         System.arraycopy(t.X, 0, X, 0, t.X.length);
     63         xOff = t.xOff;
     64     }
     65 
     66     /**
     67      * State constructor - create a digest initialised with the state of a previous one.
     68      *
     69      * @param encodedState the encoded state from the originating digest.
     70      */
     71     public SHA256Digest(byte[] encodedState)
     72     {
     73         super(encodedState);
     74 
     75         H1 = Pack.bigEndianToInt(encodedState, 16);
     76         H2 = Pack.bigEndianToInt(encodedState, 20);
     77         H3 = Pack.bigEndianToInt(encodedState, 24);
     78         H4 = Pack.bigEndianToInt(encodedState, 28);
     79         H5 = Pack.bigEndianToInt(encodedState, 32);
     80         H6 = Pack.bigEndianToInt(encodedState, 36);
     81         H7 = Pack.bigEndianToInt(encodedState, 40);
     82         H8 = Pack.bigEndianToInt(encodedState, 44);
     83 
     84         xOff = Pack.bigEndianToInt(encodedState, 48);
     85         for (int i = 0; i != xOff; i++)
     86         {
     87             X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
     88         }
     89     }
     90 
     91 
     92     public String getAlgorithmName()
     93     {
     94         return "SHA-256";
     95     }
     96 
     97     public int getDigestSize()
     98     {
     99         return DIGEST_LENGTH;
    100     }
    101 
    102     protected void processWord(
    103         byte[]  in,
    104         int     inOff)
    105     {
    106         // Note: Inlined for performance
    107 //        X[xOff] = Pack.bigEndianToInt(in, inOff);
    108         int n = in[inOff] << 24;
    109         n |= (in[++inOff] & 0xff) << 16;
    110         n |= (in[++inOff] & 0xff) << 8;
    111         n |= (in[++inOff] & 0xff);
    112         X[xOff] = n;
    113 
    114         if (++xOff == 16)
    115         {
    116             processBlock();
    117         }
    118     }
    119 
    120     protected void processLength(
    121         long    bitLength)
    122     {
    123         if (xOff > 14)
    124         {
    125             processBlock();
    126         }
    127 
    128         X[14] = (int)(bitLength >>> 32);
    129         X[15] = (int)(bitLength & 0xffffffff);
    130     }
    131 
    132     public int doFinal(
    133         byte[]  out,
    134         int     outOff)
    135     {
    136         finish();
    137 
    138         Pack.intToBigEndian(H1, out, outOff);
    139         Pack.intToBigEndian(H2, out, outOff + 4);
    140         Pack.intToBigEndian(H3, out, outOff + 8);
    141         Pack.intToBigEndian(H4, out, outOff + 12);
    142         Pack.intToBigEndian(H5, out, outOff + 16);
    143         Pack.intToBigEndian(H6, out, outOff + 20);
    144         Pack.intToBigEndian(H7, out, outOff + 24);
    145         Pack.intToBigEndian(H8, out, outOff + 28);
    146 
    147         reset();
    148 
    149         return DIGEST_LENGTH;
    150     }
    151 
    152     /**
    153      * reset the chaining variables
    154      */
    155     public void reset()
    156     {
    157         super.reset();
    158 
    159         /* SHA-256 initial hash value
    160          * The first 32 bits of the fractional parts of the square roots
    161          * of the first eight prime numbers
    162          */
    163 
    164         H1 = 0x6a09e667;
    165         H2 = 0xbb67ae85;
    166         H3 = 0x3c6ef372;
    167         H4 = 0xa54ff53a;
    168         H5 = 0x510e527f;
    169         H6 = 0x9b05688c;
    170         H7 = 0x1f83d9ab;
    171         H8 = 0x5be0cd19;
    172 
    173         xOff = 0;
    174         for (int i = 0; i != X.length; i++)
    175         {
    176             X[i] = 0;
    177         }
    178     }
    179 
    180     protected void processBlock()
    181     {
    182         //
    183         // expand 16 word block into 64 word blocks.
    184         //
    185         for (int t = 16; t <= 63; t++)
    186         {
    187             X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
    188         }
    189 
    190         //
    191         // set up working variables.
    192         //
    193         int     a = H1;
    194         int     b = H2;
    195         int     c = H3;
    196         int     d = H4;
    197         int     e = H5;
    198         int     f = H6;
    199         int     g = H7;
    200         int     h = H8;
    201 
    202         int t = 0;
    203         for(int i = 0; i < 8; i ++)
    204         {
    205             // t = 8 * i
    206             h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
    207             d += h;
    208             h += Sum0(a) + Maj(a, b, c);
    209             ++t;
    210 
    211             // t = 8 * i + 1
    212             g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
    213             c += g;
    214             g += Sum0(h) + Maj(h, a, b);
    215             ++t;
    216 
    217             // t = 8 * i + 2
    218             f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
    219             b += f;
    220             f += Sum0(g) + Maj(g, h, a);
    221             ++t;
    222 
    223             // t = 8 * i + 3
    224             e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
    225             a += e;
    226             e += Sum0(f) + Maj(f, g, h);
    227             ++t;
    228 
    229             // t = 8 * i + 4
    230             d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
    231             h += d;
    232             d += Sum0(e) + Maj(e, f, g);
    233             ++t;
    234 
    235             // t = 8 * i + 5
    236             c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
    237             g += c;
    238             c += Sum0(d) + Maj(d, e, f);
    239             ++t;
    240 
    241             // t = 8 * i + 6
    242             b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
    243             f += b;
    244             b += Sum0(c) + Maj(c, d, e);
    245             ++t;
    246 
    247             // t = 8 * i + 7
    248             a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
    249             e += a;
    250             a += Sum0(b) + Maj(b, c, d);
    251             ++t;
    252         }
    253 
    254         H1 += a;
    255         H2 += b;
    256         H3 += c;
    257         H4 += d;
    258         H5 += e;
    259         H6 += f;
    260         H7 += g;
    261         H8 += h;
    262 
    263         //
    264         // reset the offset and clean out the word buffer.
    265         //
    266         xOff = 0;
    267         for (int i = 0; i < 16; i++)
    268         {
    269             X[i] = 0;
    270         }
    271     }
    272 
    273     /* SHA-256 functions */
    274     private int Ch(
    275         int    x,
    276         int    y,
    277         int    z)
    278     {
    279         return (x & y) ^ ((~x) & z);
    280     }
    281 
    282     private int Maj(
    283         int    x,
    284         int    y,
    285         int    z)
    286     {
    287         return (x & y) ^ (x & z) ^ (y & z);
    288     }
    289 
    290     private int Sum0(
    291         int    x)
    292     {
    293         return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
    294     }
    295 
    296     private int Sum1(
    297         int    x)
    298     {
    299         return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
    300     }
    301 
    302     private int Theta0(
    303         int    x)
    304     {
    305         return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
    306     }
    307 
    308     private int Theta1(
    309         int    x)
    310     {
    311         return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
    312     }
    313 
    314     /* SHA-256 Constants
    315      * (represent the first 32 bits of the fractional parts of the
    316      * cube roots of the first sixty-four prime numbers)
    317      */
    318     static final int K[] = {
    319         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    320         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    321         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    322         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    323         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    324         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    325         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    326         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
    327     };
    328 
    329     public Memoable copy()
    330     {
    331         return new SHA256Digest(this);
    332     }
    333 
    334     public void reset(Memoable other)
    335     {
    336         SHA256Digest d = (SHA256Digest)other;
    337 
    338         copyIn(d);
    339     }
    340 
    341     public byte[] getEncodedState()
    342     {
    343         byte[] state = new byte[52 + xOff * 4];
    344 
    345         super.populateState(state);
    346 
    347         Pack.intToBigEndian(H1, state, 16);
    348         Pack.intToBigEndian(H2, state, 20);
    349         Pack.intToBigEndian(H3, state, 24);
    350         Pack.intToBigEndian(H4, state, 28);
    351         Pack.intToBigEndian(H5, state, 32);
    352         Pack.intToBigEndian(H6, state, 36);
    353         Pack.intToBigEndian(H7, state, 40);
    354         Pack.intToBigEndian(H8, state, 44);
    355         Pack.intToBigEndian(xOff, state, 48);
    356 
    357         for (int i = 0; i != xOff; i++)
    358         {
    359             Pack.intToBigEndian(X[i], state, 52 + (i * 4));
    360         }
    361 
    362         return state;
    363     }
    364 }
    365 
    366