Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/tools/keytool/CertAndKeyGen.java
38923 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.tools.keytool;2627import java.io.IOException;28import java.security.cert.X509Certificate;29import java.security.cert.CertificateException;30import java.security.cert.CertificateEncodingException;31import java.security.*;32import java.security.spec.AlgorithmParameterSpec;33import java.util.Date;3435import sun.security.pkcs10.PKCS10;36import sun.security.x509.*;3738/**39* Generate a pair of keys, and provide access to them. This class is40* provided primarily for ease of use.41*42* <P>This provides some simple certificate management functionality.43* Specifically, it allows you to create self-signed X.509 certificates44* as well as PKCS 10 based certificate signing requests.45*46* <P>Keys for some public key signature algorithms have algorithm47* parameters, such as DSS/DSA. Some sites' Certificate Authorities48* adopt fixed algorithm parameters, which speeds up some operations49* including key generation and signing. <em>At this time, this interface50* does not provide a way to provide such algorithm parameters, e.g.51* by providing the CA certificate which includes those parameters.</em>52*53* <P>Also, note that at this time only signature-capable keys may be54* acquired through this interface. Diffie-Hellman keys, used for secure55* key exchange, may be supported later.56*57* @author David Brownell58* @author Hemma Prafullchandra59* @see PKCS1060* @see X509CertImpl61*/62public final class CertAndKeyGen {63/**64* Creates a CertAndKeyGen object for a particular key type65* and signature algorithm.66*67* @param keyType type of key, e.g. "RSA", "DSA"68* @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",69* "MD2WithRSA", "SHAwithDSA".70* @exception NoSuchAlgorithmException on unrecognized algorithms.71*/72public CertAndKeyGen (String keyType, String sigAlg)73throws NoSuchAlgorithmException74{75keyGen = KeyPairGenerator.getInstance(keyType);76this.sigAlg = sigAlg;77}7879/**80* Creates a CertAndKeyGen object for a particular key type,81* signature algorithm, and provider.82*83* @param keyType type of key, e.g. "RSA", "DSA"84* @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",85* "MD2WithRSA", "SHAwithDSA".86* @param providerName name of the provider87* @exception NoSuchAlgorithmException on unrecognized algorithms.88* @exception NoSuchProviderException on unrecognized providers.89*/90public CertAndKeyGen (String keyType, String sigAlg, String providerName)91throws NoSuchAlgorithmException, NoSuchProviderException92{93if (providerName == null) {94keyGen = KeyPairGenerator.getInstance(keyType);95} else {96try {97keyGen = KeyPairGenerator.getInstance(keyType, providerName);98} catch (Exception e) {99// try first available provider instead100keyGen = KeyPairGenerator.getInstance(keyType);101}102}103this.sigAlg = sigAlg;104}105106/**107* Sets the source of random numbers used when generating keys.108* If you do not provide one, a system default facility is used.109* You may wish to provide your own source of random numbers110* to get a reproducible sequence of keys and signatures, or111* because you may be able to take advantage of strong sources112* of randomness/entropy in your environment.113*/114public void setRandom (SecureRandom generator)115{116prng = generator;117}118119// want "public void generate (X509Certificate)" ... inherit DSA/D-H param120121/**122* Generates a random public/private key pair, with a given key123* size. Different algorithms provide different degrees of security124* for the same key size, because of the "work factor" involved in125* brute force attacks. As computers become faster, it becomes126* easier to perform such attacks. Small keys are to be avoided.127*128* <P>Note that not all values of "keyBits" are valid for all129* algorithms, and not all public key algorithms are currently130* supported for use in X.509 certificates. If the algorithm131* you specified does not produce X.509 compatible keys, an132* invalid key exception is thrown.133*134* @param keyBits the number of bits in the keys.135* @exception InvalidKeyException if the environment does not136* provide X.509 public keys for this signature algorithm.137*/138public void generate (int keyBits)139throws InvalidKeyException140{141KeyPair pair;142143try {144if (prng == null) {145prng = new SecureRandom();146}147keyGen.initialize(keyBits, prng);148pair = keyGen.generateKeyPair();149150} catch (Exception e) {151throw new IllegalArgumentException(e.getMessage());152}153154publicKey = pair.getPublic();155privateKey = pair.getPrivate();156157// publicKey's format must be X.509 otherwise158// the whole CertGen part of this class is broken.159if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) {160throw new IllegalArgumentException("publicKey's is not X.509, but "161+ publicKey.getFormat());162}163}164165166/**167* Returns the public key of the generated key pair if it is of type168* <code>X509Key</code>, or null if the public key is of a different type.169*170* XXX Note: This behaviour is needed for backwards compatibility.171* What this method really should return is the public key of the172* generated key pair, regardless of whether or not it is an instance of173* <code>X509Key</code>. Accordingly, the return type of this method174* should be <code>PublicKey</code>.175*/176public X509Key getPublicKey()177{178if (!(publicKey instanceof X509Key)) {179return null;180}181return (X509Key)publicKey;182}183184/**185* Always returns the public key of the generated key pair. Used186* by KeyTool only.187*188* The publicKey is not necessarily to be an instance of189* X509Key in some JCA/JCE providers, for example SunPKCS11.190*/191public PublicKey getPublicKeyAnyway() {192return publicKey;193}194195/**196* Returns the private key of the generated key pair.197*198* <P><STRONG><em>Be extremely careful when handling private keys.199* When private keys are not kept secret, they lose their ability200* to securely authenticate specific entities ... that is a huge201* security risk!</em></STRONG>202*/203public PrivateKey getPrivateKey ()204{205return privateKey;206}207208/**209* Returns a self-signed X.509v3 certificate for the public key.210* The certificate is immediately valid. No extensions.211*212* <P>Such certificates normally are used to identify a "Certificate213* Authority" (CA). Accordingly, they will not always be accepted by214* other parties. However, such certificates are also useful when215* you are bootstrapping your security infrastructure, or deploying216* system prototypes.217*218* @param myname X.500 name of the subject (who is also the issuer)219* @param firstDate the issue time of the certificate220* @param validity how long the certificate should be valid, in seconds221* @exception CertificateException on certificate handling errors.222* @exception InvalidKeyException on key handling errors.223* @exception SignatureException on signature handling errors.224* @exception NoSuchAlgorithmException on unrecognized algorithms.225* @exception NoSuchProviderException on unrecognized providers.226*/227public X509Certificate getSelfCertificate (228X500Name myname, Date firstDate, long validity)229throws CertificateException, InvalidKeyException, SignatureException,230NoSuchAlgorithmException, NoSuchProviderException231{232return getSelfCertificate(myname, firstDate, validity, null);233}234235// Like above, plus a CertificateExtensions argument, which can be null.236public X509Certificate getSelfCertificate (X500Name myname, Date firstDate,237long validity, CertificateExtensions ext)238throws CertificateException, InvalidKeyException, SignatureException,239NoSuchAlgorithmException, NoSuchProviderException240{241X509CertImpl cert;242Date lastDate;243244try {245lastDate = new Date ();246lastDate.setTime (firstDate.getTime () + validity * 1000);247248CertificateValidity interval =249new CertificateValidity(firstDate,lastDate);250251X509CertInfo info = new X509CertInfo();252AlgorithmParameterSpec params = AlgorithmId253.getDefaultAlgorithmParameterSpec(sigAlg, privateKey);254// Add all mandatory attributes255info.set(X509CertInfo.VERSION,256new CertificateVersion(CertificateVersion.V3));257info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(258new java.util.Random().nextInt() & 0x7fffffff));259AlgorithmId algID = AlgorithmId.getWithParameterSpec(sigAlg, params);260info.set(X509CertInfo.ALGORITHM_ID,261new CertificateAlgorithmId(algID));262info.set(X509CertInfo.SUBJECT, myname);263info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));264info.set(X509CertInfo.VALIDITY, interval);265info.set(X509CertInfo.ISSUER, myname);266if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);267268cert = new X509CertImpl(info);269cert.sign(privateKey,270params,271sigAlg,272null);273274return (X509Certificate)cert;275276} catch (IOException e) {277throw new CertificateEncodingException("getSelfCert: " +278e.getMessage());279} catch (InvalidAlgorithmParameterException e2) {280throw new SignatureException(281"Unsupported PSSParameterSpec: " + e2.getMessage());282}283}284285// Keep the old method286public X509Certificate getSelfCertificate (X500Name myname, long validity)287throws CertificateException, InvalidKeyException, SignatureException,288NoSuchAlgorithmException, NoSuchProviderException289{290return getSelfCertificate(myname, new Date(), validity);291}292293/**294* Returns a PKCS #10 certificate request. The caller uses either295* <code>PKCS10.print</code> or <code>PKCS10.toByteArray</code>296* operations on the result, to get the request in an appropriate297* transmission format.298*299* <P>PKCS #10 certificate requests are sent, along with some proof300* of identity, to Certificate Authorities (CAs) which then issue301* X.509 public key certificates.302*303* @param myname X.500 name of the subject304* @exception InvalidKeyException on key handling errors.305* @exception SignatureException on signature handling errors.306*/307// This method is not used inside JDK. Will not update it.308public PKCS10 getCertRequest (X500Name myname)309throws InvalidKeyException, SignatureException310{311PKCS10 req = new PKCS10 (publicKey);312313try {314Signature signature = Signature.getInstance(sigAlg);315signature.initSign (privateKey);316req.encodeAndSign(myname, signature);317318} catch (CertificateException e) {319throw new SignatureException (sigAlg + " CertificateException");320321} catch (IOException e) {322throw new SignatureException (sigAlg + " IOException");323324} catch (NoSuchAlgorithmException e) {325// "can't happen"326throw new SignatureException (sigAlg + " unavailable?");327}328return req;329}330331private SecureRandom prng;332private String sigAlg;333private KeyPairGenerator keyGen;334private PublicKey publicKey;335private PrivateKey privateKey;336}337338339