1 /*
2 * Copyright (c) 1996, 2014, 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.util.Date;
34
35 import sun.security.pkcs10.PKCS10;
36 import sun.security.x509.*;
37
38
39 /**
40 * Generate a pair of keys, and provide access to them. This class is
41 * provided primarily for ease of use.
42 *
43 * <P>This provides some simple certificate management functionality.
44 * Specifically, it allows you to create self-signed X.509 certificates
45 * as well as PKCS 10 based certificate signing requests.
46 *
47 * <P>Keys for some public key signature algorithms have algorithm
48 * parameters, such as DSS/DSA. Some sites' Certificate Authorities
49 * adopt fixed algorithm parameters, which speeds up some operations
50 * including key generation and signing. <em>At this time, this interface
51 * does not provide a way to provide such algorithm parameters, e.g.
52 * by providing the CA certificate which includes those parameters.</em>
53 *
54 * <P>Also, note that at this time only signature-capable keys may be
55 * acquired through this interface. Diffie-Hellman keys, used for secure
56 * key exchange, may be supported later.
57 *
58 * @author David Brownell
106 }
107 }
108 this.sigAlg = sigAlg;
109 }
110
111 /**
112 * Sets the source of random numbers used when generating keys.
113 * If you do not provide one, a system default facility is used.
114 * You may wish to provide your own source of random numbers
115 * to get a reproducible sequence of keys and signatures, or
116 * because you may be able to take advantage of strong sources
117 * of randomness/entropy in your environment.
118 */
119 public void setRandom (SecureRandom generator)
120 {
121 prng = generator;
122 }
123
124 // want "public void generate (X509Certificate)" ... inherit DSA/D-H param
125
126 /**
127 * Generates a random public/private key pair, with a given key
128 * size. Different algorithms provide different degrees of security
129 * for the same key size, because of the "work factor" involved in
130 * brute force attacks. As computers become faster, it becomes
131 * easier to perform such attacks. Small keys are to be avoided.
132 *
133 * <P>Note that not all values of "keyBits" are valid for all
134 * algorithms, and not all public key algorithms are currently
135 * supported for use in X.509 certificates. If the algorithm
136 * you specified does not produce X.509 compatible keys, an
137 * invalid key exception is thrown.
138 *
139 * @param keyBits the number of bits in the keys.
140 * @exception InvalidKeyException if the environment does not
141 * provide X.509 public keys for this signature algorithm.
142 */
143 public void generate (int keyBits)
144 throws InvalidKeyException
145 {
146 KeyPair pair;
147
148 try {
149 if (prng == null) {
150 prng = new SecureRandom();
151 }
152 keyGen.initialize(keyBits, prng);
153 pair = keyGen.generateKeyPair();
154
155 } catch (Exception e) {
156 throw new IllegalArgumentException(e.getMessage());
157 }
158
159 publicKey = pair.getPublic();
160 privateKey = pair.getPrivate();
161
162 // publicKey's format must be X.509 otherwise
163 // the whole CertGen part of this class is broken.
164 if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) {
165 throw new IllegalArgumentException("Public key format is "
166 + publicKey.getFormat() + ", must be X.509");
167 }
168
169 if (sigAlg == null) {
170 sigAlg = AlgorithmId.getDefaultSigAlgForKey(privateKey);
171 if (sigAlg == null) {
172 throw new IllegalArgumentException(
173 "Cannot derive signature algorithm from "
174 + privateKey.getAlgorithm());
175 }
176 }
177 }
245 return getSelfCertificate(myname, firstDate, validity, null);
246 }
247
248 // Like above, plus a CertificateExtensions argument, which can be null.
249 public X509Certificate getSelfCertificate (X500Name myname, Date firstDate,
250 long validity, CertificateExtensions ext)
251 throws CertificateException, InvalidKeyException, SignatureException,
252 NoSuchAlgorithmException, NoSuchProviderException
253 {
254 X509CertImpl cert;
255 Date lastDate;
256
257 try {
258 lastDate = new Date ();
259 lastDate.setTime (firstDate.getTime () + validity * 1000);
260
261 CertificateValidity interval =
262 new CertificateValidity(firstDate,lastDate);
263
264 X509CertInfo info = new X509CertInfo();
265 // Add all mandatory attributes
266 info.set(X509CertInfo.VERSION,
267 new CertificateVersion(CertificateVersion.V3));
268 info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(
269 new java.util.Random().nextInt() & 0x7fffffff));
270 AlgorithmId algID = AlgorithmId.get(sigAlg);
271 info.set(X509CertInfo.ALGORITHM_ID,
272 new CertificateAlgorithmId(algID));
273 info.set(X509CertInfo.SUBJECT, myname);
274 info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
275 info.set(X509CertInfo.VALIDITY, interval);
276 info.set(X509CertInfo.ISSUER, myname);
277 if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
278
279 cert = new X509CertImpl(info);
280 cert.sign(privateKey, this.sigAlg);
281
282 return (X509Certificate)cert;
283
284 } catch (IOException e) {
285 throw new CertificateEncodingException("getSelfCert: " +
286 e.getMessage());
287 }
288 }
289
290 // Keep the old method
291 public X509Certificate getSelfCertificate (X500Name myname, long validity)
292 throws CertificateException, InvalidKeyException, SignatureException,
293 NoSuchAlgorithmException, NoSuchProviderException
294 {
295 return getSelfCertificate(myname, new Date(), validity);
296 }
297
298 /**
299 * Returns a PKCS #10 certificate request. The caller uses either
300 * <code>PKCS10.print</code> or <code>PKCS10.toByteArray</code>
301 * operations on the result, to get the request in an appropriate
302 * transmission format.
303 *
304 * <P>PKCS #10 certificate requests are sent, along with some proof
305 * of identity, to Certificate Authorities (CAs) which then issue
306 * X.509 public key certificates.
307 *
308 * @param myname X.500 name of the subject
309 * @exception InvalidKeyException on key handling errors.
310 * @exception SignatureException on signature handling errors.
311 */
312 public PKCS10 getCertRequest (X500Name myname)
313 throws InvalidKeyException, SignatureException
314 {
315 PKCS10 req = new PKCS10 (publicKey);
316
317 try {
318 Signature signature = Signature.getInstance(sigAlg);
319 signature.initSign (privateKey);
320 req.encodeAndSign(myname, signature);
321
322 } catch (CertificateException e) {
323 throw new SignatureException (sigAlg + " CertificateException");
324
325 } catch (IOException e) {
326 throw new SignatureException (sigAlg + " IOException");
327
328 } catch (NoSuchAlgorithmException e) {
329 // "can't happen"
330 throw new SignatureException (sigAlg + " unavailable?");
331 }
|
1 /*
2 * Copyright (c) 1996, 2019, 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.AlgorithmParameterSpec;
34 import java.util.Date;
35
36 import sun.security.pkcs10.PKCS10;
37 import sun.security.x509.*;
38
39 /**
40 * Generate a pair of keys, and provide access to them. This class is
41 * provided primarily for ease of use.
42 *
43 * <P>This provides some simple certificate management functionality.
44 * Specifically, it allows you to create self-signed X.509 certificates
45 * as well as PKCS 10 based certificate signing requests.
46 *
47 * <P>Keys for some public key signature algorithms have algorithm
48 * parameters, such as DSS/DSA. Some sites' Certificate Authorities
49 * adopt fixed algorithm parameters, which speeds up some operations
50 * including key generation and signing. <em>At this time, this interface
51 * does not provide a way to provide such algorithm parameters, e.g.
52 * by providing the CA certificate which includes those parameters.</em>
53 *
54 * <P>Also, note that at this time only signature-capable keys may be
55 * acquired through this interface. Diffie-Hellman keys, used for secure
56 * key exchange, may be supported later.
57 *
58 * @author David Brownell
106 }
107 }
108 this.sigAlg = sigAlg;
109 }
110
111 /**
112 * Sets the source of random numbers used when generating keys.
113 * If you do not provide one, a system default facility is used.
114 * You may wish to provide your own source of random numbers
115 * to get a reproducible sequence of keys and signatures, or
116 * because you may be able to take advantage of strong sources
117 * of randomness/entropy in your environment.
118 */
119 public void setRandom (SecureRandom generator)
120 {
121 prng = generator;
122 }
123
124 // want "public void generate (X509Certificate)" ... inherit DSA/D-H param
125
126 public void generate(int keyBits) {
127 if (keyBits != -1) {
128 try {
129 if (prng == null) {
130 prng = new SecureRandom();
131 }
132 keyGen.initialize(keyBits, prng);
133
134 } catch (Exception e) {
135 throw new IllegalArgumentException(e.getMessage());
136 }
137 }
138 generateInternal();
139 }
140
141 /**
142 * Generates a random public/private key pair, with a given key
143 * size. Different algorithms provide different degrees of security
144 * for the same key size, because of the "work factor" involved in
145 * brute force attacks. As computers become faster, it becomes
146 * easier to perform such attacks. Small keys are to be avoided.
147 *
148 * <P>Note that not all values of "keyBits" are valid for all
149 * algorithms, and not all public key algorithms are currently
150 * supported for use in X.509 certificates. If the algorithm
151 * you specified does not produce X.509 compatible keys, an
152 * invalid key exception is thrown.
153 *
154 * @param keyBits the number of bits in the keys.
155 * @exception InvalidKeyException if the environment does not
156 * provide X.509 public keys for this signature algorithm.
157 */
158 public void generateInternal() {
159 KeyPair pair = keyGen.generateKeyPair();
160
161 publicKey = pair.getPublic();
162 privateKey = pair.getPrivate();
163
164 // publicKey's format must be X.509 otherwise
165 // the whole CertGen part of this class is broken.
166 if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) {
167 throw new IllegalArgumentException("Public key format is "
168 + publicKey.getFormat() + ", must be X.509");
169 }
170
171 if (sigAlg == null) {
172 sigAlg = AlgorithmId.getDefaultSigAlgForKey(privateKey);
173 if (sigAlg == null) {
174 throw new IllegalArgumentException(
175 "Cannot derive signature algorithm from "
176 + privateKey.getAlgorithm());
177 }
178 }
179 }
247 return getSelfCertificate(myname, firstDate, validity, null);
248 }
249
250 // Like above, plus a CertificateExtensions argument, which can be null.
251 public X509Certificate getSelfCertificate (X500Name myname, Date firstDate,
252 long validity, CertificateExtensions ext)
253 throws CertificateException, InvalidKeyException, SignatureException,
254 NoSuchAlgorithmException, NoSuchProviderException
255 {
256 X509CertImpl cert;
257 Date lastDate;
258
259 try {
260 lastDate = new Date ();
261 lastDate.setTime (firstDate.getTime () + validity * 1000);
262
263 CertificateValidity interval =
264 new CertificateValidity(firstDate,lastDate);
265
266 X509CertInfo info = new X509CertInfo();
267 AlgorithmParameterSpec params = AlgorithmId
268 .getDefaultAlgorithmParameterSpec(sigAlg, privateKey);
269 // Add all mandatory attributes
270 info.set(X509CertInfo.VERSION,
271 new CertificateVersion(CertificateVersion.V3));
272 info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(
273 new java.util.Random().nextInt() & 0x7fffffff));
274 AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlg, params);
275 info.set(X509CertInfo.ALGORITHM_ID,
276 new CertificateAlgorithmId(algID));
277 info.set(X509CertInfo.SUBJECT, myname);
278 info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
279 info.set(X509CertInfo.VALIDITY, interval);
280 info.set(X509CertInfo.ISSUER, myname);
281 if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
282
283 cert = new X509CertImpl(info);
284 cert.sign(privateKey,
285 params,
286 sigAlg,
287 null);
288
289 return (X509Certificate)cert;
290
291 } catch (IOException e) {
292 throw new CertificateEncodingException("getSelfCert: " +
293 e.getMessage());
294 } catch (InvalidAlgorithmParameterException e2) {
295 throw new SignatureException(
296 "Unsupported PSSParameterSpec: " + e2.getMessage());
297 }
298 }
299
300 // Keep the old method
301 public X509Certificate getSelfCertificate (X500Name myname, long validity)
302 throws CertificateException, InvalidKeyException, SignatureException,
303 NoSuchAlgorithmException, NoSuchProviderException
304 {
305 return getSelfCertificate(myname, new Date(), validity);
306 }
307
308 /**
309 * Returns a PKCS #10 certificate request. The caller uses either
310 * <code>PKCS10.print</code> or <code>PKCS10.toByteArray</code>
311 * operations on the result, to get the request in an appropriate
312 * transmission format.
313 *
314 * <P>PKCS #10 certificate requests are sent, along with some proof
315 * of identity, to Certificate Authorities (CAs) which then issue
316 * X.509 public key certificates.
317 *
318 * @param myname X.500 name of the subject
319 * @exception InvalidKeyException on key handling errors.
320 * @exception SignatureException on signature handling errors.
321 */
322 // This method is not used inside JDK. Will not update it.
323 public PKCS10 getCertRequest (X500Name myname)
324 throws InvalidKeyException, SignatureException
325 {
326 PKCS10 req = new PKCS10 (publicKey);
327
328 try {
329 Signature signature = Signature.getInstance(sigAlg);
330 signature.initSign (privateKey);
331 req.encodeAndSign(myname, signature);
332
333 } catch (CertificateException e) {
334 throw new SignatureException (sigAlg + " CertificateException");
335
336 } catch (IOException e) {
337 throw new SignatureException (sigAlg + " IOException");
338
339 } catch (NoSuchAlgorithmException e) {
340 // "can't happen"
341 throw new SignatureException (sigAlg + " unavailable?");
342 }
|