package jimmy;

/*
 * ARC4Cipher.java
 *
 * Created on 2006/08/08, 18:40
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

/**
 *
 * @author def
 */
public class ARC4Cipher 
{
    private int     x;
    private int     y;
    private byte[] mstate;
    
    /** Creates a new instance of ARC4Cipher */
    public ARC4Cipher() {
    }
    public ARC4Cipher(byte[] key)
    {
        init(key);
    }
    
    public byte[] encrypt(byte[] src)
    {
        byte[] dest = new byte[src.length];
        System.arraycopy(src, 0, dest, 0, src.length);

        int x    = this.x;
        int y    = this.y;
        int sx, sy, i;

        for (i = 0; i < src.length; ++i) {
            ++x;
            sx           = mstate[x];
            y            = (y + sx) & 0xff;
            sy           = mstate[y];
            mstate[y]    = (byte)sx;
            mstate[x]    = (byte)sy;
            sx           = (sx + sy) & 0xff;
            dest[i]     ^= mstate[sx];
        }

        this.x = x;
        this.y = y;
        
        return dest;
    }
    
    public byte[] decrypt(byte[] src)
    {
        return encrypt(src);
    }
    
    public void init(byte[] key)
    {
        mstate = new byte[256];

        int i, keylen, keyindex, stateindex;
        byte u;

        this.x = this.y = keylen = 0;
        
        for (i = 0; i < key.length; ++i) {
            if (key[i] == 0) {
                break;
            }
            ++keylen;
        }

        for (i = 0; i < mstate.length; ++i) {
            mstate[i] = (byte)i;
        }
        if (keylen == 0) {
            return;
        }

        keyindex    = stateindex =0;

        for (i = 0; i < mstate.length; ++i) {
            byte state = mstate[i];

            stateindex              = (stateindex + key[keyindex] + state) & 0xff;
            u                       = mstate[stateindex];
            mstate[stateindex]      = mstate[i];
            mstate[i]               = u;
            if (++keyindex >= keylen) {
                keyindex = 0;
            }
        }
    }
}
