rc4.java

来自「jpeg2000编解码」· Java 代码 · 共 456 行 · 第 1/2 页

JAVA
456
字号
//............................................................................    /**     * 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;// 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");    }    /**     * Cleans up resources used by this instance, if necessary.     */    protected final void finalize() {        if (native_lock != null) {            synchronized(native_lock) {                String error = native_finalize(); // may be called more than once                if (error != null)                    debug(error + " in native_finalize");            }        }    }    /**     * 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 InvalidKeyException if the key is invalid.     */    public void engineInitEncrypt(Key key)    throws InvalidKeyException {        makeKey(key);    }    /**     * <b>SPI</b>: Initializes this cipher for decryption, using the     * specified key.     *     * @param  key  the key to use for decryption.     * @exception InvalidKeyException if the key is invalid.     */    public void engineInitDecrypt(Key key)    throws InvalidKeyException {        makeKey(key);    }    /**     * <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.     * @exception CryptixException if the native library is being used, and it     *                      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 < (long)inOffset+inLen ||                          inOffset >= outOffset && inOffset < (long)outOffset+inLen)) {            byte[] newin = new byte[inLen];            System.arraycopy(in, inOffset, newin, 0, inLen);            in = newin;            inOffset = 0;        }        if (native_lock != null) {            synchronized(native_lock) {                // If in == null || out == 0, evaluating their lengths will throw a                // NullPointerException.                if (inOffset < 0 || (long)inOffset + inLen > in.length ||                    outOffset < 0 || (long)outOffset + inLen > out.length)                    throw new ArrayIndexOutOfBoundsException(getAlgorithm() +                        ": Arguments to native_crypt would cause a buffer overflow");                if (0 == native_crypt(native_cookie, in, inOffset, inLen, out, outOffset))                    throw new CryptixException(getAlgorithm() + ": Error in native code");            }        } else            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 InvalidKeyException 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(Key key)    throws InvalidKeyException {        byte[] userkey = key.getEncoded();        if (userkey == null)            throw new InvalidKeyException(getAlgorithm() + ": Null user key");        int len = userkey.length;        if (len == 0)            throw new InvalidKeyException(getAlgorithm() + ": Invalid user key length");        // If native library available then use it. If not or if        // native method returned error then revert to 100% Java.        if (native_lock != null) {            synchronized(native_lock) {                try {                    linkStatus.check(native_ks(native_cookie, userkey));                    return;                } catch (Error error) {                    native_finalize();                    native_lock = null;if (DEBUG && debuglevel > 0) debug(error + ". Will use 100% Java.");                }            }        }        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;        }    }}

⌨️ 快捷键说明

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