diff options
Diffstat (limited to 'libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java')
-rw-r--r-- | libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java | 547 |
1 files changed, 0 insertions, 547 deletions
diff --git a/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java deleted file mode 100644 index 3416b7139..000000000 --- a/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/digests/SHA3Digest.java +++ /dev/null @@ -1,547 +0,0 @@ -package org.spongycastle.crypto.digests; - -import org.spongycastle.crypto.ExtendedDigest; -import org.spongycastle.util.Arrays; - -/** - * implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/ - * <p/> - * Following the naming conventions used in the C source code to enable easy review of the implementation. - */ -public class SHA3Digest - implements ExtendedDigest -{ - private static long[] KeccakRoundConstants = keccakInitializeRoundConstants(); - - private static int[] KeccakRhoOffsets = keccakInitializeRhoOffsets(); - - private static long[] keccakInitializeRoundConstants() - { - long[] keccakRoundConstants = new long[24]; - byte[] LFSRstate = new byte[1]; - - LFSRstate[0] = 0x01; - int i, j, bitPosition; - - for (i = 0; i < 24; i++) - { - keccakRoundConstants[i] = 0; - for (j = 0; j < 7; j++) - { - bitPosition = (1 << j) - 1; - if (LFSR86540(LFSRstate)) - { - keccakRoundConstants[i] ^= 1L << bitPosition; - } - } - } - - return keccakRoundConstants; - } - - private static boolean LFSR86540(byte[] LFSR) - { - boolean result = (((LFSR[0]) & 0x01) != 0); - if (((LFSR[0]) & 0x80) != 0) - { - LFSR[0] = (byte)(((LFSR[0]) << 1) ^ 0x71); - } - else - { - LFSR[0] <<= 1; - } - - return result; - } - - private static int[] keccakInitializeRhoOffsets() - { - int[] keccakRhoOffsets = new int[25]; - int x, y, t, newX, newY; - - keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = 0; - x = 1; - y = 0; - for (t = 0; t < 24; t++) - { - keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = ((t + 1) * (t + 2) / 2) % 64; - newX = (0 * x + 1 * y) % 5; - newY = (2 * x + 3 * y) % 5; - x = newX; - y = newY; - } - - return keccakRhoOffsets; - } - - private byte[] state = new byte[(1600 / 8)]; - private byte[] dataQueue = new byte[(1536 / 8)]; - private int rate; - private int bitsInQueue; - private int fixedOutputLength; - private boolean squeezing; - private int bitsAvailableForSqueezing; - private byte[] chunk; - private byte[] oneByte; - - private void clearDataQueueSection(int off, int len) - { - for (int i = off; i != off + len; i++) - { - dataQueue[i] = 0; - } - } - - public SHA3Digest() - { - init(0); - } - - public SHA3Digest(int bitLength) - { - init(bitLength); - } - - public SHA3Digest(SHA3Digest source) { - System.arraycopy(source.state, 0, this.state, 0, source.state.length); - System.arraycopy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.length); - this.rate = source.rate; - this.bitsInQueue = source.bitsInQueue; - this.fixedOutputLength = source.fixedOutputLength; - this.squeezing = source.squeezing; - this.bitsAvailableForSqueezing = source.bitsAvailableForSqueezing; - this.chunk = Arrays.clone(source.chunk); - this.oneByte = Arrays.clone(source.oneByte); - } - - public String getAlgorithmName() - { - return "SHA3-" + fixedOutputLength; - } - - public int getDigestSize() - { - return fixedOutputLength / 8; - } - - public void update(byte in) - { - oneByte[0] = in; - - doUpdate(oneByte, 0, 8L); - } - - public void update(byte[] in, int inOff, int len) - { - doUpdate(in, inOff, len * 8L); - } - - public int doFinal(byte[] out, int outOff) - { - squeeze(out, outOff, fixedOutputLength); - - reset(); - - return getDigestSize(); - } - - public void reset() - { - init(fixedOutputLength); - } - - /** - * Return the size of block that the compression function is applied to in bytes. - * - * @return internal byte length of a block. - */ - public int getByteLength() - { - return rate / 8; - } - - private void init(int bitLength) - { - switch (bitLength) - { - case 0: - case 288: - initSponge(1024, 576); - break; - case 224: - initSponge(1152, 448); - break; - case 256: - initSponge(1088, 512); - break; - case 384: - initSponge(832, 768); - break; - case 512: - initSponge(576, 1024); - break; - default: - throw new IllegalArgumentException("bitLength must be one of 224, 256, 384, or 512."); - } - } - - private void doUpdate(byte[] data, int off, long databitlen) - { - if ((databitlen % 8) == 0) - { - absorb(data, off, databitlen); - } - else - { - absorb(data, off, databitlen - (databitlen % 8)); - - byte[] lastByte = new byte[1]; - - lastByte[0] = (byte)(data[off + (int)(databitlen / 8)] >> (8 - (databitlen % 8))); - absorb(lastByte, off, databitlen % 8); - } - } - - private void initSponge(int rate, int capacity) - { - if (rate + capacity != 1600) - { - throw new IllegalStateException("rate + capacity != 1600"); - } - if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) - { - throw new IllegalStateException("invalid rate value"); - } - - this.rate = rate; - // this is never read, need to check to see why we want to save it - // this.capacity = capacity; - this.fixedOutputLength = 0; - Arrays.fill(this.state, (byte)0); - Arrays.fill(this.dataQueue, (byte)0); - this.bitsInQueue = 0; - this.squeezing = false; - this.bitsAvailableForSqueezing = 0; - this.fixedOutputLength = capacity / 2; - this.chunk = new byte[rate / 8]; - this.oneByte = new byte[1]; - } - - private void absorbQueue() - { - KeccakAbsorb(state, dataQueue, rate / 8); - - bitsInQueue = 0; - } - - private void absorb(byte[] data, int off, long databitlen) - { - long i, j, wholeBlocks; - - if ((bitsInQueue % 8) != 0) - { - throw new IllegalStateException("attempt to absorb with odd length queue."); - } - if (squeezing) - { - throw new IllegalStateException("attempt to absorb while squeezing."); - } - - i = 0; - while (i < databitlen) - { - if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate))) - { - wholeBlocks = (databitlen - i) / rate; - - for (j = 0; j < wholeBlocks; j++) - { - System.arraycopy(data, (int)(off + (i / 8) + (j * chunk.length)), chunk, 0, chunk.length); - -// displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8); - - KeccakAbsorb(state, chunk, chunk.length); - } - - i += wholeBlocks * rate; - } - else - { - int partialBlock = (int)(databitlen - i); - if (partialBlock + bitsInQueue > rate) - { - partialBlock = rate - bitsInQueue; - } - int partialByte = partialBlock % 8; - partialBlock -= partialByte; - System.arraycopy(data, off + (int)(i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8); - - bitsInQueue += partialBlock; - i += partialBlock; - if (bitsInQueue == rate) - { - absorbQueue(); - } - if (partialByte > 0) - { - int mask = (1 << partialByte) - 1; - dataQueue[bitsInQueue / 8] = (byte)(data[off + ((int)(i / 8))] & mask); - bitsInQueue += partialByte; - i += partialByte; - } - } - } - } - - private void padAndSwitchToSqueezingPhase() - { - if (bitsInQueue + 1 == rate) - { - dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8); - absorbQueue(); - clearDataQueueSection(0, rate / 8); - } - else - { - clearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8); - dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8); - } - dataQueue[(rate - 1) / 8] |= 1 << ((rate - 1) % 8); - absorbQueue(); - - -// displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---"); - - - if (rate == 1024) - { - KeccakExtract1024bits(state, dataQueue); - bitsAvailableForSqueezing = 1024; - } - else - - { - KeccakExtract(state, dataQueue, rate / 64); - bitsAvailableForSqueezing = rate; - } - -// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8); - - squeezing = true; - } - - private void squeeze(byte[] output, int offset, long outputLength) - { - long i; - int partialBlock; - - if (!squeezing) - { - padAndSwitchToSqueezingPhase(); - } - if ((outputLength % 8) != 0) - { - throw new IllegalStateException("outputLength not a multiple of 8"); - } - - i = 0; - while (i < outputLength) - { - if (bitsAvailableForSqueezing == 0) - { - keccakPermutation(state); - - if (rate == 1024) - { - KeccakExtract1024bits(state, dataQueue); - bitsAvailableForSqueezing = 1024; - } - else - - { - KeccakExtract(state, dataQueue, rate / 64); - bitsAvailableForSqueezing = rate; - } - -// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8); - - } - partialBlock = bitsAvailableForSqueezing; - if ((long)partialBlock > outputLength - i) - { - partialBlock = (int)(outputLength - i); - } - - System.arraycopy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int)(i / 8), partialBlock / 8); - bitsAvailableForSqueezing -= partialBlock; - i += partialBlock; - } - } - - private void fromBytesToWords(long[] stateAsWords, byte[] state) - { - for (int i = 0; i < (1600 / 64); i++) - { - stateAsWords[i] = 0; - int index = i * (64 / 8); - for (int j = 0; j < (64 / 8); j++) - { - stateAsWords[i] |= ((long)state[index + j] & 0xff) << ((8 * j)); - } - } - } - - private void fromWordsToBytes(byte[] state, long[] stateAsWords) - { - for (int i = 0; i < (1600 / 64); i++) - { - int index = i * (64 / 8); - for (int j = 0; j < (64 / 8); j++) - { - state[index + j] = (byte)((stateAsWords[i] >>> ((8 * j))) & 0xFF); - } - } - } - - private void keccakPermutation(byte[] state) - { - long[] longState = new long[state.length / 8]; - - fromBytesToWords(longState, state); - -// displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState); - - keccakPermutationOnWords(longState); - -// displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState); - - fromWordsToBytes(state, longState); - } - - private void keccakPermutationAfterXor(byte[] state, byte[] data, int dataLengthInBytes) - { - int i; - - for (i = 0; i < dataLengthInBytes; i++) - { - state[i] ^= data[i]; - } - - keccakPermutation(state); - } - - private void keccakPermutationOnWords(long[] state) - { - int i; - -// displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state); - - for (i = 0; i < 24; i++) - { -// displayIntermediateValues.displayRoundNumber(3, i); - - theta(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state); - - rho(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state); - - pi(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state); - - chi(state); -// displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state); - - iota(state, i); -// displayIntermediateValues.displayStateAs64bitWords(3, "After iota", state); - } - } - - long[] C = new long[5]; - - private void theta(long[] A) - { - for (int x = 0; x < 5; x++) - { - C[x] = 0; - for (int y = 0; y < 5; y++) - { - C[x] ^= A[x + 5 * y]; - } - } - for (int x = 0; x < 5; x++) - { - long dX = ((((C[(x + 1) % 5]) << 1) ^ ((C[(x + 1) % 5]) >>> (64 - 1)))) ^ C[(x + 4) % 5]; - for (int y = 0; y < 5; y++) - { - A[x + 5 * y] ^= dX; - } - } - } - - private void rho(long[] A) - { - for (int x = 0; x < 5; x++) - { - for (int y = 0; y < 5; y++) - { - int index = x + 5 * y; - A[index] = ((KeccakRhoOffsets[index] != 0) ? (((A[index]) << KeccakRhoOffsets[index]) ^ ((A[index]) >>> (64 - KeccakRhoOffsets[index]))) : A[index]); - } - } - } - - long[] tempA = new long[25]; - - private void pi(long[] A) - { - System.arraycopy(A, 0, tempA, 0, tempA.length); - - for (int x = 0; x < 5; x++) - { - for (int y = 0; y < 5; y++) - { - A[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y]; - } - } - } - - long[] chiC = new long[5]; - - private void chi(long[] A) - { - for (int y = 0; y < 5; y++) - { - for (int x = 0; x < 5; x++) - { - chiC[x] = A[x + 5 * y] ^ ((~A[(((x + 1) % 5) + 5 * y)]) & A[(((x + 2) % 5) + 5 * y)]); - } - for (int x = 0; x < 5; x++) - { - A[x + 5 * y] = chiC[x]; - } - } - } - - private void iota(long[] A, int indexRound) - { - A[(((0) % 5) + 5 * ((0) % 5))] ^= KeccakRoundConstants[indexRound]; - } - - private void KeccakAbsorb(byte[] byteState, byte[] data, int dataInBytes) - { - keccakPermutationAfterXor(byteState, data, dataInBytes); - } - - - private void KeccakExtract1024bits(byte[] byteState, byte[] data) - { - System.arraycopy(byteState, 0, data, 0, 128); - } - - - private void KeccakExtract(byte[] byteState, byte[] data, int laneCount) - { - System.arraycopy(byteState, 0, data, 0, laneCount * 8); - } -} |