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

org.bouncycastle.crypto.digests.SHA512tDigest 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.CryptoServicesRegistrar;
import org.bouncycastle.util.Memoable;
import org.bouncycastle.util.MemoableResetException;
import org.bouncycastle.util.Pack;

/**
 * FIPS 180-4 implementation of SHA-512/t
 */
public class SHA512tDigest
    extends LongDigest
{
    private int digestLength;      // non-final due to old flow analyser.

    private long  H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t;

    /**
     * Standard constructor
     */
    public SHA512tDigest(int bitLength)
    {
        this(bitLength, CryptoServicePurpose.ANY);
    }

    public SHA512tDigest(int bitLength, CryptoServicePurpose purpose)
    {
        if (bitLength >= 512)
        {
            throw new IllegalArgumentException("bitLength cannot be >= 512");
        }

        if (bitLength % 8 != 0)
        {
            throw new IllegalArgumentException("bitLength needs to be a multiple of 8");
        }

        if (bitLength == 384)
        {
            throw new IllegalArgumentException("bitLength cannot be 384 use SHA384 instead");
        }

        this.digestLength = bitLength / 8;

        CryptoServicesRegistrar.checkConstraints(cryptoServiceProperties());

        tIvGenerate(digestLength * 8);

        reset();
    }

    /**
     * Copy constructor.  This will copy the state of the provided
     * message digest.
     */
    public SHA512tDigest(SHA512tDigest t)
    {
        super(t);

        this.digestLength = t.digestLength;

        CryptoServicesRegistrar.checkConstraints(cryptoServiceProperties());

        reset(t);
    }

    public SHA512tDigest(byte[] encodedState)
    {
        this(readDigestLength(encodedState), CryptoServicePurpose.values()[encodedState[encodedState.length - 1]]);

        CryptoServicesRegistrar.checkConstraints(cryptoServiceProperties());

        restoreState(encodedState);
    }

    private static int readDigestLength(byte[] encodedState)
    {
        return Pack.bigEndianToInt(encodedState, encodedState.length - 5);
    }

    public String getAlgorithmName()
    {
        return "SHA-512/" + Integer.toString(digestLength * 8);
    }

    public int getDigestSize()
    {
        return digestLength;
    }

    public int doFinal(
        byte[]  out,
        int     outOff)
    {
        finish();

        longToBigEndian(H1, out, outOff, digestLength);
        longToBigEndian(H2, out, outOff + 8, digestLength - 8);
        longToBigEndian(H3, out, outOff + 16, digestLength - 16);
        longToBigEndian(H4, out, outOff + 24, digestLength - 24);
        longToBigEndian(H5, out, outOff + 32, digestLength - 32);
        longToBigEndian(H6, out, outOff + 40, digestLength - 40);
        longToBigEndian(H7, out, outOff + 48, digestLength - 48);
        longToBigEndian(H8, out, outOff + 56, digestLength - 56);

        reset();

        return digestLength;
    }

    /**
     * reset the chaining variables
     */
    public void reset()
    {
        super.reset();

        /*
         * initial hash values use the iv generation algorithm for t.
         */
        H1 = H1t;
        H2 = H2t;
        H3 = H3t;
        H4 = H4t;
        H5 = H5t;
        H6 = H6t;
        H7 = H7t;
        H8 = H8t;
    }

    private void tIvGenerate(int bitLength)
    {
        H1 = 0x6a09e667f3bcc908L ^ 0xa5a5a5a5a5a5a5a5L;
        H2 = 0xbb67ae8584caa73bL ^ 0xa5a5a5a5a5a5a5a5L;
        H3 = 0x3c6ef372fe94f82bL ^ 0xa5a5a5a5a5a5a5a5L;
        H4 = 0xa54ff53a5f1d36f1L ^ 0xa5a5a5a5a5a5a5a5L;
        H5 = 0x510e527fade682d1L ^ 0xa5a5a5a5a5a5a5a5L;
        H6 = 0x9b05688c2b3e6c1fL ^ 0xa5a5a5a5a5a5a5a5L;
        H7 = 0x1f83d9abfb41bd6bL ^ 0xa5a5a5a5a5a5a5a5L;
        H8 = 0x5be0cd19137e2179L ^ 0xa5a5a5a5a5a5a5a5L;

        update((byte)0x53);
        update((byte)0x48);
        update((byte)0x41);
        update((byte)0x2D);
        update((byte)0x35);
        update((byte)0x31);
        update((byte)0x32);
        update((byte)0x2F);

        if (bitLength > 100)
        {
            update((byte)(bitLength / 100 + 0x30));
            bitLength = bitLength % 100;
            update((byte)(bitLength / 10 + 0x30));
            bitLength = bitLength % 10;
            update((byte)(bitLength + 0x30));
        }
        else if (bitLength > 10)
        {
            update((byte)(bitLength / 10 + 0x30));
            bitLength = bitLength % 10;
            update((byte)(bitLength + 0x30));
        }
        else
        {
            update((byte)(bitLength + 0x30));
        }

        finish();

        H1t = H1;
        H2t = H2;
        H3t = H3;
        H4t = H4;
        H5t = H5;
        H6t = H6;
        H7t = H7;
        H8t = H8;
    }

    private static void longToBigEndian(long n, byte[] bs, int off, int max)
    {
        if (max > 0)
        {
            intToBigEndian((int)(n >>> 32), bs, off, max);

            if (max > 4)
            {
                intToBigEndian((int)(n & 0xffffffffL), bs, off + 4, max - 4);
            }
        }
    }

    private static void intToBigEndian(int n, byte[] bs, int off, int max)
    {
        int num = Math.min(4, max);
        while (--num >= 0)
        {
            int shift = 8 * (3 - num);
            bs[off + num] = (byte)(n >>> shift);
        }
    }

    public Memoable copy()
    {
        return new SHA512tDigest(this);
    }

    public void reset(Memoable other)
    {
        SHA512tDigest t = (SHA512tDigest)other;

        if (this.digestLength != t.digestLength)
        {
            throw new MemoableResetException("digestLength inappropriate in other");
        }

        super.copyIn(t);

        this.H1t = t.H1t;
        this.H2t = t.H2t;
        this.H3t = t.H3t;
        this.H4t = t.H4t;
        this.H5t = t.H5t;
        this.H6t = t.H6t;
        this.H7t = t.H7t;
        this.H8t = t.H8t;
    }

    public byte[] getEncodedState()
    {
        final int baseSize = getEncodedStateSize();
        byte[] encoded = new byte[baseSize + 4 + 1];
        populateState(encoded);
        Pack.intToBigEndian(digestLength * 8, encoded, baseSize);

        encoded[encoded.length - 1] = (byte)purpose.ordinal();

        return encoded;
    }

    protected CryptoServiceProperties cryptoServiceProperties()
    {
        return Utils.getDefaultProperties(this, this.getDigestSize() * 8, purpose);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy