| /* ARCFour.java -- |
| Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. |
| |
| This file is a part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or (at |
| your option) any later version. |
| |
| GNU Classpath 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 |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 |
| USA |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package gnu.javax.crypto.prng; |
| |
| import gnu.java.security.Registry; |
| import gnu.java.security.prng.BasePRNG; |
| import gnu.java.security.prng.LimitReachedException; |
| |
| import java.util.Map; |
| |
| /** |
| * RC4 is a stream cipher developed by Ron Rivest. Until 1994 RC4 was a trade |
| * secret of RSA Data Security, Inc., when it was released anonymously to a |
| * mailing list. This version is a descendent of that code, and since there is |
| * no proof that the leaked version was in fact RC4 and because "RC4" is a |
| * trademark, it is called "ARCFOUR", short for "Allegedly RC4". |
| * <p> |
| * This class only implements the <i>keystream</i> of ARCFOUR. To use this as a |
| * stream cipher, one would say: |
| * <pre> |
| * out = in ˆ arcfour.nextByte(); |
| * </pre> |
| * <p> |
| * This operation works for encryption and decryption. |
| * <p> |
| * References: |
| * <ol> |
| * <li>Schneier, Bruce: <i>Applied Cryptography: Protocols, Algorithms, and |
| * Source Code in C, Second Edition.</i> (1996 John Wiley and Sons), pp. |
| * 397--398. ISBN 0-471-11709-9</li> |
| * <li>K. Kaukonen and R. Thayer, "A Stream Cipher Encryption Algorithm |
| * 'Arcfour'", Internet Draft (expired), <a |
| * href="http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt">draft-kaukonen-cipher-arcfour-03.txt</a></li> |
| * </ol> |
| */ |
| public class ARCFour |
| extends BasePRNG |
| implements Cloneable |
| { |
| /** The attributes property name for the key bytes. */ |
| public static final String ARCFOUR_KEY_MATERIAL = "gnu.crypto.prng.arcfour.key-material"; |
| /** The size of the internal S-box. */ |
| public static final int ARCFOUR_SBOX_SIZE = 256; |
| /** The S-box. */ |
| private byte[] s; |
| private byte m, n; |
| |
| /** Default 0-arguments constructor. */ |
| public ARCFour() |
| { |
| super(Registry.ARCFOUR_PRNG); |
| } |
| |
| public void setup(Map attributes) |
| { |
| byte[] kb = (byte[]) attributes.get(ARCFOUR_KEY_MATERIAL); |
| if (kb == null) |
| throw new IllegalArgumentException("ARCFOUR needs a key"); |
| s = new byte[ARCFOUR_SBOX_SIZE]; |
| m = n = 0; |
| byte[] k = new byte[ARCFOUR_SBOX_SIZE]; |
| for (int i = 0; i < ARCFOUR_SBOX_SIZE; i++) |
| s[i] = (byte) i; |
| if (kb.length > 0) |
| for (int i = 0, j = 0; i < ARCFOUR_SBOX_SIZE; i++) |
| { |
| k[i] = kb[j++]; |
| if (j >= kb.length) |
| j = 0; |
| } |
| for (int i = 0, j = 0; i < ARCFOUR_SBOX_SIZE; i++) |
| { |
| j = j + s[i] + k[i]; |
| byte temp = s[i]; |
| s[i] = s[j & 0xff]; |
| s[j & 0xff] = temp; |
| } |
| buffer = new byte[ARCFOUR_SBOX_SIZE]; |
| try |
| { |
| fillBlock(); |
| } |
| catch (LimitReachedException wontHappen) |
| { |
| } |
| } |
| |
| public void fillBlock() throws LimitReachedException |
| { |
| for (int i = 0; i < buffer.length; i++) |
| { |
| m++; |
| n = (byte)(n + s[m & 0xff]); |
| byte temp = s[m & 0xff]; |
| s[m & 0xff] = s[n & 0xff]; |
| s[n & 0xff] = temp; |
| temp = (byte)(s[m & 0xff] + s[n & 0xff]); |
| buffer[i] = s[temp & 0xff]; |
| } |
| } |
| } |