⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rc4.java

📁 cygwin 是一个在windows平台上运行的unix模拟环境
💻 JAVA
字号:
package net.propero.rdp.crypto;

/**    
 * This class implements the RC4 (TM) stream cipher.
 * <p>
 * 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" &lt;sterndark@netcom.com&gt;
 * (Message-ID: &lt;sternCvKL4B.Hyy@netcom.com&gt;)
 * <p>
 * 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.
 * <p>
 * <b>References:</b>
 * <ol>
 *   <li> Bruce Schneier,
 *        "Section 17.1 RC4,"
 *        <cite>Applied Cryptography, 2nd edition</cite>,
 *        John Wiley &amp; Sons, 1996.
 * </ol>
 * <p>
 * <b>Copyright</b> &copy; 1997
 * <a href="http://www.systemics.com/">Systemics Ltd</a> on behalf of the
 * <a href="http://www.systemics.com/docs/cryptix/">Cryptix Development Team</a>.
 * <br>All rights reserved.
 * <p>
 * <b>$Revision: 1.6 $</b>
 * @author  Raif S. Naffah
 * @author  David Hopwood
 * @since   Cryptix 2.2.2
 */
public final class RC4 { // must be final for security reasons

// 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 <code>initEncrypt</code>.
     *
     * @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 <code>initDecrypt</code>.
     *
     * @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 <i>implBuffering</i> false,
     * <i>implPadding</i> false and the provider set to "Cryptix".
     */
    public RC4() {
        //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
//............................................................................
    
    /**
     * <b>SPI</b>: 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; }

    /**
     * <b>SPI</b>: 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)
	throws CryptoException {
        makeKey(key);
	state = ENCRYPT;
    }

    /**
     * <b>SPI</b>: 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)
	throws CryptoException {
        makeKey(key);
	state = ENCRYPT;
    }

    /**
     * <b>SPI</b>: This is the main engine method for updating data.
     * <p>
     * <i>in</i> and <i>out</i> 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.
     * <p>
     * The key bytes are first extracted from the user-key and then
     * used to build the contents of this key schedule.
     * <p>
     * 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: <ul>
     *                <li> key.getEncoded() == null;
     *                <li> The encoded byte array form of the key is zero-length;
     *              </ul>
     */
    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 (<em>not</em> including
     * mode and padding).
     * <p>
     * See <a href="../guide/ijce/Algorithms.html#Cipher">
     * <cite>International JCE Standard Algorithm Names</cite></a> 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:
     * <p>
     * <dl>
     *   <dt> UNINITIALIZED
     *     <dd> The cipher has not been initialized. 
     *   <dt> ENCRYPT
     *     <dd> The cipher has been initialized for encryption. It may be
     *          used for encryption only.
     *   <dt> DECRYPT
     *     <dd> The cipher has been initialized for decryption. It may be
     *          used for decryption only.
     * </dl>
     *
     * @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);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -