/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Implementation of the ARCFOUR cipher, an algorithm apparently compatible
* with RSA Security's RC4(tm) cipher. The description of this algorithm was
* taken from Bruce Schneier's book Applied Cryptography, 2nd ed.,
* section 17.1.
*
* We support keys from 40 to 1024 bits. ARCFOUR would allow for keys shorter
* than 40 bits, but that is too insecure for us to permit.
*
* Note that we subclass CipherSpi directly and do not use the CipherCore
* framework. That was designed to simplify implementation of block ciphers
* and does not offer any advantages for stream ciphers such as ARCFOUR.
*
* @since 1.5
* @author Andreas Sterbenz
*/
// state array S, 256 entries. The entries are 8-bit, but we use an int[]
// because int arithmetic is much faster than in Java than bytes.
private final int[] S;
// state indices i and j. Called is and js to avoid collision with
// local variables. 'is' is set to -1 after a call to doFinal()
// the bytes of the last key used (if any)
// we need this to re-initialize after a call to doFinal()
private byte[] lastKey;
// called by the JCE framework
public ARCFOURCipher() {
S = new int[256];
}
// core key setup code. initializes S, is, and js
// assumes key is non-null and between 40 and 1024 bit
// initialize S[i] to i
for (int i = 0; i < 256; i++) {
S[i] = i;
}
// we avoid expanding key to 256 bytes and instead keep a separate
// counter ki = i mod key.length.
int Si = S[i];
S[i] = S[j];
S[j] = Si;
ki++;
ki = 0;
}
}
// set indices to 0
is = 0;
js = 0;
}
// core crypt code. OFB style, so works for both encryption and decryption
int outOfs) {
if (is < 0) {
// doFinal() was called, need to reset the cipher to initial state
}
while (inLen-- > 0) {
}
}
// Modes do not make sense with stream ciphers, but allow ECB
// see JCE spec.
}
}
// Padding does not make sense with stream ciphers, but allow NoPadding
// see JCE spec.
throws NoSuchPaddingException {
throw new NoSuchPaddingException("Padding must be NoPadding");
}
}
// Return 0 to indicate stream cipher
// see JCE spec.
protected int engineGetBlockSize() {
return 0;
}
// output length is always the same as input length
// see JCE spec
return inputLen;
}
// no IV, return null
// see JCE spec
protected byte[] engineGetIV() {
return null;
}
// no parameters
// see JCE spec
return null;
}
// see JCE spec
throws InvalidKeyException {
}
// see JCE spec
throw new InvalidAlgorithmParameterException
("Parameters not supported");
}
}
// see JCE spec
throw new InvalidAlgorithmParameterException
("Parameters not supported");
}
}
// init method. Check opmode and key, then call init(byte[]).
}
}
// return the encoding of key if key is a valid ARCFOUR key.
// otherwise, throw an InvalidKeyException
}
throw new InvalidKeyException("Key encoding format must be RAW");
}
throw new InvalidKeyException
("Key length must be between 40 and 1024 bit");
}
return encodedKey;
}
// see JCE spec
return out;
}
// see JCE spec
throw new ShortBufferException("Output buffer too small");
}
return inLen;
}
// see JCE spec
is = -1;
return out;
}
// see JCE spec
is = -1;
return outLen;
}
// see JCE spec
throw new InvalidKeyException("Could not obtain encoded key");
}
}
// see JCE spec
}
// see JCE spec
}
}