All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rzo.netty.ahessian.crypto.RC4Cipher Maven / Gradle / Ivy

package org.rzo.netty.ahessian.crypto;

import java.util.Arrays;

/** 
 * Taken from the cryptix project   
 * This class implements the RC4 (TM) stream cipher.
 * 

* The source code (C version) from which this port was done, is the one * posted to the sci.crypt, alt.security, comp.security.misc, and * alt.privacy newsgroups on Wed, 14 Sep 1994 06:35:31 GMT by * "David Sterndark" <[email protected]> * (Message-ID: <[email protected]>) *

* RC4 (TM) was designed by Ron Rivest, and was previously a trade secret of * RSA Data Security, Inc. The algorithm is now in the public domain. The name * "RC4" is a trademark of RSA Data Security, Inc. *

* References: *

    *
  1. Bruce Schneier, * "Section 17.1 RC4," * Applied Cryptography, 2nd edition, * John Wiley & Sons, 1996. *
*

* Copyright © 1997 * Systemics Ltd on behalf of the * Cryptix Development Team. *
All rights reserved. *

* $Revision: 1.6 $ * @author Raif S. Naffah * @author David Hopwood * @since Cryptix 2.2.2 */ public class RC4Cipher implements StreamCipher { // RC4 constants and variables //............................................................................ /** * The state of the cipher object when it is uninitialized, * that is, the state it is in right after it has been created. */ public static final int UNINITIALIZED = 0; /** * The state of the cipher when it is ready to encrypt, that is, * the state it is in right after a call to initEncrypt. * * @see #initEncrypt */ public static final int ENCRYPT = 1; /** * The state of the cipher when it is ready to decrypt, that is, * the state it is in right after a call to initDecrypt. * * @see #initDecrypt */ public static final int DECRYPT = 2; /** * Will hold the contents of the current set S-box. */ private int[] sBox = new int[256]; /** * The two indices for the S-box computation referred to as i and j * in Schneier. */ private int x, y; /** * The block size of this cipher. Being a stream cipher this value * is 1! */ private static final int BLOCK_SIZE = 1; private int state; // defaults to UNINITIALIZED = 0 private String cipherName = "RC4"; // Constructor, finalizer, and clone() //............................................................................ /** * Constructs an RC4 cipher object, in the UNINITIALIZED state. * This calls the Cipher constructor with implBuffering false, * implPadding false and the provider set to "Cryptix". */ public RC4Cipher() { //super(false, false, "Cryptix"); } /** * Always throws a CloneNotSupportedException (cloning of ciphers is not * supported for security reasons). */ public final Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } // Implementation of JCE methods //............................................................................ /** * SPI: Returns the length of an input block, in bytes. * * @return the length in bytes of an input block for this cipher. */ public int engineBlockSize() { return BLOCK_SIZE; } /** * SPI: Initializes this cipher for encryption, using the * specified key. * * @param key the key to use for encryption. * @exception CryptoException if the key is invalid. */ public void engineInitEncrypt(byte[] key, byte[] iv) throws CryptoException { makeKey(key); state = ENCRYPT; } /** * SPI: Initializes this cipher for decryption, using the * specified key. * * @param key the key to use for decryption. * @exception CryptoException if the key is invalid. */ public void engineInitDecrypt(byte[] key, byte[] iv) throws CryptoException { makeKey(key); state = ENCRYPT; } /** * SPI: This is the main engine method for updating data. *

* in and out may be the same array, and the input and output * regions may overlap. * * @param in the input data. * @param inOffset the offset into in specifying where the data starts. * @param inLen the length of the subarray. * @param out the output array. * @param outOffset the offset indicating where to start writing into * the out array. * @return the number of bytes written. * reports an error. */ protected int engineUpdate(byte[] in, int inOffset, int inLen, byte[] out, int outOffset) { if (inLen < 0) throw new IllegalArgumentException("inLen < 0"); boolean doEncrypt = (getState() == ENCRYPT); // Avoid overlapping input and output regions. if (in == out && (outOffset >= inOffset && outOffset < inOffset + inLen || inOffset >= outOffset && inOffset < outOffset + inLen)) { byte[] newin = new byte[inLen]; System.arraycopy(in, inOffset, newin, 0, inLen); in = newin; inOffset = 0; } rc4(in, inOffset, inLen, out, outOffset); return inLen; } // Own methods //............................................................................ /** * RC4 encryption/decryption. The input and output regions are assumed not to * overlap. * * @param in the input data. * @param inOffset the offset into in specifying where the data starts. * @param inLen the length of the subarray. * @param out the output array. * @param outOffset the offset indicating where to start writing into * the out array. */ private void rc4(byte[] in, int inOffset, int inLen, byte[] out, int outOffset) { int xorIndex, t; for (int i = 0; i < inLen; i++) { x = (x + 1) & 0xFF; y = (sBox[x] + y) & 0xFF; t = sBox[x]; sBox[x] = sBox[y]; sBox[y] = t; xorIndex = (sBox[x] + sBox[y]) & 0xFF; out[outOffset++] = (byte) (in[inOffset++] ^ sBox[xorIndex]); } } /** * Expands a user-key to a working key schedule. *

* The key bytes are first extracted from the user-key and then * used to build the contents of this key schedule. *

* The method's only exceptions are when the user-key's contents * are null, or a byte array of zero length. * * @param key the user-key object to use. * @exception CryptoException if one of the following occurs:

    *
  • key.getEncoded() == null; *
  • The encoded byte array form of the key is zero-length; *
*/ private void makeKey(byte[] userkey) throws CryptoException { if (userkey == null) throw new CryptoException(getAlgorithm() + ": Null user key"); int len = userkey.length; if (len == 0) throw new CryptoException(getAlgorithm() + ": Invalid user key length"); x = y = 0; for (int i = 0; i < 256; i++) sBox[i] = i; int i1 = 0, i2 = 0, t; for (int i = 0; i < 256; i++) { i2 = ((userkey[i1] & 0xFF) + sBox[i] + i2) & 0xFF; t = sBox[i]; sBox[i] = sBox[i2]; sBox[i2] = t; i1 = (i1 + 1) % len; } } /** * Returns this algorithm's standard cipher name (not including * mode and padding). *

* See * International JCE Standard Algorithm Names for a list * of Cipher algorithm names. * * @return the standard cipher name (such as "DES"). */ public final String getAlgorithm() { return cipherName; } /** * Returns the state of this Cipher object. Possible states are: *

*

*
UNINITIALIZED *
The cipher has not been initialized. *
ENCRYPT *
The cipher has been initialized for encryption. It may be * used for encryption only. *
DECRYPT *
The cipher has been initialized for decryption. It may be * used for decryption only. *
* * @return the state of this cipher object. * * @see #UNINITIALIZED * @see #ENCRYPT * @see #DECRYPT */ public final int getState() { return state; } public final byte[] crypt(byte[] data, int position, int length) { byte[] buffer = new byte[length]; engineUpdate(data, position, length, buffer, 0); return buffer; } public final byte[] crypt(byte[] data) { byte[] buffer = new byte[data.length]; engineUpdate(data, 0, data.length, buffer, 0); return buffer; } public final void crypt(byte[] in, int in_offset, int length, byte[] out, int out_offset) { engineUpdate(in, in_offset, length, out, out_offset); } public static void main(String[] args) throws Exception { byte[] iv = new byte[CryptoConstants.SYM_IV_SIZE]; byte[] key = new byte[CryptoConstants.SYM_KEY_SIZE]; StreamCipher eCipher = StreamCipherFactory.createCipher("RC4"); StreamCipher dCipher = StreamCipherFactory.createCipher("RC4"); eCipher.engineInitEncrypt(key, iv); dCipher.engineInitDecrypt(key, iv); byte[] msg = "this is a secret message".getBytes(); byte[] cMsg; byte[] eMsg = new byte[0]; long t = System.currentTimeMillis(); for (int i=0; i<1000000; i++) { cMsg = eCipher.crypt(msg, 0, msg.length); eMsg = dCipher.crypt(cMsg, 0, cMsg.length); } System.out.println(System.currentTimeMillis() - t); if (!Arrays.equals(msg, eMsg)) System.out.println("error"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy