I'm currently implementing a chat program that lets the user choose between RC4 and TEA encryption. It's a partner assignment, and I have taken RC4. I've used the wikipedia page mostly, as well as our book (which the code I believe is the same as on the wikipedia page).
https://en.wikipedia.org/wiki/RC4
Going off of the code on there, I've changed it into Java. Note that my convertKey method will be taking in a key from a separate class which utilizes Diffie-Hellman to obtain the key (I have the key hard coded right now to ensure RC4 works as intended), but only my RC4 class is non-functional, so unless specifically requested (since the other classes work fine and this RC4 one doesn't use them currently) I will just paste the RC4 class to avoid wasted space.
STACK TRACE: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -24 at cryptochat2.RC4.PRGA(RC4.java:80) at cryptochat2.RC4.main(RC4.java:132) Java Result: 1 –
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package cryptochat2;
/**
*
* @author Braydon
*/
//Initialize array of 256 bytes
// Run KSA on them (key stream algorithm)
// Run PRGA on KSA to generate keystream
// XOR the data with the keystream
import java.util.Arrays;
import java.util.*;
import java.util.stream.IntStream;
// The interesting feature of RC4 is that the key can be of any length from 1 to 256
//bytes. And again, the key is only used to initialize the permutation S.
//Note that the 256-byte array K is filled by simply repeating the key until
//the array is full.
public class RC4 {
byte[] lookUpTable = new byte[256]; // S
byte[] key = new byte[256];
byte[] initializedKey = new byte[256]; // key
byte[] keyStream;
byte keyStreamByte;
boolean generatingOutput;
//int key;
int keylength = 256;
// Call KSA then PRGA
public void KSA() {
// uses identity permutation while also converting to bytes
// then must process S
for (int k = 0; k < 256; k++) {
lookUpTable[k] = (byte) k;
}
// now processing permutation of array
int j = 0;
int tempOne = 0;
int tempTwo = 0;
for (int k = 0; k < 256; k++) {
j = (j + lookUpTable[k] + initializedKey[k % keylength]) % 256;
// Switching S[i] and S[j]
byte tmp;
for (int i = 0; i < 256; i++) {
j = (j + lookUpTable[i] + initializedKey[i]) & 0xFF;
tmp = lookUpTable[j];
lookUpTable[j] = lookUpTable[i];
lookUpTable[i] = tmp;
}
}
}
//Error in PRGA-- arrayIndexOutOfBounds, value differs based on key but
// error remains the same. It's an issue with the following method.
public void PRGA() {
int i = 0;
int j = 0;
byte tmp;
boolean generatingOutput = true;
while (generatingOutput) {
i = (i + 1) % 256;
j = (j + lookUpTable[i]) % 256;
for (int k = 0; k < 256; k++) {
j = (j + lookUpTable[i] + initializedKey[i]) & 0xFF;
tmp = lookUpTable[j];
lookUpTable[j] = lookUpTable[i];
lookUpTable[i] = tmp;
}
int keyStreamByteTemp = ((lookUpTable[i] + lookUpTable[j]) % 256);
try {// error's in this part vvvvvv
keyStreamByte = lookUpTable[keyStreamByteTemp];
System.out.println("keystream byte: " + keyStreamByte);
} catch (IndexOutOfBoundsException exception){
System.out.println(keyStreamByte + " has given an exception");
}
}
}
public void convertKey(int key) {
// call this first. it gives us our key.
int nonByte = key;
byte bytedKey = (byte) key;
// We create an int array and from it we initialize our key byte array
int[] data = IntStream.generate(() -> bytedKey).limit(256).toArray();
for (int i = 0; i < 256; i++) {
initializedKey[i] = (byte) data[i];
}
keylength = numberOfLeadingZeros(key);
}
public static int numberOfLeadingZeros(int i) {
// http://stackoverflow.com/questions/2935793/count-bits-used-in-int
if (i == 0) {
return 32;
}
int n = 1;
if (i >>> 16 == 0) {
n += 16;
i <<= 16;
}
if (i >>> 24 == 0) {
n += 8;
i <<= 8;
}
if (i >>> 28 == 0) {
n += 4;
i <<= 4;
}
if (i >>> 30 == 0) {
n += 2;
i <<= 2;
}
n -= i >>> 31;
return n;
}
public static void main(String[] args) {
RC4 RC4 = new RC4();
// temp hard coded key
RC4.convertKey(16);
RC4.KSA();
RC4.PRGA();
}
}
While I have a general understanding of RC4, it's very possible that I have an element or two confused, or incorrect, or something like that. The try/catch block gives me an infinite loop (due to the generatingOutput boolean I'd imagine, and since we aren't passing in an actual message yet) of numbers, positive and negative, throwing IndexOutOfBounds exceptions, until I stop the program.
keystream byte: -53
keystream byte: 105
105 has given an exception
keystream byte: 6
6 has given an exception
keystream byte: -111
keystream byte: 73
73 has given an exception
keystream byte: 66
keystream byte: -86
keystream byte: -104
keystream byte: -114
keystream byte: -117
keystream byte: 56
keystream byte: 67
67 has given an exception
keystream byte: 121
keystream byte: 10
keystream byte: -7
keystream byte: 16
keystream byte: 103
103 has given an exception
keystream byte: -65
-65 has given an exception
keystream byte: 31
31 has given an exception
keystream byte: 21
I would really appreciate any help, I'd like to learn this well and not disappoint my professor or myself.