Home | History | Annotate | Download | only in digests
      1 package org.bouncycastle.crypto.digests;
      2 
      3 /**
      4  * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
      5  *
      6  * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
      7  * is the "endienness" of the word processing!
      8  */
      9 public class SHA1Digest
     10     extends GeneralDigest
     11 {
     12     private static final int    DIGEST_LENGTH = 20;
     13 
     14     private int     H1, H2, H3, H4, H5;
     15 
     16     private int[]   X = new int[80];
     17     private int     xOff;
     18 
     19     /**
     20      * Standard constructor
     21      */
     22     public SHA1Digest()
     23     {
     24         reset();
     25     }
     26 
     27     /**
     28      * Copy constructor.  This will copy the state of the provided
     29      * message digest.
     30      */
     31     public SHA1Digest(SHA1Digest t)
     32     {
     33         super(t);
     34 
     35         H1 = t.H1;
     36         H2 = t.H2;
     37         H3 = t.H3;
     38         H4 = t.H4;
     39         H5 = t.H5;
     40 
     41         System.arraycopy(t.X, 0, X, 0, t.X.length);
     42         xOff = t.xOff;
     43     }
     44 
     45     public String getAlgorithmName()
     46     {
     47         return "SHA-1";
     48     }
     49 
     50     public int getDigestSize()
     51     {
     52         return DIGEST_LENGTH;
     53     }
     54 
     55     protected void processWord(
     56         byte[]  in,
     57         int     inOff)
     58     {
     59         X[xOff++] = (in[inOff] & 0xff) << 24 | (in[inOff + 1] & 0xff) << 16
     60                     | (in[inOff + 2] & 0xff) << 8 | in[inOff + 3] & 0xff;
     61 
     62         if (xOff == 16)
     63         {
     64             processBlock();
     65         }
     66     }
     67 
     68     private void unpackWord(
     69         int     word,
     70         byte[]  out,
     71         int     outOff)
     72     {
     73         out[outOff++] = (byte)(word >>> 24);
     74         out[outOff++] = (byte)(word >>> 16);
     75         out[outOff++] = (byte)(word >>> 8);
     76         out[outOff++] = (byte)word;
     77     }
     78 
     79     protected void processLength(
     80         long    bitLength)
     81     {
     82         if (xOff > 14)
     83         {
     84             processBlock();
     85         }
     86 
     87         X[14] = (int)(bitLength >>> 32);
     88         X[15] = (int)(bitLength & 0xffffffff);
     89     }
     90 
     91     public int doFinal(
     92         byte[]  out,
     93         int     outOff)
     94     {
     95         finish();
     96 
     97         unpackWord(H1, out, outOff);
     98         unpackWord(H2, out, outOff + 4);
     99         unpackWord(H3, out, outOff + 8);
    100         unpackWord(H4, out, outOff + 12);
    101         unpackWord(H5, out, outOff + 16);
    102 
    103         reset();
    104 
    105         return DIGEST_LENGTH;
    106     }
    107 
    108     /**
    109      * reset the chaining variables
    110      */
    111     public void reset()
    112     {
    113         super.reset();
    114 
    115         H1 = 0x67452301;
    116         H2 = 0xefcdab89;
    117         H3 = 0x98badcfe;
    118         H4 = 0x10325476;
    119         H5 = 0xc3d2e1f0;
    120 
    121         xOff = 0;
    122         for (int i = 0; i != X.length; i++)
    123         {
    124             X[i] = 0;
    125         }
    126     }
    127 
    128     //
    129     // Additive constants
    130     //
    131     private static final int    Y1 = 0x5a827999;
    132     private static final int    Y2 = 0x6ed9eba1;
    133     private static final int    Y3 = 0x8f1bbcdc;
    134     private static final int    Y4 = 0xca62c1d6;
    135 
    136     private int f(
    137         int    u,
    138         int    v,
    139         int    w)
    140     {
    141         return ((u & v) | ((~u) & w));
    142     }
    143 
    144     private int h(
    145         int    u,
    146         int    v,
    147         int    w)
    148     {
    149         return (u ^ v ^ w);
    150     }
    151 
    152     private int g(
    153         int    u,
    154         int    v,
    155         int    w)
    156     {
    157         return ((u & v) | (u & w) | (v & w));
    158     }
    159 
    160     protected void processBlock()
    161     {
    162         //
    163         // expand 16 word block into 80 word block.
    164         //
    165         for (int i = 16; i < 80; i++)
    166         {
    167             int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
    168             X[i] = t << 1 | t >>> 31;
    169         }
    170 
    171         //
    172         // set up working variables.
    173         //
    174         int     A = H1;
    175         int     B = H2;
    176         int     C = H3;
    177         int     D = H4;
    178         int     E = H5;
    179 
    180         //
    181         // round 1
    182         //
    183         int idx = 0;
    184 
    185         for (int j = 0; j < 4; j++)
    186         {
    187             // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
    188             // B = rotateLeft(B, 30)
    189             E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
    190             B = B << 30 | B >>> 2;
    191 
    192             D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
    193             A = A << 30 | A >>> 2;
    194 
    195             C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
    196             E = E << 30 | E >>> 2;
    197 
    198             B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
    199             D = D << 30 | D >>> 2;
    200 
    201             A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
    202             C = C << 30 | C >>> 2;
    203         }
    204 
    205         //
    206         // round 2
    207         //
    208         for (int j = 0; j < 4; j++)
    209         {
    210             // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
    211             // B = rotateLeft(B, 30)
    212             E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
    213             B = B << 30 | B >>> 2;
    214 
    215             D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
    216             A = A << 30 | A >>> 2;
    217 
    218             C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
    219             E = E << 30 | E >>> 2;
    220 
    221             B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
    222             D = D << 30 | D >>> 2;
    223 
    224             A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
    225             C = C << 30 | C >>> 2;
    226         }
    227 
    228         //
    229         // round 3
    230         //
    231         for (int j = 0; j < 4; j++)
    232         {
    233             // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
    234             // B = rotateLeft(B, 30)
    235             E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
    236             B = B << 30 | B >>> 2;
    237 
    238             D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
    239             A = A << 30 | A >>> 2;
    240 
    241             C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
    242             E = E << 30 | E >>> 2;
    243 
    244             B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
    245             D = D << 30 | D >>> 2;
    246 
    247             A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
    248             C = C << 30 | C >>> 2;
    249         }
    250 
    251         //
    252         // round 4
    253         //
    254         for (int j = 0; j <= 3; j++)
    255         {
    256             // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
    257             // B = rotateLeft(B, 30)
    258             E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
    259             B = B << 30 | B >>> 2;
    260 
    261             D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
    262             A = A << 30 | A >>> 2;
    263 
    264             C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
    265             E = E << 30 | E >>> 2;
    266 
    267             B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
    268             D = D << 30 | D >>> 2;
    269 
    270             A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
    271             C = C << 30 | C >>> 2;
    272         }
    273 
    274 
    275         H1 += A;
    276         H2 += B;
    277         H3 += C;
    278         H4 += D;
    279         H5 += E;
    280 
    281         //
    282         // reset start of the buffer.
    283         //
    284         xOff = 0;
    285         for (int i = 0; i < 16; i++)
    286         {
    287             X[i] = 0;
    288         }
    289     }
    290 }
    291 
    292 
    293 
    294 
    295