Created
October 23, 2014 06:06
-
-
Save hakatashi/3d3351cec8c509d5097c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.util.Arrays; | |
| import edu.rit.util.Hex; | |
| import edu.rit.util.Packing; | |
| public class FEALCipher implements BlockCipher { | |
| //Set up parameters and default values | |
| public int R = 8; | |
| byte deltaParam = 0; | |
| int numOfSubKeys = (this.R + 8); | |
| short[] subKey = new short[numOfSubKeys]; | |
| //Returns the block size of FEAL in bytes | |
| public int blockSize() { | |
| return 8; | |
| } | |
| //Returns the key size in Bytes | |
| public int keySize() { | |
| return 8; | |
| } | |
| //Function to set the number of rounds. This is used in our attack | |
| //It also sets up the appropriate number of subkeys which need to be generated | |
| public void setRounds(int R) { | |
| this.R = R; | |
| this.numOfSubKeys = (this.R + 8); | |
| this.subKey = new short[numOfSubKeys]; | |
| } | |
| //Method to access the subkeys used in the encryption process | |
| public short[] getSubKeys() { | |
| return subKey; | |
| } | |
| //Method to set the key and extend keys to get the subkeys | |
| //Takes in a 64-bit key | |
| //Extends it based on how many rounds are needed | |
| //Makes use of the FK function to generate the key | |
| public void setKey(byte[] key) { | |
| //Set up the necessary parameters to extend the key using the Fiestel rounds | |
| int roundsLimit = ((this.R + 8) / 2) + 1; | |
| int[] A = new int[roundsLimit + 1]; // Left part of the 64 bits Key (MSB) | |
| int[] B = new int[roundsLimit + 1]; // Right part of the 64 bits Key (LSB) | |
| int[] D = new int[roundsLimit + 1]; // Result from functionFK | |
| int fkOutput = 0; | |
| // Spliting the 64 bits key into two 32 bits ints (A and B) to pass those to functionFK | |
| A[0] = A[0] |= ((key[0] & 255) << 24); | |
| A[0] = A[0] |= ((key[1] & 255) << 16); | |
| A[0] = A[0] |= ((key[2] & 255) << 8); | |
| A[0] = A[0] |= (key[3] & 255); | |
| B[0] = B[0] |= ((key[4] & 255) << 24); | |
| B[0] = B[0] |= ((key[5] & 255) << 16); | |
| B[0] = B[0] |= ((key[6] & 255) << 8); | |
| B[0] = B[0] |= (key[7] & 255); | |
| // Getting the subkeys: Using the key schedule | |
| for (int r = 1; r < (roundsLimit); r++) { | |
| D[r] = A[r - 1]; | |
| A[r] = B[r - 1]; | |
| B[r] = functionFK(A[r - 1], (B[r - 1] ^ D[r - 1])); | |
| subKey[2 * (r - 1)] = (short)(B[r] >> 16); | |
| subKey[(2 * (r - 1) + 1)] = (short) B[r]; | |
| } | |
| //Checks to see final case if our R is odd. We need an extra key than what is normally used | |
| if (this.R % 2 == 1) { | |
| D[roundsLimit] = A[roundsLimit - 1]; | |
| A[roundsLimit] = B[roundsLimit - 1]; | |
| B[roundsLimit] = functionFK(A[roundsLimit - 1], (B[roundsLimit - 1] ^ D[roundsLimit - 1])); | |
| subKey[2 * (roundsLimit - 1)] = (short)(B[roundsLimit] >> 16); | |
| } | |
| } | |
| //Method for encrypting a single plaintext block of 64 bits | |
| public void encrypt(byte[] text) { | |
| //Set up side Arrays | |
| int[] RightArray = new int[R + 2]; | |
| int[] LeftArray = new int[R + 2]; | |
| //Pack text into Right and Left 32-bit integers | |
| LeftArray[0] |= ((text[0] & 255) << 24); | |
| LeftArray[0] |= ((text[1] & 255) << 16); | |
| LeftArray[0] |= ((text[2] & 255) << 8); | |
| LeftArray[0] |= (text[3] & 255); | |
| RightArray[0] |= ((text[4] & 255) << 24); | |
| RightArray[0] |= ((text[5] & 255) << 16); | |
| RightArray[0] |= ((text[6] & 255) << 8); | |
| RightArray[0] |= (text[7] & 255); | |
| //Set up the initial keys for use | |
| int leftInitKey = 0; | |
| int rightInitKey = 0; | |
| leftInitKey |= ((subKey[R] & 65535) << 16); | |
| leftInitKey |= ((subKey[R + 1] & 65535)); | |
| rightInitKey |= ((subKey[R + 2] & 65535) << 16); | |
| rightInitKey |= ((subKey[R + 3] & 65535)); | |
| LeftArray[0] = LeftArray[0] ^ leftInitKey; | |
| RightArray[0] = RightArray[0] ^ rightInitKey; | |
| //Initial xor | |
| RightArray[0] = RightArray[0] ^ LeftArray[0]; | |
| //Feistel rounds | |
| for (int i = 1; i <= R; i++) { | |
| RightArray[i] = LeftArray[i - 1] ^ functionF(RightArray[i - 1], subKey[i - 1]); | |
| LeftArray[i] = RightArray[i - 1]; | |
| } | |
| //Final xor of he left and right sides | |
| LeftArray[R + 1] = LeftArray[R] ^ RightArray[R]; | |
| RightArray[R + 1] = RightArray[R]; | |
| //Set up final keys for xor | |
| int leftFinalKey = 0; | |
| int rightFinalKey = 0; | |
| rightFinalKey |= ((subKey[R + 4] & 65535) << 16); | |
| rightFinalKey |= ((subKey[R + 5] & 65535)); | |
| leftFinalKey |= ((subKey[R + 6] & 65535) << 16); | |
| leftFinalKey |= ((subKey[R + 7] & 65535)); | |
| //Xor the last subkeys | |
| LeftArray[R + 1] = LeftArray[R + 1] ^ leftFinalKey; | |
| RightArray[R + 1] = RightArray[R + 1] ^ rightFinalKey; | |
| //pack the results back into the encryption array | |
| for (int i = 3; i >= 0; i--) { | |
| text[i] = (byte) RightArray[R + 1]; | |
| RightArray[R + 1] = RightArray[R + 1] >>> 8; | |
| } | |
| for (int i = 7; i >= 4; i--) { | |
| text[i] = (byte) LeftArray[R + 1]; | |
| LeftArray[R + 1] = LeftArray[R + 1] >>> 8; | |
| } | |
| } | |
| //Function F used for encryption | |
| //Inputs: A, B, where A is the plaintext and B is the subkey | |
| private int functionF(int A, short B) { | |
| //set up and pack int and short inputs into byte arrays for convinence and set up a output array | |
| byte[] subA = new byte[4]; | |
| byte[] subB = new byte[2]; | |
| subA[0] = (byte)(A >>> 24); | |
| subA[1] = (byte)(A >>> 16); | |
| subA[2] = (byte)(A >>> 8); | |
| subA[3] = (byte)(A >>> 0); | |
| subB[0] = (byte)(B >>> 8); | |
| subB[1] = (byte)(B >>> 0); | |
| byte[] fOut = new byte[4]; | |
| //Do some initial xoring | |
| fOut[1] = (byte)((subA[1] & 255) ^ (subB[0] & 255) ^ (subA[0] & 255)); | |
| fOut[2] = (byte)((subA[2] & 255) ^ (subB[1] & 255) ^ (subA[3] & 255)); | |
| //Call the S function given a particular path through the Function | |
| fOut[1] = functionS(fOut[1], fOut[2], (byte) 1); | |
| fOut[2] = functionS(fOut[2], fOut[1], (byte) 0); | |
| fOut[0] = functionS(subA[0], fOut[1], (byte) 0); | |
| fOut[3] = functionS(subA[3], fOut[2], (byte) 1); | |
| //Set up and pack the result into an output integer | |
| int output = 0; | |
| output |= (fOut[0] & 255); | |
| output = output << 8; | |
| output |= (fOut[1] & 255); | |
| output = output << 8; | |
| output |= (fOut[2] & 255); | |
| output = output << 8; | |
| output |= (fOut[3] & 255); | |
| return output; | |
| } | |
| //Function FK which is used in the key generation phase | |
| //Inputs: A and B which are both 32-bit integers | |
| private int functionFK(int A, int B) { | |
| //Set up substitute bytes and pack in the two inputs | |
| byte[] subA = new byte[4]; | |
| byte[] subB = new byte[4]; | |
| subA[0] = (byte)(A >>> 24); | |
| subA[1] = (byte)(A >>> 16); | |
| subA[2] = (byte)(A >>> 8); | |
| subA[3] = (byte)(A >>> 0); | |
| subB[0] = (byte)(B >>> 24); | |
| subB[1] = (byte)(B >>> 16); | |
| subB[2] = (byte)(B >>> 8); | |
| subB[3] = (byte)(B >>> 0); | |
| //Set up the output byte array for convinence | |
| byte[] fKOut = new byte[4]; | |
| fKOut[1] = (byte)((subA[1] & 255) ^ (subA[0] & 255)); | |
| fKOut[2] = (byte)((subA[2] & 255) ^ (subA[3] & 255)); | |
| //Do the appropriate xor functions | |
| fKOut[1] = functionS(fKOut[1], (byte)((fKOut[2] & 255) ^ (subB[0] & 255)), (byte) 1); | |
| fKOut[2] = functionS(fKOut[2], (byte)((fKOut[1] & 255) ^ (subB[1] & 255)), (byte) 0); | |
| fKOut[0] = functionS(subA[0], (byte)((fKOut[1] & 255) ^ (subB[2] & 255)), (byte) 0); | |
| fKOut[3] = functionS(subA[3], (byte)((fKOut[2] & 255) ^ (subB[3] & 255)), (byte) 1); | |
| //Pack the output into an integer | |
| int output = 0; | |
| output |= (fKOut[0] & 255); | |
| output = output << 8; | |
| output |= (fKOut[1] & 255); | |
| output = output << 8; | |
| output |= (fKOut[2] & 255); | |
| output = output << 8; | |
| output |= (fKOut[3] & 255); | |
| return output; | |
| } | |
| //S Function used in both F and FK | |
| //Takes in 2 bytes and a 1 or zero for delta. | |
| //Sums them then mods by 256 and left rotates by 2 | |
| private byte functionS(byte A, byte B, byte delta) { | |
| //Sum inputs | |
| byte T = (byte)(((A & 255) + (B & 255) + (delta & 255)) % 256); | |
| //Left Rotate by 2 | |
| return (byte)(((T & 255) << (byte) 2) | ((T & 255) >>> (byte) 6)); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment