116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.crypto.digests;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.util.Memoable;
553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giroimport org.bouncycastle.util.Pack;
616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro/**
916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * SHA-224 as described in RFC 3874
1016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * <pre>
1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro *         block  word  digest
1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * SHA-1   512    32    160
1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * SHA-224 512    32    224
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * SHA-256 512    32    256
1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * SHA-384 1024   64    384
1616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * SHA-512 1024   64    512
1716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * </pre>
1816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro */
1916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic class SHA224Digest
2016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    extends GeneralDigest
2153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    implements EncodableDigest
2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
2316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private static final int    DIGEST_LENGTH = 28;
2416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
2516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int     H1, H2, H3, H4, H5, H6, H7, H8;
2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int[]   X = new int[64];
2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int     xOff;
2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
3116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Standard constructor
3216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
3316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public SHA224Digest()
3416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        reset();
3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Copy constructor.  This will copy the state of the provided
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * message digest.
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public SHA224Digest(SHA224Digest t)
4316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
4416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        super(t);
4516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        doCopy(t);
4716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
4816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private void doCopy(SHA224Digest t)
5016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
5116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        super.copyIn(t);
5216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
5316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H1 = t.H1;
5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H2 = t.H2;
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H3 = t.H3;
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H4 = t.H4;
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H5 = t.H5;
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H6 = t.H6;
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H7 = t.H7;
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H8 = t.H8;
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        System.arraycopy(t.X, 0, X, 0, t.X.length);
6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        xOff = t.xOff;
6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
664caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    /**
674caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro     * State constructor - create a digest initialised with the state of a previous one.
684caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro     *
694caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro     * @param encodedState the encoded state from the originating digest.
704caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro     */
7153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public SHA224Digest(byte[] encodedState)
7253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
7353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        super(encodedState);
7453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
7553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H1 = Pack.bigEndianToInt(encodedState, 16);
7653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H2 = Pack.bigEndianToInt(encodedState, 20);
7753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H3 = Pack.bigEndianToInt(encodedState, 24);
7853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H4 = Pack.bigEndianToInt(encodedState, 28);
7953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H5 = Pack.bigEndianToInt(encodedState, 32);
8053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H6 = Pack.bigEndianToInt(encodedState, 36);
8153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H7 = Pack.bigEndianToInt(encodedState, 40);
8253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        H8 = Pack.bigEndianToInt(encodedState, 44);
8353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
8453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        xOff = Pack.bigEndianToInt(encodedState, 48);
8553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        for (int i = 0; i != xOff; i++)
8653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
8753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
8853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
8953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
9053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
9116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public String getAlgorithmName()
9216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
9316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return "SHA-224";
9416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
9516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public int getDigestSize()
9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
9816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return DIGEST_LENGTH;
9916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
10016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void processWord(
10216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  in,
10316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     inOff)
10416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
10516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // Note: Inlined for performance
10616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro//        X[xOff] = Pack.bigEndianToInt(in, inOff);
10716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int n = in[  inOff] << 24;
10816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        n |= (in[++inOff] & 0xff) << 16;
10916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        n |= (in[++inOff] & 0xff) << 8;
11016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        n |= (in[++inOff] & 0xff);
11116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        X[xOff] = n;
11216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (++xOff == 16)
11416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
11516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            processBlock();
11616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
11716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
11816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void processLength(
12016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        long    bitLength)
12116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
12216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (xOff > 14)
12316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
12416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            processBlock();
12516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
12616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
12716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        X[14] = (int)(bitLength >>> 32);
12816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        X[15] = (int)(bitLength & 0xffffffff);
12916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
13016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
13116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public int doFinal(
13216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  out,
13316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     outOff)
13416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
13516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        finish();
13616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
13716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H1, out, outOff);
13816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H2, out, outOff + 4);
13916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H3, out, outOff + 8);
14016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H4, out, outOff + 12);
14116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H5, out, outOff + 16);
14216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H6, out, outOff + 20);
14316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        Pack.intToBigEndian(H7, out, outOff + 24);
14416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
14516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        reset();
14616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
14716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return DIGEST_LENGTH;
14816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
14916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
15016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
15116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * reset the chaining variables
15216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
15316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public void reset()
15416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
15516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        super.reset();
15616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
15716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        /* SHA-224 initial hash value
15816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro         */
15916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
16016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H1 = 0xc1059ed8;
16116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H2 = 0x367cd507;
16216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H3 = 0x3070dd17;
16316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H4 = 0xf70e5939;
16416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H5 = 0xffc00b31;
16516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H6 = 0x68581511;
16616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H7 = 0x64f98fa7;
16716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H8 = 0xbefa4fa4;
16816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
16916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        xOff = 0;
17016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        for (int i = 0; i != X.length; i++)
17116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
17216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            X[i] = 0;
17316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
17416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
17516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
17616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    protected void processBlock()
17716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
17816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
17916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // expand 16 word block into 64 word blocks.
18016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
18116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        for (int t = 16; t <= 63; t++)
18216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
18316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
18416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
18516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
18616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
18716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // set up working variables.
18816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
18916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     a = H1;
19016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     b = H2;
19116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     c = H3;
19216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     d = H4;
19316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     e = H5;
19416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     f = H6;
19516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     g = H7;
19616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     h = H8;
19716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
19816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
19916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int t = 0;
20016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        for(int i = 0; i < 8; i ++)
20116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
20216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i
20316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
20416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            d += h;
20516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            h += Sum0(a) + Maj(a, b, c);
20616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
20716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
20816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 1
20916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
21016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            c += g;
21116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            g += Sum0(h) + Maj(h, a, b);
21216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
21316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
21416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 2
21516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
21616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            b += f;
21716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            f += Sum0(g) + Maj(g, h, a);
21816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
21916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
22016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 3
22116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
22216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            a += e;
22316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            e += Sum0(f) + Maj(f, g, h);
22416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
22516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
22616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 4
22716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
22816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            h += d;
22916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            d += Sum0(e) + Maj(e, f, g);
23016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
23116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
23216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 5
23316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
23416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            g += c;
23516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            c += Sum0(d) + Maj(d, e, f);
23616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
23716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
23816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 6
23916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
24016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            f += b;
24116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            b += Sum0(c) + Maj(c, d, e);
24216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
24316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
24416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // t = 8 * i + 7
24516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
24616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            e += a;
24716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            a += Sum0(b) + Maj(b, c, d);
24816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ++t;
24916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
25016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
25116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H1 += a;
25216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H2 += b;
25316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H3 += c;
25416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H4 += d;
25516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H5 += e;
25616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H6 += f;
25716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H7 += g;
25816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        H8 += h;
25916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
26016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
26116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        // reset the offset and clean out the word buffer.
26216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        //
26316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        xOff = 0;
26416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        for (int i = 0; i < 16; i++)
26516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
26616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            X[i] = 0;
26716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
26816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
26916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
27016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /* SHA-224 functions */
27116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int Ch(
27216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    x,
27316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    y,
27416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    z)
27516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
27616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return ((x & y) ^ ((~x) & z));
27716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
27816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
27916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int Maj(
28016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    x,
28116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    y,
28216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    z)
28316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
28416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return ((x & y) ^ (x & z) ^ (y & z));
28516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
28616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
28716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int Sum0(
28816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    x)
28916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
29016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
29116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
29216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
29316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int Sum1(
29416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    x)
29516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
29616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
29716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
29816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
29916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int Theta0(
30016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    x)
30116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
30216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
30316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
30416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
30516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private int Theta1(
30616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int    x)
30716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
30816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
30916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
31016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
31116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /* SHA-224 Constants
31216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * (represent the first 32 bits of the fractional parts of the
31316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * cube roots of the first sixty-four prime numbers)
31416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
31516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    static final int K[] = {
31616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
31716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
31816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
31916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
32016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
32116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
32216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
32316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    };
32416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
32516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public Memoable copy()
32616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
32716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return new SHA224Digest(this);
32816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
32916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
33016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public void reset(Memoable other)
33116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
33216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        SHA224Digest d = (SHA224Digest)other;
33316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
33416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        doCopy(d);
33516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
33653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
33753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    public byte[] getEncodedState()
33853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    {
33953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        byte[] state = new byte[52 + xOff * 4];
34053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
34153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        super.populateState(state);
34253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
34353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H1, state, 16);
34453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H2, state, 20);
34553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H3, state, 24);
34653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H4, state, 28);
34753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H5, state, 32);
34853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H6, state, 36);
34953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H7, state, 40);
35053b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(H8, state, 44);
35153b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        Pack.intToBigEndian(xOff, state, 48);
35253b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
35353b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        for (int i = 0; i != xOff; i++)
35453b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        {
35553b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro            Pack.intToBigEndian(X[i], state, 52 + (i * 4));
35653b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        }
35753b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro
35853b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro        return state;
35953b61f9fe9d58034fcc7021137e92460f91b70ceSergio Giro    }
36016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
36116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
362