Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.digests;
  
implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349. It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5 is the "endianness" of the word processing!
 
 public class SHA1Digest
     extends GeneralDigest
     implements EncodableDigest
 {
     private static final int    DIGEST_LENGTH = 20;
 
     private int     H1H2H3H4H5;
 
     private int[]   X = new int[80];
     private int     xOff;

    
Standard constructor
 
     public SHA1Digest()
     {
         reset();
     }

    
Copy constructor. This will copy the state of the provided message digest.
 
     public SHA1Digest(SHA1Digest t)
     {
         super(t);
 
         copyIn(t);
     }
 
     public SHA1Digest(byte[] encodedState)
     {
         super(encodedState);
 
          = Pack.bigEndianToInt(encodedState, 16);
          = Pack.bigEndianToInt(encodedState, 20);
          = Pack.bigEndianToInt(encodedState, 24);
          = Pack.bigEndianToInt(encodedState, 28);
          = Pack.bigEndianToInt(encodedState, 32);
 
          = Pack.bigEndianToInt(encodedState, 36);
         for (int i = 0; i != i++)
         {
             [i] = Pack.bigEndianToInt(encodedState, 40 + (i * 4));
         }
     }
 
     private void copyIn(SHA1Digest t)
     {
          = t.H1;
          = t.H2;
          = t.H3;
          = t.H4;
          = t.H5;
 
         System.arraycopy(t.X, 0, , 0, t.X.length);
          = t.xOff;
     }
 
     public String getAlgorithmName()
     {
         return "SHA-1";
     }
 
     public int getDigestSize()
     {
         return ;
     }
 
     protected void processWord(
         byte[]  in,
         int     inOff)
     {
         // Note: Inlined for performance
 //        X[xOff] = Pack.bigEndianToInt(in, inOff);
         int n = in[  inOff] << 24;
         n |= (in[++inOff] & 0xff) << 16;
         n |= (in[++inOff] & 0xff) << 8;
         n |= (in[++inOff] & 0xff);
         [] = n;
 
         if (++ == 16)
         {
             processBlock();
         }        
     }
 
     protected void processLength(
        long    bitLength)
    {
        if ( > 14)
        {
            processBlock();
        }
        [14] = (int)(bitLength >>> 32);
        [15] = (int)(bitLength & 0xffffffff);
    }
    public int doFinal(
        byte[]  out,
        int     outOff)
    {
        finish();
        Pack.intToBigEndian(outoutOff);
        Pack.intToBigEndian(outoutOff + 4);
        Pack.intToBigEndian(outoutOff + 8);
        Pack.intToBigEndian(outoutOff + 12);
        Pack.intToBigEndian(outoutOff + 16);
        reset();
        return ;
    }

    
reset the chaining variables
    public void reset()
    {
        super.reset();
         = 0x67452301;
         = 0xefcdab89;
         = 0x98badcfe;
         = 0x10325476;
         = 0xc3d2e1f0;
         = 0;
        for (int i = 0; i != .i++)
        {
            [i] = 0;
        }
    }
    //
    // Additive constants
    //
    private static final int    Y1 = 0x5a827999;
    private static final int    Y2 = 0x6ed9eba1;
    private static final int    Y3 = 0x8f1bbcdc;
    private static final int    Y4 = 0xca62c1d6;
   
    private int f(
        int    u,
        int    v,
        int    w)
    {
        return ((u & v) | ((~u) & w));
    }
    private int h(
        int    u,
        int    v,
        int    w)
    {
        return (u ^ v ^ w);
    }
    private int g(
        int    u,
        int    v,
        int    w)
    {
        return ((u & v) | (u & w) | (v & w));
    }
    protected void processBlock()
    {
        //
        // expand 16 word block into 80 word block.
        //
        for (int i = 16; i < 80; i++)
        {
            int t = [i - 3] ^ [i - 8] ^ [i - 14] ^ [i - 16];
            [i] = t << 1 | t >>> 31;
        }
        //
        // set up working variables.
        //
        int     A = ;
        int     B = ;
        int     C = ;
        int     D = ;
        int     E = ;
        //
        // round 1
        //
        int idx = 0;
        
        for (int j = 0; j < 4; j++)
        {
            // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
            // B = rotateLeft(B, 30)
            E += (A << 5 | A >>> 27) + f(BCD) + [idx++] + ;
            B = B << 30 | B >>> 2;
        
            D += (E << 5 | E >>> 27) + f(ABC) + [idx++] + ;
            A = A << 30 | A >>> 2;
       
            C += (D << 5 | D >>> 27) + f(EAB) + [idx++] + ;
            E = E << 30 | E >>> 2;
       
            B += (C << 5 | C >>> 27) + f(DEA) + [idx++] + ;
            D = D << 30 | D >>> 2;
            A += (B << 5 | B >>> 27) + f(CDE) + [idx++] + ;
            C = C << 30 | C >>> 2;
        }
        
        //
        // round 2
        //
        for (int j = 0; j < 4; j++)
        {
            // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
            // B = rotateLeft(B, 30)
            E += (A << 5 | A >>> 27) + h(BCD) + [idx++] + ;
            B = B << 30 | B >>> 2;   
            
            D += (E << 5 | E >>> 27) + h(ABC) + [idx++] + ;
            A = A << 30 | A >>> 2;
            
            C += (D << 5 | D >>> 27) + h(EAB) + [idx++] + ;
            E = E << 30 | E >>> 2;
            
            B += (C << 5 | C >>> 27) + h(DEA) + [idx++] + ;
            D = D << 30 | D >>> 2;
            A += (B << 5 | B >>> 27) + h(CDE) + [idx++] + ;
            C = C << 30 | C >>> 2;
        }
        
        //
        // round 3
        //
        for (int j = 0; j < 4; j++)
        {
            // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
            // B = rotateLeft(B, 30)
            E += (A << 5 | A >>> 27) + g(BCD) + [idx++] + ;
            B = B << 30 | B >>> 2;
            
            D += (E << 5 | E >>> 27) + g(ABC) + [idx++] + ;
            A = A << 30 | A >>> 2;
            
            C += (D << 5 | D >>> 27) + g(EAB) + [idx++] + ;
            E = E << 30 | E >>> 2;
            
            B += (C << 5 | C >>> 27) + g(DEA) + [idx++] + ;
            D = D << 30 | D >>> 2;
            A += (B << 5 | B >>> 27) + g(CDE) + [idx++] + ;
            C = C << 30 | C >>> 2;
        }
        //
        // round 4
        //
        for (int j = 0; j <= 3; j++)
        {
            // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
            // B = rotateLeft(B, 30)
            E += (A << 5 | A >>> 27) + h(BCD) + [idx++] + ;
            B = B << 30 | B >>> 2;
            
            D += (E << 5 | E >>> 27) + h(ABC) + [idx++] + ;
            A = A << 30 | A >>> 2;
            
            C += (D << 5 | D >>> 27) + h(EAB) + [idx++] + ;
            E = E << 30 | E >>> 2;
            
            B += (C << 5 | C >>> 27) + h(DEA) + [idx++] + ;
            D = D << 30 | D >>> 2;
            A += (B << 5 | B >>> 27) + h(CDE) + [idx++] + ;
            C = C << 30 | C >>> 2;
        }
         += A;
         += B;
         += C;
         += D;
         += E;
        //
        // reset start of the buffer.
        //
         = 0;
        for (int i = 0; i < 16; i++)
        {
            [i] = 0;
        }
    }
    public Memoable copy()
    {
        return new SHA1Digest(this);
    }
    public void reset(Memoable other)
    {
        SHA1Digest d = (SHA1Digest)other;
        super.copyIn(d);
        copyIn(d);
    }
    public byte[] getEncodedState()
    {
        byte[] state = new byte[40 +  * 4];
        super.populateState(state);
        Pack.intToBigEndian(state, 16);
        Pack.intToBigEndian(state, 20);
        Pack.intToBigEndian(state, 24);
        Pack.intToBigEndian(state, 28);
        Pack.intToBigEndian(state, 32);
        Pack.intToBigEndian(state, 36);
        for (int i = 0; i != i++)
        {
            Pack.intToBigEndian([i], state, 40 + (i * 4));
        }
        return state;
    }
New to GrepCode? Check out our FAQ X