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