/*************************************************************************
 * PCRaw
 * Author: nori090
 * Original author: ◆e5bW6vDOJ.
 * Copyright: Copyright (C) 2008 nori090
 * Copyright: Copyright (C) 2007 ◆e5bW6vDOJ.
 * Date: February 11, 2007
 * License: 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 * 
 * http://mosax.sakura.ne.jp/fswiki.cgi?page=PCRaw
 */
package org.coderepos.nori090.pcraw;

/**
 * @author nori090
 * @version $Rev: 122 $ $Date: 2008-07-21 21:40:59 +0900 (Mon, 21 Jul 2008) $
 */
public final class Arcfour {
    private int x;

    private int y;

    private byte[] key;

    private final static int SIZE = 256;

    void init( byte[] pass ) {
        x = 0;
        y = 0;
        key = new byte[SIZE];
        for ( int i = 0; i < SIZE; i++ ) {
            key[i] = (byte) i;
        }
        int j = 0;
        for ( int i = 0; i < key.length; i++ ) {
            byte b = key[i];
            j = ( j + ( b & 0xff ) + ( pass[i % pass.length] & 0xff ) ) & 0xff;
            key[i] = key[j];
            key[j] = b;
        }
    }

    void uninit() {
        x = 0;
        y = 0;
        key = new byte[SIZE];
        for ( int i = 0; i < SIZE; i++ ) {
            key[i] = (byte) i;
        }
    }

    byte[] codec( byte[] src ) {
        byte n, m;
        int pos;
        byte[] dest = new byte[src.length];
        for ( int i = 0; i < src.length; i++ ) {
            byte c = src[i];
            x = ( x + 1 ) & 0xff;
            n = key[x];
            y = ( y + ( n & 0xff ) ) & 0xff;
            m = key[y];
            key[x] = m;
            key[y] = n;
            pos = ( ( m & 0xff ) + ( n & 0xff ) ) & 0xff;
            dest[i] = (byte) ( c ^ key[pos] );
        }
        return dest;
    }

    public static void main( String[] args ) {
        Arcfour rc4 = new Arcfour();

        byte[] plain = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        byte[] key = new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab, (byte) 0xcd, (byte) 0xef };
        byte[] cipher = new byte[] { 0x74, (byte) 0x94, (byte) 0xc2, (byte) 0xe7, 0x10, 0x4b, 0x08, 0x79 };

        rc4.init( key );
        byte[] ret = rc4.codec( plain );
        System.out.println( PCRawTools.encodeHex( ret ) );
        System.out.println( PCRawTools.encodeHex( cipher ) );
    }
}
