org.bouncycastle.crypto.engines.RC4Engine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcprov-ext-debug-jdk18on Show documentation
Show all versions of bcprov-ext-debug-jdk18on Show documentation
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 Java 1.8 and later with debug enabled.
The newest version!
package org.bouncycastle.crypto.engines;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.constraints.DefaultServiceProperties;
import org.bouncycastle.crypto.params.KeyParameter;
public class RC4Engine
implements StreamCipher
{
private final static int STATE_LENGTH = 256;
/*
* variables to hold the state of the RC4 engine
* during encryption and decryption
*/
private byte[] engineState = null;
private int x = 0;
private int y = 0;
private byte[] workingKey = null;
private boolean forEncryption;
public RC4Engine()
{
CryptoServicesRegistrar.checkConstraints(new DefaultServiceProperties(getAlgorithmName(), 20));
}
/**
* initialise a RC4 cipher.
*
* @param forEncryption whether or not we are for encryption.
* @param params the parameters required to set up the cipher.
* @exception IllegalArgumentException if the params argument is
* inappropriate.
*/
public void init(
boolean forEncryption,
CipherParameters params)
{
if (params instanceof KeyParameter)
{
/*
* RC4 encryption and decryption is completely
* symmetrical, so the 'forEncryption' is
* irrelevant.
*/
this.workingKey = ((KeyParameter)params).getKey();
this.forEncryption = forEncryption;
setKey(workingKey);
CryptoServicesRegistrar.checkConstraints(new DefaultServiceProperties(getAlgorithmName(), 20, params, Utils.getPurpose(forEncryption)));
return;
}
throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());
}
public String getAlgorithmName()
{
return "RC4";
}
public byte returnByte(byte in)
{
x = (x + 1) & 0xff;
y = (engineState[x] + y) & 0xff;
// swap
byte tmp = engineState[x];
engineState[x] = engineState[y];
engineState[y] = tmp;
// xor
return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
}
public int processBytes(
byte[] in,
int inOff,
int len,
byte[] out,
int outOff)
{
if ((inOff + len) > in.length)
{
throw new DataLengthException("input buffer too short");
}
if ((outOff + len) > out.length)
{
throw new OutputLengthException("output buffer too short");
}
for (int i = 0; i < len ; i++)
{
x = (x + 1) & 0xff;
y = (engineState[x] + y) & 0xff;
// swap
byte tmp = engineState[x];
engineState[x] = engineState[y];
engineState[y] = tmp;
// xor
out[i+outOff] = (byte)(in[i + inOff]
^ engineState[(engineState[x] + engineState[y]) & 0xff]);
}
return len;
}
public void reset()
{
setKey(workingKey);
}
// Private implementation
private void setKey(byte[] keyBytes)
{
workingKey = keyBytes;
// System.out.println("the key length is ; "+ workingKey.length);
x = 0;
y = 0;
if (engineState == null)
{
engineState = new byte[STATE_LENGTH];
}
// reset the state of the engine
for (int i=0; i < STATE_LENGTH; i++)
{
engineState[i] = (byte)i;
}
int i1 = 0;
int i2 = 0;
for (int i=0; i < STATE_LENGTH; i++)
{
i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
// do the byte-swap inline
byte tmp = engineState[i];
engineState[i] = engineState[i2];
engineState[i2] = tmp;
i1 = (i1+1) % keyBytes.length;
}
}
}