Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
41159 views
1
/*
2
* Copyright (c) 2003, 2020, 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.math.BigInteger;
29
30
import java.security.*;
31
import java.security.spec.AlgorithmParameterSpec;
32
import java.security.spec.RSAKeyGenParameterSpec;
33
34
import static java.math.BigInteger.*;
35
import sun.security.jca.JCAUtil;
36
import sun.security.rsa.RSAUtil.KeyType;
37
38
import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE;
39
import static sun.security.util.SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE;
40
41
/**
42
* RSA keypair generation. Standard algorithm, minimum key length 512 bit.
43
* We generate two random primes until we find two where phi is relative
44
* prime to the public exponent. Default exponent is 65537. It has only bit 0
45
* and bit 4 set, which makes it particularly efficient.
46
*
47
* @since 1.5
48
* @author Andreas Sterbenz
49
*/
50
public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
51
52
private static final BigInteger SQRT_2048;
53
private static final BigInteger SQRT_3072;
54
private static final BigInteger SQRT_4096;
55
56
static {
57
SQRT_2048 = TWO.pow(2047).sqrt();
58
SQRT_3072 = TWO.pow(3071).sqrt();
59
SQRT_4096 = TWO.pow(4095).sqrt();
60
}
61
62
// public exponent to use
63
private BigInteger publicExponent;
64
65
// size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
66
private int keySize;
67
68
private final KeyType type;
69
private AlgorithmParameterSpec keyParams;
70
71
// PRNG to use
72
private SecureRandom random;
73
74
// whether to generate key pairs following the new guidelines from
75
// FIPS 186-4 and later
76
private boolean useNew;
77
78
RSAKeyPairGenerator(KeyType type, int defKeySize) {
79
this.type = type;
80
// initialize to default in case the app does not call initialize()
81
initialize(defKeySize, null);
82
}
83
84
// initialize the generator. See JCA doc
85
public void initialize(int keySize, SecureRandom random) {
86
try {
87
initialize(new RSAKeyGenParameterSpec(keySize,
88
RSAKeyGenParameterSpec.F4), random);
89
} catch (InvalidAlgorithmParameterException iape) {
90
throw new InvalidParameterException(iape.getMessage());
91
}
92
}
93
94
// second initialize method. See JCA doc.
95
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
96
throws InvalidAlgorithmParameterException {
97
if (params instanceof RSAKeyGenParameterSpec == false) {
98
throw new InvalidAlgorithmParameterException
99
("Params must be instance of RSAKeyGenParameterSpec");
100
}
101
102
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
103
int tmpKeySize = rsaSpec.getKeysize();
104
BigInteger tmpPubExp = rsaSpec.getPublicExponent();
105
AlgorithmParameterSpec tmpParams = rsaSpec.getKeyParams();
106
107
// use the new approach for even key sizes >= 2048 AND when the
108
// public exponent is within FIPS valid range
109
boolean useNew = (tmpKeySize >= 2048 && ((tmpKeySize & 1) == 0));
110
111
if (tmpPubExp == null) {
112
tmpPubExp = RSAKeyGenParameterSpec.F4;
113
} else {
114
if (!tmpPubExp.testBit(0)) {
115
throw new InvalidAlgorithmParameterException
116
("Public exponent must be an odd number");
117
}
118
// current impl checks that F0 <= e < 2^keysize
119
// vs FIPS 186-4 checks that F4 <= e < 2^256
120
// for backward compatibility, we keep the same checks
121
BigInteger minValue = RSAKeyGenParameterSpec.F0;
122
int maxBitLength = tmpKeySize;
123
if (tmpPubExp.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
124
throw new InvalidAlgorithmParameterException
125
("Public exponent must be " + minValue + " or larger");
126
}
127
if (tmpPubExp.bitLength() > maxBitLength) {
128
throw new InvalidAlgorithmParameterException
129
("Public exponent must be no longer than " +
130
maxBitLength + " bits");
131
}
132
useNew &= ((tmpPubExp.compareTo(RSAKeyGenParameterSpec.F4) >= 0) &&
133
(tmpPubExp.bitLength() < 256));
134
}
135
136
// do not allow unreasonably large key sizes, probably user error
137
try {
138
RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPubExp, 512,
139
64 * 1024);
140
} catch (InvalidKeyException e) {
141
throw new InvalidAlgorithmParameterException(
142
"Invalid key sizes", e);
143
}
144
145
try {
146
this.keyParams = RSAUtil.checkParamsAgainstType(type, tmpParams);
147
} catch (ProviderException e) {
148
throw new InvalidAlgorithmParameterException(
149
"Invalid key parameters", e);
150
}
151
152
this.keySize = tmpKeySize;
153
this.publicExponent = tmpPubExp;
154
this.random = (random == null? JCAUtil.getSecureRandom() : random);
155
this.useNew = useNew;
156
}
157
158
// FIPS 186-4 B.3.3 / FIPS 186-5 A.1.3
159
// Generation of Random Primes that are Probably Prime
160
public KeyPair generateKeyPair() {
161
BigInteger e = publicExponent;
162
BigInteger minValue = (useNew? getSqrt(keySize) : ZERO);
163
int lp = (keySize + 1) >> 1;;
164
int lq = keySize - lp;
165
int pqDiffSize = lp - 100;
166
167
while (true) {
168
BigInteger p = null;
169
BigInteger q = null;
170
171
int i = 0;
172
while (i++ < 10*lp) {
173
BigInteger tmpP = BigInteger.probablePrime(lp, random);
174
if ((!useNew || tmpP.compareTo(minValue) == 1) &&
175
isRelativePrime(e, tmpP.subtract(ONE))) {
176
p = tmpP;
177
break;
178
}
179
}
180
if (p == null) {
181
throw new ProviderException("Cannot find prime P");
182
}
183
184
i = 0;
185
186
while (i++ < 20*lq) {
187
BigInteger tmpQ = BigInteger.probablePrime(lq, random);
188
189
if ((!useNew || tmpQ.compareTo(minValue) == 1) &&
190
(p.subtract(tmpQ).abs().compareTo
191
(TWO.pow(pqDiffSize)) == 1) &&
192
isRelativePrime(e, tmpQ.subtract(ONE))) {
193
q = tmpQ;
194
break;
195
}
196
}
197
if (q == null) {
198
throw new ProviderException("Cannot find prime Q");
199
}
200
201
BigInteger n = p.multiply(q);
202
if (n.bitLength() != keySize) {
203
// regenerate P, Q if n is not the right length; should
204
// never happen for the new case but check it anyway
205
continue;
206
}
207
208
KeyPair kp = createKeyPair(type, keyParams, n, e, p, q);
209
// done, return the generated keypair;
210
if (kp != null) return kp;
211
}
212
}
213
214
private static BigInteger getSqrt(int keySize) {
215
BigInteger sqrt = null;
216
switch (keySize) {
217
case 2048:
218
sqrt = SQRT_2048;
219
break;
220
case 3072:
221
sqrt = SQRT_3072;
222
break;
223
case 4096:
224
sqrt = SQRT_4096;
225
break;
226
default:
227
sqrt = TWO.pow(keySize-1).sqrt();
228
}
229
return sqrt;
230
}
231
232
private static boolean isRelativePrime(BigInteger e, BigInteger bi) {
233
// optimize for common known public exponent prime values
234
if (e.compareTo(RSAKeyGenParameterSpec.F4) == 0 ||
235
e.compareTo(RSAKeyGenParameterSpec.F0) == 0) {
236
return !bi.mod(e).equals(ZERO);
237
} else {
238
return e.gcd(bi).equals(ONE);
239
}
240
}
241
242
private static KeyPair createKeyPair(KeyType type,
243
AlgorithmParameterSpec keyParams,
244
BigInteger n, BigInteger e, BigInteger p, BigInteger q) {
245
// phi = (p - 1) * (q - 1) must be relative prime to e
246
// otherwise RSA just won't work ;-)
247
BigInteger p1 = p.subtract(ONE);
248
BigInteger q1 = q.subtract(ONE);
249
BigInteger phi = p1.multiply(q1);
250
251
BigInteger gcd = p1.gcd(q1);
252
BigInteger lcm = (gcd.equals(ONE)? phi : phi.divide(gcd));
253
254
BigInteger d = e.modInverse(lcm);
255
256
if (d.compareTo(TWO.pow(p.bitLength())) != 1) {
257
return null;
258
}
259
260
// 1st prime exponent pe = d mod (p - 1)
261
BigInteger pe = d.mod(p1);
262
// 2nd prime exponent qe = d mod (q - 1)
263
BigInteger qe = d.mod(q1);
264
// crt coefficient coeff is the inverse of q mod p
265
BigInteger coeff = q.modInverse(p);
266
267
try {
268
PublicKey publicKey = new RSAPublicKeyImpl(type, keyParams, n, e);
269
PrivateKey privateKey = new RSAPrivateCrtKeyImpl(
270
type, keyParams, n, e, d, p, q, pe, qe, coeff);
271
return new KeyPair(publicKey, privateKey);
272
} catch (InvalidKeyException exc) {
273
// invalid key exception only thrown for keys < 512 bit,
274
// will not happen here
275
throw new RuntimeException(exc);
276
}
277
}
278
279
public static final class Legacy extends RSAKeyPairGenerator {
280
public Legacy() {
281
super(KeyType.RSA, DEF_RSA_KEY_SIZE);
282
}
283
}
284
285
public static final class PSS extends RSAKeyPairGenerator {
286
public PSS() {
287
super(KeyType.PSS, DEF_RSASSA_PSS_KEY_SIZE);
288
}
289
}
290
}
291
292