0

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.

  • When you get an exception you also get a stacktrace. Copy and paste that stacktrace into your question. – President James K. Polk Nov 29 '16 at 19:00
  • 1
    Note that `x%y` will have the sign of `x`, so if `x` is negative then so will `x%y`. This affects things like `int keyStreamByteTemp = ((lookUpTable[i] + lookUpTable[j]) % 256);` due to Java's integral promotion rules and the fact that `byte` is a signed type. There are several ways to deal with this, one of the simplest being to replace `% 256` with `& 0xff` everywhere. – President James K. Polk Nov 29 '16 at 19:06
  • Thanks James-- is this what you meant by the stacktrace? Also thank you for that tip, I'll go through and replace %256 with & 0xff. 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 – Braydon Rekart Nov 29 '16 at 19:18
  • After implementing your tip, there is no exceptions given anymore, thank you. (I had forgot I removed the test code, but added it back in, and still no exceptions in sight!) I wonder what your opinion on the negative keystream bytes is? I was thinking of just switching the respective number's sign if it's a negative, then XORing that with a plaintext character, instead of leaving it negative. – Braydon Rekart Nov 30 '16 at 17:37
  • You can do the same trick, `& 0xFF` to convert it to a positive *integer* (instead of a byte), or you could print them out in hexadecimals (format string `"%02X"` instead of decimals. You're using the key stream to XOR, so a presentation closer to bits makes more sense. – Maarten Bodewes Nov 30 '16 at 23:52

0 Answers0