Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/ARCFOURCipher.java
41161 views
1
/*
2
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package com.sun.crypto.provider;
27
28
import java.security.*;
29
import java.security.spec.AlgorithmParameterSpec;
30
import java.util.Arrays;
31
32
import javax.crypto.*;
33
34
/**
35
* Implementation of the ARCFOUR cipher, an algorithm apparently compatible
36
* with RSA Security's RC4(tm) cipher. The description of this algorithm was
37
* taken from Bruce Schneier's book Applied Cryptography, 2nd ed.,
38
* section 17.1.
39
*
40
* We support keys from 40 to 1024 bits. ARCFOUR would allow for keys shorter
41
* than 40 bits, but that is too insecure for us to permit.
42
*
43
* Note that we subclass CipherSpi directly and do not use the CipherCore
44
* framework. That was designed to simplify implementation of block ciphers
45
* and does not offer any advantages for stream ciphers such as ARCFOUR.
46
*
47
* @since 1.5
48
* @author Andreas Sterbenz
49
*/
50
public final class ARCFOURCipher extends CipherSpi {
51
52
// state array S, 256 entries. The entries are 8-bit, but we use an int[]
53
// because int arithmetic is much faster than in Java than bytes.
54
private final int[] S;
55
56
// state indices i and j. Called is and js to avoid collision with
57
// local variables. 'is' is set to -1 after a call to doFinal()
58
private int is, js;
59
60
// the bytes of the last key used (if any)
61
// we need this to re-initialize after a call to doFinal()
62
private byte[] lastKey;
63
64
// called by the JCE framework
65
public ARCFOURCipher() {
66
S = new int[256];
67
}
68
69
// core key setup code. initializes S, is, and js
70
// assumes key is non-null and between 40 and 1024 bit
71
private void init(byte[] key) {
72
// initialize S[i] to i
73
for (int i = 0; i < 256; i++) {
74
S[i] = i;
75
}
76
77
// we avoid expanding key to 256 bytes and instead keep a separate
78
// counter ki = i mod key.length.
79
for (int i = 0, j = 0, ki = 0; i < 256; i++) {
80
int Si = S[i];
81
j = (j + Si + key[ki]) & 0xff;
82
S[i] = S[j];
83
S[j] = Si;
84
ki++;
85
if (ki == key.length) {
86
ki = 0;
87
}
88
}
89
90
// set indices to 0
91
is = 0;
92
js = 0;
93
}
94
95
// core crypt code. OFB style, so works for both encryption and decryption
96
private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
97
int outOfs) {
98
if (is < 0) {
99
// doFinal() was called, need to reset the cipher to initial state
100
init(lastKey);
101
}
102
while (inLen-- > 0) {
103
is = (is + 1) & 0xff;
104
int Si = S[is];
105
js = (js + Si) & 0xff;
106
int Sj = S[js];
107
S[is] = Sj;
108
S[js] = Si;
109
out[outOfs++] = (byte)(in[inOfs++] ^ S[(Si + Sj) & 0xff]);
110
}
111
}
112
113
// Modes do not make sense with stream ciphers, but allow ECB
114
// see JCE spec.
115
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
116
if (mode.equalsIgnoreCase("ECB") == false) {
117
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
118
}
119
}
120
121
// Padding does not make sense with stream ciphers, but allow NoPadding
122
// see JCE spec.
123
protected void engineSetPadding(String padding)
124
throws NoSuchPaddingException {
125
if (padding.equalsIgnoreCase("NoPadding") == false) {
126
throw new NoSuchPaddingException("Padding must be NoPadding");
127
}
128
}
129
130
// Return 0 to indicate stream cipher
131
// see JCE spec.
132
protected int engineGetBlockSize() {
133
return 0;
134
}
135
136
// output length is always the same as input length
137
// see JCE spec
138
protected int engineGetOutputSize(int inputLen) {
139
return inputLen;
140
}
141
142
// no IV, return null
143
// see JCE spec
144
protected byte[] engineGetIV() {
145
return null;
146
}
147
148
// no parameters
149
// see JCE spec
150
protected AlgorithmParameters engineGetParameters() {
151
return null;
152
}
153
154
// see JCE spec
155
protected void engineInit(int opmode, Key key, SecureRandom random)
156
throws InvalidKeyException {
157
init(opmode, key);
158
}
159
160
// see JCE spec
161
protected void engineInit(int opmode, Key key,
162
AlgorithmParameterSpec params, SecureRandom random)
163
throws InvalidKeyException, InvalidAlgorithmParameterException {
164
if (params != null) {
165
throw new InvalidAlgorithmParameterException
166
("Parameters not supported");
167
}
168
init(opmode, key);
169
}
170
171
// see JCE spec
172
protected void engineInit(int opmode, Key key,
173
AlgorithmParameters params, SecureRandom random)
174
throws InvalidKeyException, InvalidAlgorithmParameterException {
175
if (params != null) {
176
throw new InvalidAlgorithmParameterException
177
("Parameters not supported");
178
}
179
init(opmode, key);
180
}
181
182
// init method. Check opmode and key, then call init(byte[]).
183
private void init(int opmode, Key key) throws InvalidKeyException {
184
if (lastKey != null) {
185
Arrays.fill(lastKey, (byte)0);
186
}
187
if ((opmode < Cipher.ENCRYPT_MODE) || (opmode > Cipher.UNWRAP_MODE)) {
188
throw new InvalidKeyException("Unknown opmode: " + opmode);
189
}
190
lastKey = getEncodedKey(key);
191
init(lastKey);
192
}
193
194
// return the encoding of key if key is a valid ARCFOUR key.
195
// otherwise, throw an InvalidKeyException
196
private static byte[] getEncodedKey(Key key) throws InvalidKeyException {
197
String keyAlg = key.getAlgorithm();
198
if (!keyAlg.equals("RC4") && !keyAlg.equals("ARCFOUR")) {
199
throw new InvalidKeyException("Not an ARCFOUR key: " + keyAlg);
200
}
201
if ("RAW".equals(key.getFormat()) == false) {
202
throw new InvalidKeyException("Key encoding format must be RAW");
203
}
204
byte[] encodedKey = key.getEncoded();
205
if ((encodedKey.length < 5) || (encodedKey.length > 128)) {
206
Arrays.fill(encodedKey, (byte)0);
207
throw new InvalidKeyException
208
("Key length must be between 40 and 1024 bit");
209
}
210
return encodedKey;
211
}
212
213
// see JCE spec
214
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
215
byte[] out = new byte[inLen];
216
crypt(in, inOfs, inLen, out, 0);
217
return out;
218
}
219
220
// see JCE spec
221
protected int engineUpdate(byte[] in, int inOfs, int inLen,
222
byte[] out, int outOfs) throws ShortBufferException {
223
if (out.length - outOfs < inLen) {
224
throw new ShortBufferException("Output buffer too small");
225
}
226
crypt(in, inOfs, inLen, out, outOfs);
227
return inLen;
228
}
229
230
// see JCE spec
231
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen) {
232
byte[] out = engineUpdate(in, inOfs, inLen);
233
is = -1;
234
return out;
235
}
236
237
// see JCE spec
238
protected int engineDoFinal(byte[] in, int inOfs, int inLen,
239
byte[] out, int outOfs) throws ShortBufferException {
240
int outLen = engineUpdate(in, inOfs, inLen, out, outOfs);
241
is = -1;
242
return outLen;
243
}
244
245
// see JCE spec
246
protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
247
InvalidKeyException {
248
byte[] encoded = key.getEncoded();
249
if ((encoded == null) || (encoded.length == 0)) {
250
throw new InvalidKeyException("Could not obtain encoded key");
251
}
252
try {
253
return engineDoFinal(encoded, 0, encoded.length);
254
} finally {
255
Arrays.fill(encoded, (byte)0);
256
}
257
}
258
259
// see JCE spec
260
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
261
int type) throws InvalidKeyException, NoSuchAlgorithmException {
262
byte[] encoded = null;
263
try {
264
encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
265
return ConstructKeys.constructKey(encoded, algorithm, type);
266
} finally {
267
if (encoded != null) {
268
Arrays.fill(encoded, (byte) 0);
269
}
270
}
271
}
272
273
// see JCE spec
274
protected int engineGetKeySize(Key key) throws InvalidKeyException {
275
byte[] encodedKey = getEncodedKey(key);
276
Arrays.fill(encodedKey, (byte)0);
277
return Math.multiplyExact(encodedKey.length, 8);
278
}
279
280
}
281
282