001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: ///////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp.crypto;
022:
023: public final class RC4 {
024: private static final int BLOCK_SIZE = 1;
025: public static final int UNINITIALIZED = 0;
026: public static final int ENCRYPT = 1;
027: public static final int DECRYPT = 2;
028:
029: private int m_x;
030: private int m_y;
031: private int m_state;
032: private int[] m_sBox = new int[256];
033: private String m_cipherName = "RC4";
034:
035: public RC4() {
036: //super(false, false, "Cryptix");
037: }
038:
039: private void rc4(byte[] in, int inOffset, int inLen, byte[] out,
040: int outOffset) {
041: int xorIndex, t;
042:
043: for (int i = 0; i < inLen; i++) {
044: m_x = (m_x + 1) & 0xFF;
045: m_y = (m_sBox[m_x] + m_y) & 0xFF;
046:
047: t = m_sBox[m_x];
048: m_sBox[m_x] = m_sBox[m_y];
049: m_sBox[m_y] = t;
050:
051: xorIndex = (m_sBox[m_x] + m_sBox[m_y]) & 0xFF;
052: out[outOffset++] = (byte) (in[inOffset++] ^ m_sBox[xorIndex]);
053: }
054: }
055:
056: private void makeKey(byte[] userkey) throws CryptoException {
057: if (userkey == null) {
058: throw new CryptoException(getAlgorithm()
059: + ": Null user key");
060: }
061:
062: int len = userkey.length;
063: if (len == 0) {
064: throw new CryptoException(getAlgorithm()
065: + ": Invalid user key length");
066: }
067:
068: m_x = m_y = 0;
069: for (int i = 0; i < 256; i++) {
070: m_sBox[i] = i;
071: }
072:
073: int i1 = 0, i2 = 0, t;
074: for (int i = 0; i < 256; i++) {
075: i2 = ((userkey[i1] & 0xFF) + m_sBox[i] + i2) & 0xFF;
076:
077: t = m_sBox[i];
078: m_sBox[i] = m_sBox[i2];
079: m_sBox[i2] = t;
080:
081: i1 = (i1 + 1) % len;
082: }
083: }
084:
085: protected int engineUpdate(byte[] in, int inOffset, int inLen,
086: byte[] out, int outOffset) {
087: if (inLen < 0) {
088: throw new IllegalArgumentException("inLen < 0");
089: }
090:
091: boolean doEncrypt = (getState() == ENCRYPT);
092:
093: if (in == out
094: && (outOffset >= inOffset
095: && outOffset < inOffset + inLen || inOffset >= outOffset
096: && inOffset < outOffset + inLen)) {
097: byte[] newin = new byte[inLen];
098: System.arraycopy(in, inOffset, newin, 0, inLen);
099: in = newin;
100: inOffset = 0;
101: }
102:
103: rc4(in, inOffset, inLen, out, outOffset);
104:
105: return inLen;
106: }
107:
108: public final Object clone() throws CloneNotSupportedException {
109: throw new CloneNotSupportedException();
110: }
111:
112: public int engineBlockSize() {
113: return BLOCK_SIZE;
114: }
115:
116: public void engineInitEncrypt(byte[] key) throws CryptoException {
117: makeKey(key);
118: m_state = ENCRYPT;
119: }
120:
121: public void engineInitDecrypt(byte[] key) throws CryptoException {
122: makeKey(key);
123: m_state = ENCRYPT;
124: }
125:
126: public final String getAlgorithm() {
127: return m_cipherName;
128: }
129:
130: public final int getState() {
131: return m_state;
132: }
133:
134: public final byte[] crypt(byte[] data, int position, int length) {
135: byte[] buffer = new byte[length];
136: engineUpdate(data, position, length, buffer, 0);
137: return buffer;
138: }
139:
140: public final byte[] crypt(byte[] data) {
141: byte[] buffer = new byte[data.length];
142: engineUpdate(data, 0, data.length, buffer, 0);
143: return buffer;
144: }
145:
146: public final void crypt(byte[] in, int in_offset, int length,
147: byte[] out, int out_offset) {
148: engineUpdate(in, in_offset, length, out, out_offset);
149: }
150: }
|