All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.crypto.digests.LongDigest Maven / Gradle / Ivy

Go to download

The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains JCE provider and lightweight API for the Bouncy Castle Cryptography APIs for Java 1.8 and later with debug enabled.

The newest version!
package org.bouncycastle.crypto.digests;

import org.bouncycastle.crypto.CryptoServiceProperties;
import org.bouncycastle.crypto.CryptoServicePurpose;
import org.bouncycastle.crypto.ExtendedDigest;
import org.bouncycastle.util.Memoable;
import org.bouncycastle.util.Pack;

/**
 * Base class for SHA-384 and SHA-512.
 */
public abstract class LongDigest
    implements ExtendedDigest, Memoable, EncodableDigest
{
    private static final int BYTE_LENGTH = 128;

    protected final CryptoServicePurpose purpose;

    private byte[] xBuf = new byte[8];
    private int     xBufOff;

    private long    byteCount1;
    private long    byteCount2;

    protected long    H1, H2, H3, H4, H5, H6, H7, H8;

    private long[]  W = new long[80];
    private int     wOff;

    /**
     * Constructor for variable length word
     */
    protected LongDigest()
    {
        this(CryptoServicePurpose.ANY);
    }

    /**
     * Constructor for variable length word
     */
    protected LongDigest(CryptoServicePurpose purpose)
    {
        this.purpose = purpose;

        xBufOff = 0;

        reset();
    }

    /**
     * Copy constructor.  We are using copy constructors in place
     * of the Object.clone() interface as this interface is not
     * supported by J2ME.
     */
    protected LongDigest(LongDigest t)
    {
        this.purpose = t.purpose;

        copyIn(t);
    }

    protected void copyIn(LongDigest t)
    {
        System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);

        xBufOff = t.xBufOff;
        byteCount1 = t.byteCount1;
        byteCount2 = t.byteCount2;

        H1 = t.H1;
        H2 = t.H2;
        H3 = t.H3;
        H4 = t.H4;
        H5 = t.H5;
        H6 = t.H6;
        H7 = t.H7;
        H8 = t.H8;

        System.arraycopy(t.W, 0, W, 0, t.W.length);
        wOff = t.wOff;
    }

    protected void populateState(byte[] state)
    {
        System.arraycopy(xBuf, 0, state, 0, xBufOff);
        Pack.intToBigEndian(xBufOff, state, 8);
        Pack.longToBigEndian(byteCount1, state, 12);
        Pack.longToBigEndian(byteCount2, state, 20);
        Pack.longToBigEndian(H1, state, 28);
        Pack.longToBigEndian(H2, state, 36);
        Pack.longToBigEndian(H3, state, 44);
        Pack.longToBigEndian(H4, state, 52);
        Pack.longToBigEndian(H5, state, 60);
        Pack.longToBigEndian(H6, state, 68);
        Pack.longToBigEndian(H7, state, 76);
        Pack.longToBigEndian(H8, state, 84);

        Pack.intToBigEndian(wOff, state, 92);
        for (int i = 0; i < wOff; i++)
        {
            Pack.longToBigEndian(W[i], state, 96 + (i * 8));
        }
    }

    protected void restoreState(byte[] encodedState)
    {
        xBufOff = Pack.bigEndianToInt(encodedState, 8);
        System.arraycopy(encodedState, 0, xBuf, 0, xBufOff);
        byteCount1 = Pack.bigEndianToLong(encodedState, 12);
        byteCount2 = Pack.bigEndianToLong(encodedState, 20);

        H1 = Pack.bigEndianToLong(encodedState, 28);
        H2 = Pack.bigEndianToLong(encodedState, 36);
        H3 = Pack.bigEndianToLong(encodedState, 44);
        H4 = Pack.bigEndianToLong(encodedState, 52);
        H5 = Pack.bigEndianToLong(encodedState, 60);
        H6 = Pack.bigEndianToLong(encodedState, 68);
        H7 = Pack.bigEndianToLong(encodedState, 76);
        H8 = Pack.bigEndianToLong(encodedState, 84);

        wOff = Pack.bigEndianToInt(encodedState, 92);
        for (int i = 0; i < wOff; i++)
        {
            W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8));
        }
    }

    protected int getEncodedStateSize()
    {
        return 96 + (wOff * 8);
    }

    public void update(
        byte in)
    {
        xBuf[xBufOff++] = in;

        if (xBufOff == xBuf.length)
        {
            processWord(xBuf, 0);
            xBufOff = 0;
        }

        byteCount1++;
    }

    public void update(
        byte[]  in,
        int     inOff,
        int     len)
    {
        //
        // fill the current word
        //
        while ((xBufOff != 0) && (len > 0))
        {
            update(in[inOff]);

            inOff++;
            len--;
        }

        //
        // process whole words.
        //
        while (len >= xBuf.length)
        {
            processWord(in, inOff);

            inOff += xBuf.length;
            len -= xBuf.length;
            byteCount1 += xBuf.length;
        }

        //
        // load in the remainder.
        //
        while (len > 0)
        {
            update(in[inOff]);

            inOff++;
            len--;
        }
    }

    public void finish()
    {
        adjustByteCounts();

        long    lowBitLength = byteCount1 << 3;
        long    hiBitLength = byteCount2;

        //
        // add the pad bytes.
        //
        update((byte)128);

        while (xBufOff != 0)
        {
            update((byte)0);
        }

        processLength(lowBitLength, hiBitLength);

        processBlock();
    }

    public void reset()
    {
        byteCount1 = 0;
        byteCount2 = 0;

        xBufOff = 0;
        for (int i = 0; i < xBuf.length; i++)
        {
            xBuf[i] = 0;
        }

        wOff = 0;
        for (int i = 0; i != W.length; i++)
        {
            W[i] = 0;
        }
    }

    public int getByteLength()
    {
        return BYTE_LENGTH;
    }

    protected void processWord(
        byte[]  in,
        int     inOff)
    {
        W[wOff] = Pack.bigEndianToLong(in, inOff);

        if (++wOff == 16)
        {
            processBlock();
        }
    }

    /**
     * adjust the byte counts so that byteCount2 represents the
     * upper long (less 3 bits) word of the byte count.
     */
    private void adjustByteCounts()
    {
        if (byteCount1 > 0x1fffffffffffffffL)
        {
            byteCount2 += (byteCount1 >>> 61);
            byteCount1 &= 0x1fffffffffffffffL;
        }
    }

    protected void processLength(
        long    lowW,
        long    hiW)
    {
        if (wOff > 14)
        {
            processBlock();
        }

        W[14] = hiW;
        W[15] = lowW;
    }

    protected void processBlock()
    {
        adjustByteCounts();

        //
        // expand 16 word block into 80 word blocks.
        //
        for (int t = 16; t <= 79; t++)
        {
            W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
        }

        //
        // set up working variables.
        //
        long     a = H1;
        long     b = H2;
        long     c = H3;
        long     d = H4;
        long     e = H5;
        long     f = H6;
        long     g = H7;
        long     h = H8;

        int t = 0;
        for(int i = 0; i < 10; i ++)
        {
          // t = 8 * i
          h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
          d += h;
          h += Sum0(a) + Maj(a, b, c);

          // t = 8 * i + 1
          g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
          c += g;
          g += Sum0(h) + Maj(h, a, b);

          // t = 8 * i + 2
          f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
          b += f;
          f += Sum0(g) + Maj(g, h, a);

          // t = 8 * i + 3
          e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
          a += e;
          e += Sum0(f) + Maj(f, g, h);

          // t = 8 * i + 4
          d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
          h += d;
          d += Sum0(e) + Maj(e, f, g);

          // t = 8 * i + 5
          c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
          g += c;
          c += Sum0(d) + Maj(d, e, f);

          // t = 8 * i + 6
          b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
          f += b;
          b += Sum0(c) + Maj(c, d, e);

          // t = 8 * i + 7
          a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
          e += a;
          a += Sum0(b) + Maj(b, c, d);
        }

        H1 += a;
        H2 += b;
        H3 += c;
        H4 += d;
        H5 += e;
        H6 += f;
        H7 += g;
        H8 += h;

        //
        // reset the offset and clean out the word buffer.
        //
        wOff = 0;
        for (int i = 0; i < 16; i++)
        {
            W[i] = 0;
        }
    }

    /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
    private long Ch(
        long    x,
        long    y,
        long    z)
    {
        return ((x & y) ^ ((~x) & z));
    }

    private long Maj(
        long    x,
        long    y,
        long    z)
    {
        return ((x & y) ^ (x & z) ^ (y & z));
    }

    private long Sum0(
        long    x)
    {
        return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
    }

    private long Sum1(
        long    x)
    {
        return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
    }

    private long Sigma0(
        long    x)
    {
        return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7);
    }

    private long Sigma1(
        long    x)
    {
        return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6);
    }

    /* SHA-384 and SHA-512 Constants
     * (represent the first 64 bits of the fractional parts of the
     * cube roots of the first sixty-four prime numbers)
     */
    static final long K[] = {
0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
    };

    protected abstract CryptoServiceProperties cryptoServiceProperties();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy