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

org.bouncycastle.crypto.digests.PhotonBeetleDigest 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 JDK 1.5 to JDK 1.8.

There is a newer version: 1.79
Show newest version
package org.bouncycastle.crypto.digests;

import java.io.ByteArrayOutputStream;

import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Bytes;

/**
 * Photon-Beetle, https://www.isical.ac.in/~lightweight/beetle/
 * https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/photon-beetle-spec-final.pdf
 * 

* Photon-Beetle with reference to C Reference Impl from: https://github.com/PHOTON-Beetle/Software *

*/ public class PhotonBeetleDigest implements Digest { private byte[] state; private byte[][] state_2d; private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); private final int INITIAL_RATE_INBYTES = 16; private int RATE_INBYTES = 4; private int SQUEEZE_RATE_INBYTES = 16; private int STATE_INBYTES = 32; private int TAG_INBYTES = 32; private int LAST_THREE_BITS_OFFSET = 5; private int ROUND = 12; private int D = 8; private int Dq = 3; private int Dr = 7; private int DSquare = 64; private int S = 4; private int S_1 = 3; private byte[][] RC = {//[D][12] {1, 3, 7, 14, 13, 11, 6, 12, 9, 2, 5, 10}, {0, 2, 6, 15, 12, 10, 7, 13, 8, 3, 4, 11}, {2, 0, 4, 13, 14, 8, 5, 15, 10, 1, 6, 9}, {6, 4, 0, 9, 10, 12, 1, 11, 14, 5, 2, 13}, {14, 12, 8, 1, 2, 4, 9, 3, 6, 13, 10, 5}, {15, 13, 9, 0, 3, 5, 8, 2, 7, 12, 11, 4}, {13, 15, 11, 2, 1, 7, 10, 0, 5, 14, 9, 6}, {9, 11, 15, 6, 5, 3, 14, 4, 1, 10, 13, 2} }; private byte[][] MixColMatrix = { //[D][D] {2, 4, 2, 11, 2, 8, 5, 6}, {12, 9, 8, 13, 7, 7, 5, 2}, {4, 4, 13, 13, 9, 4, 13, 9}, {1, 6, 5, 1, 12, 13, 15, 14}, {15, 12, 9, 13, 14, 5, 14, 13}, {9, 14, 5, 15, 4, 12, 9, 6}, {12, 2, 2, 10, 3, 1, 1, 14}, {15, 1, 13, 10, 5, 10, 2, 3} }; private byte[] sbox = {12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2}; public PhotonBeetleDigest() { state = new byte[STATE_INBYTES]; state_2d = new byte[D][D]; } @Override public String getAlgorithmName() { return "Photon-Beetle Hash"; } @Override public int getDigestSize() { return TAG_INBYTES; } @Override public void update(byte input) { buffer.write(input); } @Override public void update(byte[] input, int inOff, int len) { if ((inOff + len) > input.length) { throw new DataLengthException("input buffer too short"); } buffer.write(input, inOff, len); } @Override public int doFinal(byte[] output, int outOff) { if (32 + outOff > output.length) { throw new OutputLengthException("output buffer is too short"); } byte[] input = buffer.toByteArray(); int inlen = input.length; if (inlen == 0) { state[STATE_INBYTES - 1] ^= 1 << LAST_THREE_BITS_OFFSET; } else if (inlen <= INITIAL_RATE_INBYTES) { System.arraycopy(input, 0, state, 0, inlen); if (inlen < INITIAL_RATE_INBYTES) { state[inlen] ^= 0x01; // ozs } state[STATE_INBYTES - 1] ^= (inlen < INITIAL_RATE_INBYTES ? (byte)1 : (byte)2) << LAST_THREE_BITS_OFFSET; } else { System.arraycopy(input, 0, state, 0, INITIAL_RATE_INBYTES); inlen -= INITIAL_RATE_INBYTES; int Dlen_inblocks = (inlen + RATE_INBYTES - 1) / RATE_INBYTES; int i, LastDBlocklen; for (i = 0; i < Dlen_inblocks - 1; i++) { PHOTON_Permutation(); Bytes.xorTo(RATE_INBYTES, input, INITIAL_RATE_INBYTES + i * RATE_INBYTES, state, 0); } PHOTON_Permutation(); LastDBlocklen = inlen - i * RATE_INBYTES; Bytes.xorTo(LastDBlocklen, input, INITIAL_RATE_INBYTES + i * RATE_INBYTES, state, 0); if (LastDBlocklen < RATE_INBYTES) { state[LastDBlocklen] ^= 0x01; // ozs } state[STATE_INBYTES - 1] ^= (inlen % RATE_INBYTES == 0 ? (byte)1 : (byte)2) << LAST_THREE_BITS_OFFSET; } PHOTON_Permutation(); System.arraycopy(state, 0, output, outOff, SQUEEZE_RATE_INBYTES); PHOTON_Permutation(); System.arraycopy(state, 0, output, outOff + SQUEEZE_RATE_INBYTES, TAG_INBYTES - SQUEEZE_RATE_INBYTES); return TAG_INBYTES; } @Override public void reset() { buffer.reset(); Arrays.fill(state, (byte)0); } void PHOTON_Permutation() { int i, j, k, l; for (i = 0; i < DSquare; i++) { state_2d[i >>> Dq][i & Dr] = (byte)(((state[i >> 1] & 0xFF) >>> (4 * (i & 1))) & 0xf); } for (int round = 0; round < ROUND; round++) { //AddKey for (i = 0; i < D; i++) { state_2d[i][0] ^= RC[i][round]; } //SubCell for (i = 0; i < D; i++) { for (j = 0; j < D; j++) { state_2d[i][j] = sbox[state_2d[i][j]]; } } //ShiftRow for (i = 1; i < D; i++) { System.arraycopy(state_2d[i], 0, state, 0, D); System.arraycopy(state, i, state_2d[i], 0, D - i); System.arraycopy(state, 0, state_2d[i], D - i, i); } //MixColumn for (j = 0; j < D; j++) { for (i = 0; i < D; i++) { byte sum = 0; for (k = 0; k < D; k++) { int x = MixColMatrix[i][k], ret = 0, b = state_2d[k][j]; for (l = 0; l < S; l++) { if (((b >>> l) & 1) != 0) { ret ^= x; } if (((x >>> S_1) & 1) != 0) { x <<= 1; x ^= 0x3; } else { x <<= 1; } } sum ^= ret & 15; } state[i] = sum; } for (i = 0; i < D; i++) { state_2d[i][j] = state[i]; } } } for (i = 0; i < DSquare; i += 2) { state[i >>> 1] = (byte)(((state_2d[i >>> Dq][i & Dr] & 0xf)) | ((state_2d[i >>> Dq][(i + 1) & Dr] & 0xf) << 4)); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy