Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java
38922 views
1
/*
2
* Copyright (c) 2003, 2017, 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
31
import javax.crypto.*;
32
33
/**
34
* Implementation of the ARCFOUR cipher, an algorithm apparently compatible
35
* with RSA Security's RC4(tm) cipher. The description of this algorithm was
36
* taken from Bruce Schneier's book Applied Cryptography, 2nd ed.,
37
* section 17.1.
38
*
39
* We support keys from 40 to 1024 bits. ARCFOUR would allow for keys shorter
40
* than 40 bits, but that is too insecure for us to permit.
41
*
42
* Note that we subclass CipherSpi directly and do not use the CipherCore
43
* framework. That was designed to simplify implementation of block ciphers
44
* and does not offer any advantages for stream ciphers such as ARCFOUR.
45
*
46
* @since 1.5
47
* @author Andreas Sterbenz
48
*/
49
public final class ARCFOURCipher extends CipherSpi {
50
51
// state array S, 256 entries. The entries are 8-bit, but we use an int[]
52
// because int arithmetic is much faster than in Java than bytes.
53
private final int[] S;
54
55
// state indices i and j. Called is and js to avoid collision with
56
// local variables. 'is' is set to -1 after a call to doFinal()
57
private int is, js;
58
59
// the bytes of the last key used (if any)
60
// we need this to re-initialize after a call to doFinal()
61
private byte[] lastKey;
62
63
// called by the JCE framework
64
public ARCFOURCipher() {
65
S = new int[256];
66
}
67
68
// core key setup code. initializes S, is, and js
69
// assumes key is non-null and between 40 and 1024 bit
70
private void init(byte[] key) {
71
// initialize S[i] to i
72
for (int i = 0; i < 256; i++) {
73
S[i] = i;
74
}
75
76
// we avoid expanding key to 256 bytes and instead keep a separate
77
// counter ki = i mod key.length.
78
for (int i = 0, j = 0, ki = 0; i < 256; i++) {
79
int Si = S[i];
80
j = (j + Si + key[ki]) & 0xff;
81
S[i] = S[j];
82
S[j] = Si;
83
ki++;
84
if (ki == key.length) {
85
ki = 0;
86
}
87
}
88
89
// set indices to 0
90
is = 0;
91
js = 0;
92
}
93
94
// core crypt code. OFB style, so works for both encryption and decryption
95
private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
96
int outOfs) {
97
if (is < 0) {
98
// doFinal() was called, need to reset the cipher to initial state
99
init(lastKey);
100
}
101
while (inLen-- > 0) {
102
is = (is + 1) & 0xff;
103
int Si = S[is];
104
js = (js + Si) & 0xff;
105
int Sj = S[js];
106
S[is] = Sj;
107
S[js] = Si;
108
out[outOfs++] = (byte)(in[inOfs++] ^ S[(Si + Sj) & 0xff]);
109
}
110
}
111
112
// Modes do not make sense with stream ciphers, but allow ECB
113
// see JCE spec.
114
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
115
if (mode.equalsIgnoreCase("ECB") == false) {
116
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
117
}
118
}
119
120
// Padding does not make sense with stream ciphers, but allow NoPadding
121
// see JCE spec.
122
protected void engineSetPadding(String padding)
123
throws NoSuchPaddingException {
124
if (padding.equalsIgnoreCase("NoPadding") == false) {
125
throw new NoSuchPaddingException("Padding must be NoPadding");
126
}
127
}
128
129
// Return 0 to indicate stream cipher
130
// see JCE spec.
131
protected int engineGetBlockSize() {
132
return 0;
133
}
134
135
// output length is always the same as input length
136
// see JCE spec
137
protected int engineGetOutputSize(int inputLen) {
138
return inputLen;
139
}
140
141
// no IV, return null
142
// see JCE spec
143
protected byte[] engineGetIV() {
144
return null;
145
}
146
147
// no parameters
148
// see JCE spec
149
protected AlgorithmParameters engineGetParameters() {
150
return null;
151
}
152
153
// see JCE spec
154
protected void engineInit(int opmode, Key key, SecureRandom random)
155
throws InvalidKeyException {
156
init(opmode, key);
157
}
158
159
// see JCE spec
160
protected void engineInit(int opmode, Key key,
161
AlgorithmParameterSpec params, SecureRandom random)
162
throws InvalidKeyException, InvalidAlgorithmParameterException {
163
if (params != null) {
164
throw new InvalidAlgorithmParameterException
165
("Parameters not supported");
166
}
167
init(opmode, key);
168
}
169
170
// see JCE spec
171
protected void engineInit(int opmode, Key key,
172
AlgorithmParameters params, SecureRandom random)
173
throws InvalidKeyException, InvalidAlgorithmParameterException {
174
if (params != null) {
175
throw new InvalidAlgorithmParameterException
176
("Parameters not supported");
177
}
178
init(opmode, key);
179
}
180
181
// init method. Check opmode and key, then call init(byte[]).
182
private void init(int opmode, Key key) throws InvalidKeyException {
183
if ((opmode < Cipher.ENCRYPT_MODE) || (opmode > Cipher.UNWRAP_MODE)) {
184
throw new InvalidKeyException("Unknown opmode: " + opmode);
185
}
186
lastKey = getEncodedKey(key);
187
init(lastKey);
188
}
189
190
// return the encoding of key if key is a valid ARCFOUR key.
191
// otherwise, throw an InvalidKeyException
192
private static byte[] getEncodedKey(Key key) throws InvalidKeyException {
193
String keyAlg = key.getAlgorithm();
194
if (!keyAlg.equals("RC4") && !keyAlg.equals("ARCFOUR")) {
195
throw new InvalidKeyException("Not an ARCFOUR key: " + keyAlg);
196
}
197
if ("RAW".equals(key.getFormat()) == false) {
198
throw new InvalidKeyException("Key encoding format must be RAW");
199
}
200
byte[] encodedKey = key.getEncoded();
201
if ((encodedKey.length < 5) || (encodedKey.length > 128)) {
202
throw new InvalidKeyException
203
("Key length must be between 40 and 1024 bit");
204
}
205
return encodedKey;
206
}
207
208
// see JCE spec
209
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
210
byte[] out = new byte[inLen];
211
crypt(in, inOfs, inLen, out, 0);
212
return out;
213
}
214
215
// see JCE spec
216
protected int engineUpdate(byte[] in, int inOfs, int inLen,
217
byte[] out, int outOfs) throws ShortBufferException {
218
if (out.length - outOfs < inLen) {
219
throw new ShortBufferException("Output buffer too small");
220
}
221
crypt(in, inOfs, inLen, out, outOfs);
222
return inLen;
223
}
224
225
// see JCE spec
226
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen) {
227
byte[] out = engineUpdate(in, inOfs, inLen);
228
is = -1;
229
return out;
230
}
231
232
// see JCE spec
233
protected int engineDoFinal(byte[] in, int inOfs, int inLen,
234
byte[] out, int outOfs) throws ShortBufferException {
235
int outLen = engineUpdate(in, inOfs, inLen, out, outOfs);
236
is = -1;
237
return outLen;
238
}
239
240
// see JCE spec
241
protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
242
InvalidKeyException {
243
byte[] encoded = key.getEncoded();
244
if ((encoded == null) || (encoded.length == 0)) {
245
throw new InvalidKeyException("Could not obtain encoded key");
246
}
247
return engineDoFinal(encoded, 0, encoded.length);
248
}
249
250
// see JCE spec
251
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
252
int type) throws InvalidKeyException, NoSuchAlgorithmException {
253
byte[] encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
254
return ConstructKeys.constructKey(encoded, algorithm, type);
255
}
256
257
// see JCE spec
258
protected int engineGetKeySize(Key key) throws InvalidKeyException {
259
byte[] encodedKey = getEncodedKey(key);
260
return Math.multiplyExact(encodedKey.length, 8);
261
}
262
263
}
264
265