Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java
41161 views
1
/*
2
* Copyright (c) 1996, 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.tools.keytool;
27
28
import java.io.IOException;
29
import java.security.cert.X509Certificate;
30
import java.security.cert.CertificateException;
31
import java.security.cert.CertificateEncodingException;
32
import java.security.*;
33
import java.security.spec.ECGenParameterSpec;
34
import java.security.spec.NamedParameterSpec;
35
import java.util.Date;
36
37
import sun.security.pkcs10.PKCS10;
38
import sun.security.util.SignatureUtil;
39
import sun.security.x509.*;
40
41
/**
42
* Generate a pair of keys, and provide access to them. This class is
43
* provided primarily for ease of use.
44
*
45
* <P>This provides some simple certificate management functionality.
46
* Specifically, it allows you to create self-signed X.509 certificates
47
* as well as PKCS 10 based certificate signing requests.
48
*
49
* <P>Keys for some public key signature algorithms have algorithm
50
* parameters, such as DSS/DSA. Some sites' Certificate Authorities
51
* adopt fixed algorithm parameters, which speeds up some operations
52
* including key generation and signing. <em>At this time, this interface
53
* supports initializing with a named group.</em>
54
*
55
* <P>Also, note that at this time only signature-capable keys may be
56
* acquired through this interface. Diffie-Hellman keys, used for secure
57
* key exchange, may be supported later.
58
*
59
* @author David Brownell
60
* @author Hemma Prafullchandra
61
* @see PKCS10
62
* @see X509CertImpl
63
*/
64
public final class CertAndKeyGen {
65
/**
66
* Creates a CertAndKeyGen object for a particular key type
67
* and signature algorithm.
68
*
69
* @param keyType type of key, e.g. "RSA", "DSA"
70
* @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
71
* "MD2WithRSA", "SHAwithDSA". If set to null, a default
72
* algorithm matching the private key will be chosen after
73
* the first keypair is generated.
74
* @exception NoSuchAlgorithmException on unrecognized algorithms.
75
*/
76
public CertAndKeyGen (String keyType, String sigAlg)
77
throws NoSuchAlgorithmException
78
{
79
keyGen = KeyPairGenerator.getInstance(keyType);
80
this.sigAlg = sigAlg;
81
this.keyType = keyType;
82
}
83
84
/**
85
* @see #CertAndKeyGen(String, String, String, PrivateKey, X500Name)
86
*/
87
public CertAndKeyGen (String keyType, String sigAlg, String providerName)
88
throws NoSuchAlgorithmException, NoSuchProviderException
89
{
90
this(keyType, sigAlg, providerName, null, null);
91
}
92
93
/**
94
* Creates a CertAndKeyGen object for a particular key type,
95
* signature algorithm, and provider. The newly generated cert will
96
* be signed by the signer's private key when it is provided.
97
*
98
* @param keyType type of key, e.g. "RSA", "DSA", "X25519", "DH", etc.
99
* @param sigAlg name of the signature algorithm, e.g. "SHA384WithRSA",
100
* "SHA256withDSA", etc. If set to null, a default
101
* algorithm matching the private key or signer's private
102
* key will be chosen after the first keypair is generated.
103
* @param providerName name of the provider
104
* @param signerPrivateKey (optional) signer's private key
105
* @param signerSubjectName (optional) signer's subject name
106
* @exception NoSuchAlgorithmException on unrecognized algorithms.
107
* @exception NoSuchProviderException on unrecognized providers.
108
*/
109
public CertAndKeyGen(String keyType, String sigAlg, String providerName,
110
PrivateKey signerPrivateKey, X500Name signerSubjectName)
111
throws NoSuchAlgorithmException, NoSuchProviderException
112
{
113
if (providerName == null) {
114
keyGen = KeyPairGenerator.getInstance(keyType);
115
} else {
116
try {
117
keyGen = KeyPairGenerator.getInstance(keyType, providerName);
118
} catch (Exception e) {
119
// try first available provider instead
120
keyGen = KeyPairGenerator.getInstance(keyType);
121
}
122
}
123
this.sigAlg = sigAlg;
124
this.keyType = keyType;
125
this.signerPrivateKey = signerPrivateKey;
126
this.signerSubjectName = signerSubjectName;
127
this.signerFlag = signerPrivateKey != null;
128
}
129
130
/**
131
* Sets the source of random numbers used when generating keys.
132
* If you do not provide one, a system default facility is used.
133
* You may wish to provide your own source of random numbers
134
* to get a reproducible sequence of keys and signatures, or
135
* because you may be able to take advantage of strong sources
136
* of randomness/entropy in your environment.
137
*/
138
public void setRandom (SecureRandom generator)
139
{
140
prng = generator;
141
}
142
143
public void generate(String name) {
144
try {
145
if (prng == null) {
146
prng = new SecureRandom();
147
}
148
try {
149
keyGen.initialize(new NamedParameterSpec(name), prng);
150
} catch (InvalidAlgorithmParameterException e) {
151
if (keyType.equalsIgnoreCase("EC")) {
152
// EC has another NamedParameterSpec
153
keyGen.initialize(new ECGenParameterSpec(name), prng);
154
} else {
155
throw e;
156
}
157
}
158
159
} catch (Exception e) {
160
throw new IllegalArgumentException(e.getMessage());
161
}
162
generateInternal();
163
}
164
165
// want "public void generate (X509Certificate)" ... inherit DSA/D-H param
166
167
public void generate(int keyBits) {
168
if (keyBits != -1) {
169
try {
170
if (prng == null) {
171
prng = new SecureRandom();
172
}
173
keyGen.initialize(keyBits, prng);
174
175
} catch (Exception e) {
176
throw new IllegalArgumentException(e.getMessage());
177
}
178
}
179
generateInternal();
180
}
181
182
/**
183
* Generates a random public/private key pair.
184
*
185
* <P>Note that not all public key algorithms are currently
186
* supported for use in X.509 certificates. If the algorithm
187
* you specified does not produce X.509 compatible keys, an
188
* invalid key exception is thrown.
189
*
190
* @exception IllegalArgumentException if the environment does not
191
* provide X.509 public keys for this signature algorithm.
192
*/
193
private void generateInternal() {
194
KeyPair pair = keyGen.generateKeyPair();
195
publicKey = pair.getPublic();
196
privateKey = pair.getPrivate();
197
198
// publicKey's format must be X.509 otherwise
199
// the whole CertGen part of this class is broken.
200
if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) {
201
throw new IllegalArgumentException("Public key format is "
202
+ publicKey.getFormat() + ", must be X.509");
203
}
204
205
if (sigAlg == null) {
206
if (signerFlag) {
207
sigAlg = SignatureUtil.getDefaultSigAlgForKey(signerPrivateKey);
208
if (sigAlg == null) {
209
throw new IllegalArgumentException(
210
"Cannot derive signature algorithm from "
211
+ signerPrivateKey.getAlgorithm());
212
}
213
} else {
214
sigAlg = SignatureUtil.getDefaultSigAlgForKey(privateKey);
215
if (sigAlg == null) {
216
throw new IllegalArgumentException(
217
"Cannot derive signature algorithm from "
218
+ privateKey.getAlgorithm());
219
}
220
}
221
}
222
}
223
224
/**
225
* Returns the public key of the generated key pair if it is of type
226
* <code>X509Key</code>, or null if the public key is of a different type.
227
*
228
* XXX Note: This behaviour is needed for backwards compatibility.
229
* What this method really should return is the public key of the
230
* generated key pair, regardless of whether or not it is an instance of
231
* <code>X509Key</code>. Accordingly, the return type of this method
232
* should be <code>PublicKey</code>.
233
*/
234
public X509Key getPublicKey()
235
{
236
if (!(publicKey instanceof X509Key)) {
237
return null;
238
}
239
return (X509Key)publicKey;
240
}
241
242
/**
243
* Always returns the public key of the generated key pair. Used
244
* by KeyTool only.
245
*
246
* The publicKey is not necessarily to be an instance of
247
* X509Key in some JCA/JCE providers, for example SunPKCS11.
248
*/
249
public PublicKey getPublicKeyAnyway() {
250
return publicKey;
251
}
252
253
/**
254
* Returns the private key of the generated key pair.
255
*
256
* <P><STRONG><em>Be extremely careful when handling private keys.
257
* When private keys are not kept secret, they lose their ability
258
* to securely authenticate specific entities ... that is a huge
259
* security risk!</em></STRONG>
260
*/
261
public PrivateKey getPrivateKey ()
262
{
263
return privateKey;
264
}
265
266
/**
267
* Returns a self-signed X.509v3 certificate for the public key.
268
* The certificate is immediately valid. No extensions.
269
*
270
* <P>Such certificates normally are used to identify a "Certificate
271
* Authority" (CA). Accordingly, they will not always be accepted by
272
* other parties. However, such certificates are also useful when
273
* you are bootstrapping your security infrastructure, or deploying
274
* system prototypes.
275
*
276
* @param myname X.500 name of the subject (who is also the issuer)
277
* @param firstDate the issue time of the certificate
278
* @param validity how long the certificate should be valid, in seconds
279
* @exception CertificateException on certificate handling errors.
280
* @exception InvalidKeyException on key handling errors.
281
* @exception SignatureException on signature handling errors.
282
* @exception NoSuchAlgorithmException on unrecognized algorithms.
283
* @exception NoSuchProviderException on unrecognized providers.
284
*/
285
public X509Certificate getSelfCertificate (
286
X500Name myname, Date firstDate, long validity)
287
throws CertificateException, InvalidKeyException, SignatureException,
288
NoSuchAlgorithmException, NoSuchProviderException
289
{
290
return getSelfCertificate(myname, firstDate, validity, null);
291
}
292
293
// Like above, plus a CertificateExtensions argument, which can be null.
294
// Create a self-signed certificate, or a certificate that is signed by
295
// a signer when the signer's private key is provided.
296
public X509Certificate getSelfCertificate (X500Name myname, Date firstDate,
297
long validity, CertificateExtensions ext)
298
throws CertificateException, InvalidKeyException, SignatureException,
299
NoSuchAlgorithmException, NoSuchProviderException
300
{
301
X509CertImpl cert;
302
Date lastDate;
303
304
try {
305
lastDate = new Date ();
306
lastDate.setTime (firstDate.getTime () + validity * 1000);
307
308
CertificateValidity interval =
309
new CertificateValidity(firstDate,lastDate);
310
311
X509CertInfo info = new X509CertInfo();
312
// Add all mandatory attributes
313
info.set(X509CertInfo.VERSION,
314
new CertificateVersion(CertificateVersion.V3));
315
if (prng == null) {
316
prng = new SecureRandom();
317
}
318
info.set(X509CertInfo.SERIAL_NUMBER,
319
CertificateSerialNumber.newRandom64bit(prng));
320
info.set(X509CertInfo.SUBJECT, myname);
321
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
322
info.set(X509CertInfo.VALIDITY, interval);
323
if (signerFlag) {
324
// use signer's subject name to set the issuer name
325
info.set(X509CertInfo.ISSUER, signerSubjectName);
326
} else {
327
info.set(X509CertInfo.ISSUER, myname);
328
}
329
if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
330
331
cert = new X509CertImpl(info);
332
if (signerFlag) {
333
// use signer's private key to sign
334
cert.sign(signerPrivateKey, sigAlg);
335
} else {
336
cert.sign(privateKey, sigAlg);
337
}
338
339
return cert;
340
341
} catch (IOException e) {
342
throw new CertificateEncodingException("getSelfCert: " +
343
e.getMessage());
344
}
345
}
346
347
// Keep the old method
348
public X509Certificate getSelfCertificate (X500Name myname, long validity)
349
throws CertificateException, InvalidKeyException, SignatureException,
350
NoSuchAlgorithmException, NoSuchProviderException
351
{
352
return getSelfCertificate(myname, new Date(), validity);
353
}
354
355
private SecureRandom prng;
356
private String keyType;
357
private String sigAlg;
358
private KeyPairGenerator keyGen;
359
private PublicKey publicKey;
360
private PrivateKey privateKey;
361
private boolean signerFlag;
362
private PrivateKey signerPrivateKey;
363
private X500Name signerSubjectName;
364
}
365
366