📄 rc4.java
字号:
package au.net.aba.crypto.provider;
/*
* $Id: RC4.java,v 1.18 1999/01/18 05:52:02 leachbj Exp $
* $Author: leachbj $
*
* Copyright (C) 1996-1998 Australian Business Access Pty Ltd.
* All rights reserved.
*
* Use, modification, copying and distribution of this software is subject the
* terms and conditions of the ABA Public Licence. See the file
* "PUBLIC_LICENCE" for additional information.
*
* If you have not received a copy of the Public Licence, you must destroy all
* copies of this file immediately.
*
* $Source: /aba/CVSROOT/jdk1.1/src/au.net.aba/crypto/provider/RC4.java,v $
* $Revision: 1.18 $
* $Date: 1999/01/18 05:52:02 $
* $State: Exp $
*/
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.spec.*;
/**
* A class that provides RC4 stream encryption.
*/
public class RC4 extends CipherSpi
{
public final static String ident = "$Id: RC4.java,v 1.18 1999/01/18 05:52:02 leachbj Exp $";
//==================================
// Private Implementation
//==================================
private static final int CONTEXT_LENGTH = 256;
/*
* The internal state of the RC4 algorithm.
*/
private short[] state = null;
private short x;
private short y;
/**
* Encrypt the specified byte and return the encrypted byte.
*
* @param plainText The plain text data.
* @return The encrypted data.
*/
public synchronized byte cipher(
byte plainText)
{
// internal to this method, we use chars to perform
// the ciphering, since these are unsigned values and
// therefore not subject to the weirdness of sign extension.
int xorIndex;
int _x = x;
int _y = y;
_x = (_x + 1) % CONTEXT_LENGTH;
_y = (state[_x] + _y) % CONTEXT_LENGTH;
short tmp = state[_x];
state[_x] = state[_y];
state[_y] = tmp;
xorIndex = (state[_x] + state[_y]) % CONTEXT_LENGTH;
x = (short)_x;
y = (short)_y;
return (byte)((plainText ^ state[xorIndex]) & 0xff);
}
/**
* Encrypts or decrypts data in a single-part operation, or finishes
* a multiple-part operation. The data is encrypted or decrypted,
* depending on how this cipher was initialised.
*
* @param in the data to be processed.
* @param inOff the offset in the in array that processing should start
* from.
* @param inLen the number of bytes of data to be processed.
* @return the resulting data (null if there isn't enough).
*/
protected byte[] engineDoFinal(
byte[] in,
int inOff,
int inLen)
{
return engineUpdate(in, inOff, inLen);
}
/**
* Encrypts or decrypts data in a single-part operation, or finishes
* a multiple-part operation.
*
* @param in the data to be processed.
* @param inOff the offset in the in array that processing
* should start from.
* @param inLen the number of bytes of data to be processed.
* @param out the array that the output is to be put into.
* @param outOff the offset in the out array that processed data
* should start being written at.
* @return the number of bytes that were output to the out array.
* @exception ShortBufferException The provided output buffer
* is too small for the decrypted result.
*/
protected int engineDoFinal(
byte[] in,
int inOff,
int inLen,
byte[] out,
int outOff)
throws ShortBufferException
{
return engineUpdate(in, inOff, inLen, out, outOff);
}
/**
* Returns the block size (in bytes).
*
* @return the block size (in bytes), or 0 if the underlying algorithm
* is not a block cipher
*/
protected int engineGetBlockSize()
{
return 1;
}
/**
* Returns the initialisation vector for this Cipher - in this case null
*
* @return null
*/
protected byte[] engineGetIV()
{
return null;
}
/**
* Returns the length in bytes that an output buffer would need to be
* in order to hold the result of the next update or doFinal operation,
* given the input length inputLen (in bytes).
*
* @param inputLen the length of bytes we are planning to input.
* @return the output size for input bytes plus what is in the buffer.
*/
protected int engineGetOutputSize(
int inputLen)
{
return inputLen;
}
/**
* Returns the parameters used with this cipher.
*
* @return the algorithm parameters.
*/
protected AlgorithmParameters engineGetParameters()
{
return null;
}
/**
* Initialises this cipher with a key and a source of randomness,
* using the AlgorithmParameters construct.
*
* @param opMode the cipher mode.
* @param key the key to be used.
* @param params the algorithm parameters to be used.
* @param rand the random number generator to be used.
* @exception InvalidKeyException if the key is of the wrong type.
*/
protected void engineInit(
int opMode,
Key key,
AlgorithmParameters params,
SecureRandom rand)
throws InvalidKeyException
{
state = new short[CONTEXT_LENGTH];
if (!((key instanceof RC4Key)
|| (key instanceof SecretKeySpec)))
{
throw new InvalidKeyException("not a RC4 Key");
}
prepare(key.getEncoded());
}
/**
* Initialises this cipher with a key and a source of randomness.
*
* @param opMode the cipher mode.
* @param key the key to be used.
* @param rand the random number generator to be used.
* @exception InvalidKeyException if the key is of the wrong type.
*/
protected void engineInit(
int opMode,
Key key,
SecureRandom rand)
throws InvalidKeyException
{
engineInit(opMode, key, (AlgorithmParameterSpec)null, rand);
}
/**
* Initialises this cipher with a key and a source of randomness.
*
* @param opMode the cipher mode.
* @param key the key to be used.
* @param params the parameter spec to be used.
* @param rand the random number generator to be used.
* @exception InvalidKeyException if the key is of the wrong type.
*/
protected void engineInit(
int opMode,
Key key,
AlgorithmParameterSpec params,
SecureRandom rand)
throws InvalidKeyException
{
state = new short[CONTEXT_LENGTH];
if (!((key instanceof RC4Key)
|| (key instanceof SecretKeySpec)))
{
throw new InvalidKeyException("not a RC4 Key");
}
prepare(key.getEncoded());
}
/**
* Sets the mode of this cipher. Not applicable.
*
* @param mode the mode we want.
*/
public void engineSetMode(
String mode)
throws NoSuchAlgorithmException
{
throw new NoSuchAlgorithmException("RC4 does not support " + mode);
}
/**
* Sets the padding mechanism of this cipher. Not applicable.
*
* @param padding the type of padding we want.
*/
public void engineSetPadding(
String padding)
throws NoSuchPaddingException
{
throw new NoSuchPaddingException("RC4 does not support " + padding);
}
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialised), processing another
* data part. Returns null if cipher didn't receive enough data.
*
* @param in the data to be processed.
* @param inOff the offset in the in array that processing should start
* from.
* @param inLen the number of bytes of data to be processed.
* @return the resulting data (null if more is required).
*/
protected byte[] engineUpdate(
byte[] in,
int inOff,
int inLen)
{
byte[] tmp;
tmp = new byte[inLen];
for (int i = 0; i < inLen; i++)
{
tmp[i] = cipher(in[i + inOff]);
}
return tmp;
}
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialised), processing another
* data part.
*
* @param in the data to be processed.
* @param inOff the offset in the in array that processing
* should start from.
* @param inLen the number of bytes of data to be processed.
* @param out the array that the output is to be put into.
* @param outOff the offset in the out array that processed data
* should start being written at.
* @return the number of bytes that were output to the out array.
* @exception ShortBufferException The provided output buffer is
* too short.
*/
protected int engineUpdate(
byte[] in,
int inOff,
int inLen,
byte[] out,
int outOff)
throws ShortBufferException
{
/*
* Make sure output buffer is long enough
*/
if ((outOff + inLen) > out.length)
{
throw new ShortBufferException(
"Output buffer too short.");
}
for (int i = 0; i < inLen; i++)
{
out[i + outOff] = cipher(in[i + inOff]);
}
return inLen;
}
/*
* Initialise the internal state of the RC4 algorithm
* from the specified key data.
*
* @param data The bytes to initialise the state from.
*/
private synchronized void prepare(byte[] data)
{
int index1 = 0;
int index2 = 0;
x = 0;
y = 0;
for (short i = 0; i < state.length; i++)
{
state[i] = i;
}
for (int i = 0; i < state.length; i++)
{
index2 = (((int)data[index1] & 0xff)
+ state[i] + index2) % CONTEXT_LENGTH;
short tmp = state[i];
state[i] = state[index2];
state[index2] = tmp;
index1 = (index1 + 1) % data.length;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -