< prev index next >

src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java

Print this page
rev 51972 : 8215694: keytool cannot generate RSASSA-PSS certificates
Reviewed-by: xuelei
rev 51973 : 8215694 resolve
   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         }
< prev index next >