Skip to content

Instantly share code, notes, and snippets.

@fazlurr
Last active February 17, 2024 00:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fazlurr/1d2adcaa5d3d9b70d141 to your computer and use it in GitHub Desktop.
Save fazlurr/1d2adcaa5d3d9b70d141 to your computer and use it in GitHub Desktop.
import android.util.Log;
import java.util.Arrays;
/**
* RC4+ Encryption - from Stack Overflow
* Stack Overflow : http://stackoverflow.com/a/12290876
* Original Code : https://code.google.com/p/a9cipher/source/browse/src/com/a9development/a9cipher/RC4.java?r=1b5bdf2a70b3ef8cc9464f8a31332a2ec9f54e7a
*/
public class RC4Plus {
private static final String TAG = "RC4Plus";
private final byte[] S = new byte[256];
private final byte[] T = new byte[256];
private final int keyLength;
public RC4Plus(final byte[] key) {
if (key.length < 1 || key.length > 256) {
throw new IllegalArgumentException("key must be between 1 and 256 bytes");
} else {
keyLength = key.length;
/**
* Key-scheduling algorithm (KSA)
* The pseudo code :
* for i from 0 to 255
* S[i] := i
* endfor
* j := 0
* for i from 0 to 255
* j := (j + S[i] + key[i mod keylength]) mod 256
* swap values of S[i] and S[j]
* endfor
*/
for (int i = 0; i < 256; i++) {
S[i] = (byte) i;
T[i] = key[i % keyLength]; // key[i mod keylength]
}
int j = 0;
byte tmp;
for (int i = 0; i < 256; i++) {
j = (j + S[i] + T[i]) & 0xFF; // & 0xff is same as mod 256
// Swap values
tmp = S[j];
S[j] = S[i];
S[i] = tmp;
}
}
}
/**
* Pseudo-random generation algorithm (PRGA)
* The pseudo code :
* i := 0
* j := 0
* while GeneratingOutput:
* i := (i + 1) mod 256
* j := (j + S[i]) mod 256
* swap values of S[i] and S[j]
* K := S[(S[i] + S[j]) mod 256]
* output K
* endwhile
* @param plainTextBytes bytes from plain text
* @return cipherText
*/
public byte[] encrypt(final byte[] plainTextBytes) {
// For storing keystream, not required
byte[] keystreamByteArray = new byte[plainTextBytes.length];
final byte[] cipherText = new byte[plainTextBytes.length];
int i = 0, j = 0, k, t;
byte tmp;
for (int counter = 0; counter < plainTextBytes.length; counter++) {
i = (i + 1) & 0xFF;
j = (j + S[i]) & 0xFF;
// Swap values
tmp = S[j];
S[j] = S[i];
S[i] = tmp;
t = (S[i] + S[j]) & 0xFF;
k = S[t];
// The S(S(i) + S(j)) is used as a byte of the key stream, K
cipherText[counter] = (byte) (plainTextBytes[counter] ^ k); // '^' is XOR
// Not required for encryption, only for showing keystream hexadecimal
keystreamByteArray[counter] = ((byte) k);
}
String hexadecimalKeystream = A9Utility.bytesToHex(keystreamByteArray);
Log.i(TAG, "Keystream in bytes : " + Arrays.toString(keystreamByteArray));
Log.i(TAG, "Keystream in hexadecimal : " + hexadecimalKeystream);
String hexadecimalCiphertext = A9Utility.bytesToHex(cipherText);
Log.i(TAG, "Ciphertext in bytes : " + Arrays.toString(cipherText));
Log.i(TAG, "Ciphertext in hexadecimal : " + hexadecimalCiphertext);
return cipherText;
}
public byte[] decrypt(final byte[] cipherText) {
return encrypt(cipherText);
}
}
@naldi28
Copy link

naldi28 commented Sep 15, 2017

I have error in A9Utility and log.i, please help me

String hexadecimalKeystream = A9Utility.bytesToHex(keystreamByteArray);
Log.i(TAG, "Keystream in bytes : " + Arrays.toString(keystreamByteArray));
Log.i(TAG, "Keystream in hexadecimal : " + hexadecimalKeystream);

@uzuki-P
Copy link

uzuki-P commented Sep 15, 2017

@naldi28

Got this from the source:

public static String bytesToHex(byte[] b) {
	String s = "";
	for (int i = 0; i < b.length; i++) {
		if (i > 0 && i % 4 == 0) {
			s += " ";
		}
		s += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
	}
	return s;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment