FileDocCategorySizeDatePackage
ARC4.javaAPI DocphoneME MR2 API (J2ME)10860Wed May 02 18:00:00 BST 2007com.sun.midp.crypto

ARC4

public final class ARC4 extends Cipher
This class implements the ARCfour stream cipher

Fields Summary
private int
mode
Current cipher mode.
private SecretKey
ckey
Local certificate key.
private byte[]
S
Seed array.
private int[]
ii
First intermediate result array.
private int[]
jj
Second intermediate result array.
Constructors Summary
Methods Summary
public voidARC4()
Constructor for algorithm 3 (ALG_ARCFOUR)

    
              
       
	mode = Cipher.MODE_UNINITIALIZED;
	S = null;
	ii = null;
	jj = null;
    
public intdoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)
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 initialized.

The first inputLen bytes in the input buffer, starting at inputOffset inclusive, and any input bytes that may have been buffered during a previous update operation, are processed, with padding (if requested) being applied. The result is stored in the output buffer, starting at outputOffset inclusive.

If the output buffer is too small to hold the result, a ShortBufferException is thrown. In this case, repeat this call with a larger output buffer.

Upon finishing, this method resets this cipher object to the state it was in when previously initialized via a call to init. That is, the object is reset and available to encrypt or decrypt (depending on the operation mode that was specified in the call to init) more data.

Note: if any exception is thrown, this cipher object may need to be reset before it can be used again.

Note: this method should be copy-safe, which means the input and output buffers can reference the same byte array and no unprocessed input data is overwritten when the result is copied into the output buffer.

param
input the input buffer
param
inputOffset the offset in input where the input starts
param
inputLen the input length
param
output the buffer for the result
param
outputOffset the offset in output where the result is stored
return
the number of bytes stored in output
exception
IllegalStateException if this cipher is in a wrong state (e.g., has not been initialized)
exception
IllegalBlockSizeException if this cipher is a block cipher, no padding has been requested (only in encryption mode), and the total input length of the data processed by this cipher is not a multiple of block size
exception
ShortBufferException if the given output buffer is too small to hold the result
exception
BadPaddingException if this cipher is in decryption mode, and (un)padding has been requested, but the decrypted data is not bounded by the appropriate padding bytes

        int val = update(input, inputOffset, inputLen, output, outputOffset);

        try {
            init(mode, ckey);
        } catch (InvalidKeyException ike) {
            // ignore, the key was already checked
        }

        return val;
    
public voidinit(int opmode, Key key, CryptoParameter params)
Initializes the cipher's S-boxes based on the key. This code is based on the cipher's description in Bruce Schenier's "Applied Cryptography", Second Edition, pp 397-398, ISBN 0-471-11709-9

param
opmode the operation mode of this cipher (this is one of the following: ENCRYPT_MODE or DECRYPT_MODE)
param
key the encryption key
param
params the algorithm parameters
exception
InvalidKeyException if the given key is inappropriate for initializing this cipher, or its keysize exceeds the maximum allowable keysize.
exception
InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate for this cipher, or this cipher is being initialized for decryption and requires algorithm parameters and params is null, or the given algorithm parameters imply a cryptographic strength that would exceed the legal limits.
exception
IllegalArgumentException if the opmode is invalid


        if (!(key instanceof SecretKey)) {
            throw new InvalidKeyException();
        }

        if (opmode != Cipher.ENCRYPT_MODE && opmode != Cipher.DECRYPT_MODE) {
	    throw new IllegalArgumentException();
	}
	
	mode = opmode;
	ckey = (SecretKey)key;

	// Initialize the counters
        ii = new int[1];
        ii[0] = 0;
        jj = new int[1];
        jj[0] = 0;

	S = new byte[256];
	
        // Initialize S 
	for (int i = 0; i < 256; i++) {
            S[i] = (byte) i;
        }
    
	// Initilaize K based on the key
        byte[] K = new byte[256];
	int index = 0;
	while (index < 256) {
	    for (int i = 0; (i < ckey.secret.length) && (index < 256); i++) {
		K[index++] = ckey.secret[i];
	    }
	}

	// Populate the 8*8 S-box
	int j = 0;
	byte temp;
	for (int i = 0; i < 256; i++) {
	    j = (j + ((S[i] + K[i]) & 0xff)) & 0xff;
	    temp = S[i];
	    S[i] = S[j];
	    S[j] = temp;
	}
    
private static native voidnativetx(byte[] S, int[] X, int[] Y, byte[] inbuf, int inoff, int inlen, byte[] outbuf, int outoff)
Native function to transform a buffer.

param
S array of S box values
param
X first set intermediate results
param
Y second set of intermediate results
param
inbuf input buffer of data
param
inoff offset in the provided input buffer
param
inlen length of data to be processed
param
outbuf output buffer of data
param
outoff offset in the provided output buffer

protected voidsetChainingModeAndPadding(java.lang.String mode, java.lang.String padding)
Called by the factory method to set the mode and padding parameters. Need because Class.newInstance does not take args.

param
mode the mode parsed from the transformation parameter of getInstance and upper cased
param
padding the paddinge parsed from the transformation parameter of getInstance and upper cased
exception
NoSuchPaddingException if transformation contains a padding scheme that is not available
exception
IllegalArgumentException if the mode is invalid for the cipher


        if (!(mode.equals("") || mode.equals("NONE"))) {
            throw new IllegalArgumentException();
        }

        // NOPADDING is not an option.
        if (!(padding.equals("") || padding.equals("NOPADDING"))) {
            throw new NoSuchPaddingException();
        }
    
private inttransform(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff)
Transform a buffer of data,

param
inBuf input buffer of data
param
inOff offset in the provided input buffer
param
inLen length of data to be processed
param
outBuf output buffer of data
param
outOff offset in the provided output buffer
return
number of bytes copied to output buffer

        /*
	 * Normally, we would use something like:
	 * int test = inBuf[inOff] + inBuf[inLen - 1] + 
         *            inBuf[inOff + inLen - 1] + 
	 *             outBuf[outOff] + outBuf[outOff + inLen - 1];
	 * to force an array bounds check that might otherwise crash
	 * the VM. However, since we have such checks in the update
	 * method, we do not need them here.
	 */ 
	nativetx(S, ii, jj, inBuf, inOff, inLen, outBuf, outOff); 
	return inLen;
    
public intupdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)
Update the current data record.

param
input the input buffer
param
inputOffset the offset in input where the input starts
param
inputLen the input length
param
output the buffer for the result
param
outputOffset the offset in output where the result is stored
return
the number of bytes stored in output
exception
IllegalStateException if this cipher is in a wrong state (e.g., has not been initialized)
exception
ShortBufferException if the given output buffer is too small to hold the result


        Util.checkBounds(input, inputOffset, inputLen,
                         output, outputOffset);
	
	if (mode == Cipher.MODE_UNINITIALIZED) {
	    throw new IllegalStateException();
        }
	
	if (inputLen == 0) {
	    return 0;
        }    

        if (output.length - outputOffset < inputLen) {
            throw new ShortBufferException();
        }

	return transform(input, inputOffset, inputLen, output, outputOffset);