Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
67760 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 sun.security.rsa;
27
28
import java.io.IOException;
29
import java.math.BigInteger;
30
31
import java.security.*;
32
import java.security.spec.*;
33
import java.security.interfaces.*;
34
import java.util.Arrays;
35
36
import sun.security.util.*;
37
38
import sun.security.pkcs.PKCS8Key;
39
40
import sun.security.rsa.RSAUtil.KeyType;
41
42
/**
43
* RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in CRT form.
44
* For non-CRT private keys, see RSAPrivateKeyImpl. We need separate classes
45
* to ensure correct behavior in instanceof checks, etc.
46
*
47
* Note: RSA keys must be at least 512 bits long
48
*
49
* @see RSAPrivateKeyImpl
50
* @see RSAKeyFactory
51
*
52
* @since 1.5
53
* @author Andreas Sterbenz
54
*/
55
public final class RSAPrivateCrtKeyImpl
56
extends PKCS8Key implements RSAPrivateCrtKey {
57
58
@java.io.Serial
59
private static final long serialVersionUID = -1326088454257084918L;
60
61
private BigInteger n; // modulus
62
private BigInteger e; // public exponent
63
private BigInteger d; // private exponent
64
private BigInteger p; // prime p
65
private BigInteger q; // prime q
66
private BigInteger pe; // prime exponent p
67
private BigInteger qe; // prime exponent q
68
private BigInteger coeff; // CRT coeffcient
69
70
private transient KeyType type;
71
72
// Optional parameters associated with this RSA key
73
// specified in the encoding of its AlgorithmId.
74
// Must be null for "RSA" keys.
75
private transient AlgorithmParameterSpec keyParams;
76
77
/**
78
* Generate a new RSAPrivate(Crt)Key from the specified type,
79
* format and encoding. Returns a CRT key if possible and a non-CRT
80
* key otherwise.
81
* Also used by SunPKCS11 provider.
82
*/
83
public static RSAPrivateKey newKey(KeyType type, String format,
84
byte[] encoded) throws InvalidKeyException {
85
if (encoded == null || encoded.length == 0) {
86
throw new InvalidKeyException("Missing key encoding");
87
}
88
switch (format) {
89
case "PKCS#8":
90
RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded);
91
RSAKeyFactory.checkKeyAlgo(key, type.keyAlgo);
92
// check all CRT-specific components are available, if any one
93
// missing, return a non-CRT key instead
94
if (checkComponents(key)) {
95
return key;
96
} else {
97
return new RSAPrivateKeyImpl(key.type, key.keyParams,
98
key.getModulus(), key.getPrivateExponent());
99
}
100
case "PKCS#1":
101
try {
102
BigInteger[] comps = parseASN1(encoded);
103
if ((comps[1].signum() == 0) || (comps[3].signum() == 0) ||
104
(comps[4].signum() == 0) || (comps[5].signum() == 0) ||
105
(comps[6].signum() == 0) || (comps[7].signum() == 0)) {
106
return new RSAPrivateKeyImpl(type, null, comps[0],
107
comps[2]);
108
} else {
109
return new RSAPrivateCrtKeyImpl(type, null, comps[0],
110
comps[1], comps[2], comps[3], comps[4], comps[5],
111
comps[6], comps[7]);
112
}
113
} catch (IOException ioe) {
114
throw new InvalidKeyException("Invalid PKCS#1 encoding", ioe);
115
}
116
default:
117
throw new InvalidKeyException("Unsupported RSA Private(Crt)Key "
118
+ "format: " + format);
119
}
120
}
121
122
/**
123
* Validate if all CRT-specific components are available.
124
*/
125
static boolean checkComponents(RSAPrivateCrtKey key) {
126
return !((key.getPublicExponent().signum() == 0) ||
127
(key.getPrimeExponentP().signum() == 0) ||
128
(key.getPrimeExponentQ().signum() == 0) ||
129
(key.getPrimeP().signum() == 0) ||
130
(key.getPrimeQ().signum() == 0) ||
131
(key.getCrtCoefficient().signum() == 0));
132
}
133
134
/**
135
* Generate a new key from the specified type and components.
136
* Returns a CRT key if possible and a non-CRT key otherwise.
137
* Used by SunPKCS11 provider.
138
*/
139
public static RSAPrivateKey newKey(KeyType type,
140
AlgorithmParameterSpec params,
141
BigInteger n, BigInteger e, BigInteger d,
142
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
143
BigInteger coeff) throws InvalidKeyException {
144
RSAPrivateKey key;
145
if ((e.signum() == 0) || (p.signum() == 0) ||
146
(q.signum() == 0) || (pe.signum() == 0) ||
147
(qe.signum() == 0) || (coeff.signum() == 0)) {
148
// if any component is missing, return a non-CRT key
149
return new RSAPrivateKeyImpl(type, params, n, d);
150
} else {
151
return new RSAPrivateCrtKeyImpl(type, params, n, e, d,
152
p, q, pe, qe, coeff);
153
}
154
}
155
156
/**
157
* Construct a key from its encoding. Called from newKey above.
158
*/
159
private RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
160
super(encoded);
161
parseKeyBits();
162
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
163
try {
164
// check the validity of oid and params
165
Object[] o = RSAUtil.getTypeAndParamSpec(algid);
166
this.type = (KeyType) o[0];
167
this.keyParams = (AlgorithmParameterSpec) o[1];
168
} catch (ProviderException e) {
169
throw new InvalidKeyException(e);
170
}
171
}
172
173
/**
174
* Construct a RSA key from its components. Used by the
175
* RSAKeyFactory and the RSAKeyPairGenerator.
176
*/
177
RSAPrivateCrtKeyImpl(KeyType type, AlgorithmParameterSpec keyParams,
178
BigInteger n, BigInteger e, BigInteger d,
179
BigInteger p, BigInteger q, BigInteger pe, BigInteger qe,
180
BigInteger coeff) throws InvalidKeyException {
181
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
182
183
this.n = n;
184
this.e = e;
185
this.d = d;
186
this.p = p;
187
this.q = q;
188
this.pe = pe;
189
this.qe = qe;
190
this.coeff = coeff;
191
192
try {
193
// validate and generate the algid encoding
194
algid = RSAUtil.createAlgorithmId(type, keyParams);
195
} catch (ProviderException exc) {
196
throw new InvalidKeyException(exc);
197
}
198
199
this.type = type;
200
this.keyParams = keyParams;
201
202
try {
203
byte[][] nbytes = new byte[8][];
204
nbytes[0] = n.toByteArray();
205
nbytes[1] = e.toByteArray();
206
nbytes[2] = d.toByteArray();
207
nbytes[3] = p.toByteArray();
208
nbytes[4] = q.toByteArray();
209
nbytes[5] = pe.toByteArray();
210
nbytes[6] = qe.toByteArray();
211
nbytes[7] = coeff.toByteArray();
212
213
// Initiate with a big enough size so there's no need to
214
// reallocate memory later and thus can be cleaned up
215
// reliably.
216
DerOutputStream out = new DerOutputStream(
217
nbytes[0].length + nbytes[1].length +
218
nbytes[2].length + nbytes[3].length +
219
nbytes[4].length + nbytes[5].length +
220
nbytes[6].length + nbytes[7].length +
221
100); // Enough for version(3) and 8 tag+length(3 or 4)
222
out.putInteger(0); // version must be 0
223
out.putInteger(nbytes[0]);
224
out.putInteger(nbytes[1]);
225
out.putInteger(nbytes[2]);
226
out.putInteger(nbytes[3]);
227
out.putInteger(nbytes[4]);
228
out.putInteger(nbytes[5]);
229
out.putInteger(nbytes[6]);
230
out.putInteger(nbytes[7]);
231
// Private values from [2] on.
232
Arrays.fill(nbytes[2], (byte)0);
233
Arrays.fill(nbytes[3], (byte)0);
234
Arrays.fill(nbytes[4], (byte)0);
235
Arrays.fill(nbytes[5], (byte)0);
236
Arrays.fill(nbytes[6], (byte)0);
237
Arrays.fill(nbytes[7], (byte)0);
238
DerValue val = DerValue.wrap(DerValue.tag_Sequence, out);
239
key = val.toByteArray();
240
val.clear();
241
} catch (IOException exc) {
242
// should never occur
243
throw new InvalidKeyException(exc);
244
}
245
}
246
247
// see JCA doc
248
@Override
249
public String getAlgorithm() {
250
return type.keyAlgo;
251
}
252
253
// see JCA doc
254
@Override
255
public BigInteger getModulus() {
256
return n;
257
}
258
259
// see JCA doc
260
@Override
261
public BigInteger getPublicExponent() {
262
return e;
263
}
264
265
// see JCA doc
266
@Override
267
public BigInteger getPrivateExponent() {
268
return d;
269
}
270
271
// see JCA doc
272
@Override
273
public BigInteger getPrimeP() {
274
return p;
275
}
276
277
// see JCA doc
278
@Override
279
public BigInteger getPrimeQ() {
280
return q;
281
}
282
283
// see JCA doc
284
@Override
285
public BigInteger getPrimeExponentP() {
286
return pe;
287
}
288
289
// see JCA doc
290
@Override
291
public BigInteger getPrimeExponentQ() {
292
return qe;
293
}
294
295
// see JCA doc
296
@Override
297
public BigInteger getCrtCoefficient() {
298
return coeff;
299
}
300
301
// see JCA doc
302
@Override
303
public AlgorithmParameterSpec getParams() {
304
return keyParams;
305
}
306
307
// return a string representation of this key for debugging
308
@Override
309
public String toString() {
310
return "SunRsaSign " + type.keyAlgo + " private CRT key, "
311
+ n.bitLength() + " bits" + "\n params: " + keyParams
312
+ "\n modulus: " + n + "\n private exponent: " + d;
313
}
314
315
// utility method for parsing DER encoding of RSA private keys in PKCS#1
316
// format as defined in RFC 8017 Appendix A.1.2, i.e. SEQ of version, n,
317
// e, d, p, q, pe, qe, and coeff, and return the parsed components.
318
private static BigInteger[] parseASN1(byte[] raw) throws IOException {
319
DerValue derValue = new DerValue(raw);
320
try {
321
if (derValue.tag != DerValue.tag_Sequence) {
322
throw new IOException("Not a SEQUENCE");
323
}
324
int version = derValue.data.getInteger();
325
if (version != 0) {
326
throw new IOException("Version must be 0");
327
}
328
329
BigInteger[] result = new BigInteger[8]; // n, e, d, p, q, pe, qe, coeff
330
/*
331
* Some implementations do not correctly encode ASN.1 INTEGER values
332
* in 2's complement format, resulting in a negative integer when
333
* decoded. Correct the error by converting it to a positive integer.
334
*
335
* See CR 6255949
336
*/
337
for (int i = 0; i < result.length; i++) {
338
result[i] = derValue.data.getPositiveBigInteger();
339
}
340
if (derValue.data.available() != 0) {
341
throw new IOException("Extra data available");
342
}
343
return result;
344
} finally {
345
derValue.clear();
346
}
347
}
348
349
private void parseKeyBits() throws InvalidKeyException {
350
try {
351
BigInteger[] comps = parseASN1(key);
352
n = comps[0];
353
e = comps[1];
354
d = comps[2];
355
p = comps[3];
356
q = comps[4];
357
pe = comps[5];
358
qe = comps[6];
359
coeff = comps[7];
360
} catch (IOException e) {
361
throw new InvalidKeyException("Invalid RSA private key", e);
362
}
363
}
364
}
365
366