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