Path: blob/master/src/java.base/share/classes/java/security/KeyPairGenerator.java
41152 views
/*1* Copyright (c) 1997, 2021, 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 java.security;2627import java.util.*;2829import java.security.spec.AlgorithmParameterSpec;3031import java.security.Provider.Service;3233import sun.security.jca.*;34import sun.security.jca.GetInstance.Instance;35import sun.security.util.Debug;3637/**38* The KeyPairGenerator class is used to generate pairs of39* public and private keys. Key pair generators are constructed using the40* {@code getInstance} factory methods (static methods that41* return instances of a given class).42*43* <p>A Key pair generator for a particular algorithm creates a public/private44* key pair that can be used with this algorithm. It also associates45* algorithm-specific parameters with each of the generated keys.46*47* <p>There are two ways to generate a key pair: in an algorithm-independent48* manner, and in an algorithm-specific manner.49* The only difference between the two is the initialization of the object:50*51* <ul>52* <li><b>Algorithm-Independent Initialization</b>53* <p>All key pair generators share the concepts of a keysize and a54* source of randomness. The keysize is interpreted differently for different55* algorithms (e.g., in the case of the <i>DSA</i> algorithm, the keysize56* corresponds to the length of the modulus).57* There is an58* {@link #initialize(int, java.security.SecureRandom) initialize}59* method in this KeyPairGenerator class that takes these two universally60* shared types of arguments. There is also one that takes just a61* {@code keysize} argument, and uses the {@code SecureRandom}62* implementation of the highest-priority installed provider as the source63* of randomness. (If none of the installed providers supply an implementation64* of {@code SecureRandom}, a system-provided source of randomness is65* used.)66*67* <p>Since no other parameters are specified when you call the above68* algorithm-independent {@code initialize} methods, it is up to the69* provider what to do about the algorithm-specific parameters (if any) to be70* associated with each of the keys.71*72* <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus73* size) is 512, 768, 1024, or 2048, then the <i>Sun</i> provider uses a set of74* precomputed values for the {@code p}, {@code q}, and75* {@code g} parameters. If the modulus size is not one of the above76* values, the <i>Sun</i> provider creates a new set of parameters. Other77* providers might have precomputed parameter sets for more than just the78* modulus sizes mentioned above. Still others might not have a list of79* precomputed parameters at all and instead always create new parameter sets.80*81* <li><b>Algorithm-Specific Initialization</b>82* <p>For situations where a set of algorithm-specific parameters already83* exists (e.g., so-called <i>community parameters</i> in DSA), there are two84* {@link #initialize(java.security.spec.AlgorithmParameterSpec)85* initialize} methods that have an {@code AlgorithmParameterSpec}86* argument. One also has a {@code SecureRandom} argument, while87* the other uses the {@code SecureRandom}88* implementation of the highest-priority installed provider as the source89* of randomness. (If none of the installed providers supply an implementation90* of {@code SecureRandom}, a system-provided source of randomness is91* used.)92* </ul>93*94* <p>In case the client does not explicitly initialize the KeyPairGenerator95* (via a call to an {@code initialize} method), each provider must96* supply (and document) a default initialization.97* See the Keysize Restriction sections of the98* {@extLink security_guide_jdk_providers JDK Providers}99* document for information on the KeyPairGenerator defaults used by100* JDK providers.101* However, note that defaults may vary across different providers.102* Additionally, the default value for a provider may change in a future103* version. Therefore, it is recommended to explicitly initialize the104* KeyPairGenerator instead of relying on provider-specific defaults.105*106* <p>Note that this class is abstract and extends from107* {@code KeyPairGeneratorSpi} for historical reasons.108* Application developers should only take notice of the methods defined in109* this {@code KeyPairGenerator} class; all the methods in110* the superclass are intended for cryptographic service providers who wish to111* supply their own implementations of key pair generators.112*113* <p> Every implementation of the Java platform is required to support the114* following standard {@code KeyPairGenerator} algorithms and keysizes in115* parentheses:116* <ul>117* <li>{@code DiffieHellman} (1024, 2048, 4096)</li>118* <li>{@code DSA} (1024, 2048)</li>119* <li>{@code RSA} (1024, 2048, 4096)</li>120* </ul>121* These algorithms are described in the <a href=122* "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">123* KeyPairGenerator section</a> of the124* Java Security Standard Algorithm Names Specification.125* Consult the release documentation for your implementation to see if any126* other algorithms are supported.127*128* @author Benjamin Renaud129* @since 1.1130*131* @see java.security.spec.AlgorithmParameterSpec132*/133134public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {135136private static final Debug pdebug =137Debug.getInstance("provider", "Provider");138private static final boolean skipDebug =139Debug.isOn("engine=") && !Debug.isOn("keypairgenerator");140141private final String algorithm;142143// The provider144Provider provider;145146/**147* Creates a KeyPairGenerator object for the specified algorithm.148*149* @param algorithm the standard string name of the algorithm.150* See the KeyPairGenerator section in the <a href=151* "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">152* Java Security Standard Algorithm Names Specification</a>153* for information about standard algorithm names.154*/155protected KeyPairGenerator(String algorithm) {156this.algorithm = algorithm;157}158159/**160* Returns the standard name of the algorithm for this key pair generator.161* See the KeyPairGenerator section in the <a href=162* "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">163* Java Security Standard Algorithm Names Specification</a>164* for information about standard algorithm names.165*166* @return the standard string name of the algorithm.167*/168public String getAlgorithm() {169return this.algorithm;170}171172private static KeyPairGenerator getInstance(Instance instance,173String algorithm) {174KeyPairGenerator kpg;175if (instance.impl instanceof KeyPairGenerator) {176kpg = (KeyPairGenerator)instance.impl;177} else {178KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl;179kpg = new Delegate(spi, algorithm);180}181kpg.provider = instance.provider;182183if (!skipDebug && pdebug != null) {184pdebug.println("KeyPairGenerator." + algorithm +185" algorithm from: " + kpg.provider.getName());186}187188return kpg;189}190191/**192* Returns a KeyPairGenerator object that generates public/private193* key pairs for the specified algorithm.194*195* <p> This method traverses the list of registered security Providers,196* starting with the most preferred Provider.197* A new KeyPairGenerator object encapsulating the198* KeyPairGeneratorSpi implementation from the first199* Provider that supports the specified algorithm is returned.200*201* <p> Note that the list of registered providers may be retrieved via202* the {@link Security#getProviders() Security.getProviders()} method.203*204* @implNote205* The JDK Reference Implementation additionally uses the206* {@code jdk.security.provider.preferred}207* {@link Security#getProperty(String) Security} property to determine208* the preferred provider order for the specified algorithm. This209* may be different than the order of providers returned by210* {@link Security#getProviders() Security.getProviders()}.211*212* @param algorithm the standard string name of the algorithm.213* See the KeyPairGenerator section in the <a href=214* "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">215* Java Security Standard Algorithm Names Specification</a>216* for information about standard algorithm names.217*218* @return the new {@code KeyPairGenerator} object219*220* @throws NoSuchAlgorithmException if no {@code Provider} supports a221* {@code KeyPairGeneratorSpi} implementation for the222* specified algorithm223*224* @throws NullPointerException if {@code algorithm} is {@code null}225*226* @see Provider227*/228public static KeyPairGenerator getInstance(String algorithm)229throws NoSuchAlgorithmException {230Objects.requireNonNull(algorithm, "null algorithm name");231List<Service> list =232GetInstance.getServices("KeyPairGenerator", algorithm);233Iterator<Service> t = list.iterator();234if (t.hasNext() == false) {235throw new NoSuchAlgorithmException236(algorithm + " KeyPairGenerator not available");237}238// find a working Spi or KeyPairGenerator subclass239NoSuchAlgorithmException failure = null;240do {241Service s = t.next();242try {243Instance instance =244GetInstance.getInstance(s, KeyPairGeneratorSpi.class);245if (instance.impl instanceof KeyPairGenerator) {246return getInstance(instance, algorithm);247} else {248return new Delegate(instance, t, algorithm);249}250} catch (NoSuchAlgorithmException e) {251if (failure == null) {252failure = e;253}254}255} while (t.hasNext());256throw failure;257}258259/**260* Returns a KeyPairGenerator object that generates public/private261* key pairs for the specified algorithm.262*263* <p> A new KeyPairGenerator object encapsulating the264* KeyPairGeneratorSpi implementation from the specified provider265* is returned. The specified provider must be registered266* in the security provider list.267*268* <p> Note that the list of registered providers may be retrieved via269* the {@link Security#getProviders() Security.getProviders()} method.270*271* @param algorithm the standard string name of the algorithm.272* See the KeyPairGenerator section in the <a href=273* "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">274* Java Security Standard Algorithm Names Specification</a>275* for information about standard algorithm names.276*277* @param provider the string name of the provider.278*279* @return the new {@code KeyPairGenerator} object280*281* @throws IllegalArgumentException if the provider name is {@code null}282* or empty283*284* @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}285* implementation for the specified algorithm is not286* available from the specified provider287*288* @throws NoSuchProviderException if the specified provider is not289* registered in the security provider list290*291* @throws NullPointerException if {@code algorithm} is {@code null}292*293* @see Provider294*/295public static KeyPairGenerator getInstance(String algorithm,296String provider)297throws NoSuchAlgorithmException, NoSuchProviderException {298Objects.requireNonNull(algorithm, "null algorithm name");299Instance instance = GetInstance.getInstance("KeyPairGenerator",300KeyPairGeneratorSpi.class, algorithm, provider);301return getInstance(instance, algorithm);302}303304/**305* Returns a KeyPairGenerator object that generates public/private306* key pairs for the specified algorithm.307*308* <p> A new KeyPairGenerator object encapsulating the309* KeyPairGeneratorSpi implementation from the specified Provider310* object is returned. Note that the specified Provider object311* does not have to be registered in the provider list.312*313* @param algorithm the standard string name of the algorithm.314* See the KeyPairGenerator section in the <a href=315* "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">316* Java Security Standard Algorithm Names Specification</a>317* for information about standard algorithm names.318*319* @param provider the provider.320*321* @return the new {@code KeyPairGenerator} object322*323* @throws IllegalArgumentException if the specified provider is324* {@code null}325*326* @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}327* implementation for the specified algorithm is not available328* from the specified {@code Provider} object329*330* @throws NullPointerException if {@code algorithm} is {@code null}331*332* @see Provider333*334* @since 1.4335*/336public static KeyPairGenerator getInstance(String algorithm,337Provider provider) throws NoSuchAlgorithmException {338Objects.requireNonNull(algorithm, "null algorithm name");339Instance instance = GetInstance.getInstance("KeyPairGenerator",340KeyPairGeneratorSpi.class, algorithm, provider);341return getInstance(instance, algorithm);342}343344/**345* Returns the provider of this key pair generator object.346*347* @return the provider of this key pair generator object348*/349public final Provider getProvider() {350disableFailover();351return this.provider;352}353354void disableFailover() {355// empty, overridden in Delegate356}357358/**359* Initializes the key pair generator for a certain keysize using360* a default parameter set and the {@code SecureRandom}361* implementation of the highest-priority installed provider as the source362* of randomness.363* (If none of the installed providers supply an implementation of364* {@code SecureRandom}, a system-provided source of randomness is365* used.)366*367* @param keysize the keysize. This is an368* algorithm-specific metric, such as modulus length, specified in369* number of bits.370*371* @throws InvalidParameterException if the {@code keysize} is not372* supported by this KeyPairGenerator object.373*/374public void initialize(int keysize) {375initialize(keysize, JCAUtil.getDefSecureRandom());376}377378/**379* Initializes the key pair generator for a certain keysize with380* the given source of randomness (and a default parameter set).381*382* @param keysize the keysize. This is an383* algorithm-specific metric, such as modulus length, specified in384* number of bits.385* @param random the source of randomness.386*387* @throws InvalidParameterException if the {@code keysize} is not388* supported by this KeyPairGenerator object.389*390* @since 1.2391*/392public void initialize(int keysize, SecureRandom random) {393// This does nothing, because either394// 1. the implementation object returned by getInstance() is an395// instance of KeyPairGenerator which has its own396// initialize(keysize, random) method, so the application would397// be calling that method directly, or398// 2. the implementation returned by getInstance() is an instance399// of Delegate, in which case initialize(keysize, random) is400// overridden to call the corresponding SPI method.401// (This is a special case, because the API and SPI method have the402// same name.)403}404405/**406* Initializes the key pair generator using the specified parameter407* set and the {@code SecureRandom}408* implementation of the highest-priority installed provider as the source409* of randomness.410* (If none of the installed providers supply an implementation of411* {@code SecureRandom}, a system-provided source of randomness is412* used.)413*414* <p>This concrete method has been added to this previously-defined415* abstract class.416* This method calls the KeyPairGeneratorSpi417* {@link KeyPairGeneratorSpi#initialize(418* java.security.spec.AlgorithmParameterSpec,419* java.security.SecureRandom) initialize} method,420* passing it {@code params} and a source of randomness (obtained421* from the highest-priority installed provider or system-provided if none422* of the installed providers supply one).423* That {@code initialize} method always throws an424* UnsupportedOperationException if it is not overridden by the provider.425*426* @param params the parameter set used to generate the keys.427*428* @throws InvalidAlgorithmParameterException if the given parameters429* are inappropriate for this key pair generator.430*431* @since 1.2432*/433public void initialize(AlgorithmParameterSpec params)434throws InvalidAlgorithmParameterException {435initialize(params, JCAUtil.getDefSecureRandom());436}437438/**439* Initializes the key pair generator with the given parameter440* set and source of randomness.441*442* <p>This concrete method has been added to this previously-defined443* abstract class.444* This method calls the KeyPairGeneratorSpi {@link445* KeyPairGeneratorSpi#initialize(446* java.security.spec.AlgorithmParameterSpec,447* java.security.SecureRandom) initialize} method,448* passing it {@code params} and {@code random}.449* That {@code initialize}450* method always throws an451* UnsupportedOperationException if it is not overridden by the provider.452*453* @param params the parameter set used to generate the keys.454* @param random the source of randomness.455*456* @throws InvalidAlgorithmParameterException if the given parameters457* are inappropriate for this key pair generator.458*459* @since 1.2460*/461public void initialize(AlgorithmParameterSpec params,462SecureRandom random)463throws InvalidAlgorithmParameterException464{465// This does nothing, because either466// 1. the implementation object returned by getInstance() is an467// instance of KeyPairGenerator which has its own468// initialize(params, random) method, so the application would469// be calling that method directly, or470// 2. the implementation returned by getInstance() is an instance471// of Delegate, in which case initialize(params, random) is472// overridden to call the corresponding SPI method.473// (This is a special case, because the API and SPI method have the474// same name.)475}476477/**478* Generates a key pair.479*480* <p>If this KeyPairGenerator has not been initialized explicitly,481* provider-specific defaults will be used for the size and other482* (algorithm-specific) values of the generated keys.483*484* <p>This will generate a new key pair every time it is called.485*486* <p>This method is functionally equivalent to487* {@link #generateKeyPair() generateKeyPair}.488*489* @return the generated key pair490*491* @since 1.2492*/493public final KeyPair genKeyPair() {494return generateKeyPair();495}496497/**498* Generates a key pair.499*500* <p>If this KeyPairGenerator has not been initialized explicitly,501* provider-specific defaults will be used for the size and other502* (algorithm-specific) values of the generated keys.503*504* <p>This will generate a new key pair every time it is called.505*506* <p>This method is functionally equivalent to507* {@link #genKeyPair() genKeyPair}.508*509* @return the generated key pair510*/511public KeyPair generateKeyPair() {512// This does nothing (except returning null), because either:513//514// 1. the implementation object returned by getInstance() is an515// instance of KeyPairGenerator which has its own implementation516// of generateKeyPair (overriding this one), so the application517// would be calling that method directly, or518//519// 2. the implementation returned by getInstance() is an instance520// of Delegate, in which case generateKeyPair is521// overridden to invoke the corresponding SPI method.522//523// (This is a special case, because in JDK 1.1.x the generateKeyPair524// method was used both as an API and a SPI method.)525return null;526}527528529/*530* The following class allows providers to extend from KeyPairGeneratorSpi531* rather than from KeyPairGenerator. It represents a KeyPairGenerator532* with an encapsulated, provider-supplied SPI object (of type533* KeyPairGeneratorSpi).534* If the provider implementation is an instance of KeyPairGeneratorSpi,535* the getInstance() methods above return an instance of this class, with536* the SPI object encapsulated.537*538* Note: All SPI methods from the original KeyPairGenerator class have been539* moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has540* been interposed in the hierarchy between the API (KeyPairGenerator)541* and its original parent (Object).542*/543544//545// error failover notes:546//547// . we failover if the implementation throws an error during init548// by retrying the init on other providers549//550// . we also failover if the init succeeded but the subsequent call551// to generateKeyPair() fails. In order for this to work, we need552// to remember the parameters to the last successful call to init553// and initialize() the next spi using them.554//555// . although not specified, KeyPairGenerators could be thread safe,556// so we make sure we do not interfere with that557//558// . failover is not available, if:559// . getInstance(algorithm, provider) was used560// . a provider extends KeyPairGenerator rather than561// KeyPairGeneratorSpi (JDK 1.1 style)562// . once getProvider() is called563//564565private static final class Delegate extends KeyPairGenerator {566567// The provider implementation (delegate)568private volatile KeyPairGeneratorSpi spi;569570private final Object lock = new Object();571572private Iterator<Service> serviceIterator;573574private static final int I_NONE = 1;575private static final int I_SIZE = 2;576private static final int I_PARAMS = 3;577578private int initType;579private int initKeySize;580private AlgorithmParameterSpec initParams;581private SecureRandom initRandom;582583// constructor584Delegate(KeyPairGeneratorSpi spi, String algorithm) {585super(algorithm);586this.spi = spi;587}588589Delegate(Instance instance, Iterator<Service> serviceIterator,590String algorithm) {591super(algorithm);592spi = (KeyPairGeneratorSpi)instance.impl;593provider = instance.provider;594this.serviceIterator = serviceIterator;595initType = I_NONE;596597if (!skipDebug && pdebug != null) {598pdebug.println("KeyPairGenerator." + algorithm +599" algorithm from: " + provider.getName());600}601}602603/**604* Update the active spi of this class and return the next605* implementation for failover. If no more implemenations are606* available, this method returns null. However, the active spi of607* this class is never set to null.608*/609private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi,610boolean reinit) {611synchronized (lock) {612// somebody else did a failover concurrently613// try that spi now614if ((oldSpi != null) && (oldSpi != spi)) {615return spi;616}617if (serviceIterator == null) {618return null;619}620while (serviceIterator.hasNext()) {621Service s = serviceIterator.next();622try {623Object inst = s.newInstance(null);624// ignore non-spis625if (!(inst instanceof KeyPairGeneratorSpi spi)) {626continue;627}628if (inst instanceof KeyPairGenerator) {629continue;630}631if (reinit) {632if (initType == I_SIZE) {633spi.initialize(initKeySize, initRandom);634} else if (initType == I_PARAMS) {635spi.initialize(initParams, initRandom);636} else if (initType != I_NONE) {637throw new AssertionError638("KeyPairGenerator initType: " + initType);639}640}641provider = s.getProvider();642this.spi = spi;643return spi;644} catch (Exception e) {645// ignore646}647}648disableFailover();649return null;650}651}652653void disableFailover() {654serviceIterator = null;655initType = 0;656initParams = null;657initRandom = null;658}659660// engine method661public void initialize(int keysize, SecureRandom random) {662if (serviceIterator == null) {663spi.initialize(keysize, random);664return;665}666RuntimeException failure = null;667KeyPairGeneratorSpi mySpi = spi;668do {669try {670mySpi.initialize(keysize, random);671initType = I_SIZE;672initKeySize = keysize;673initParams = null;674initRandom = random;675return;676} catch (RuntimeException e) {677if (failure == null) {678failure = e;679}680mySpi = nextSpi(mySpi, false);681}682} while (mySpi != null);683throw failure;684}685686// engine method687public void initialize(AlgorithmParameterSpec params,688SecureRandom random) throws InvalidAlgorithmParameterException {689if (serviceIterator == null) {690spi.initialize(params, random);691return;692}693Exception failure = null;694KeyPairGeneratorSpi mySpi = spi;695do {696try {697mySpi.initialize(params, random);698initType = I_PARAMS;699initKeySize = 0;700initParams = params;701initRandom = random;702return;703} catch (Exception e) {704if (failure == null) {705failure = e;706}707mySpi = nextSpi(mySpi, false);708}709} while (mySpi != null);710if (failure instanceof RuntimeException) {711throw (RuntimeException)failure;712}713// must be an InvalidAlgorithmParameterException714throw (InvalidAlgorithmParameterException)failure;715}716717// engine method718public KeyPair generateKeyPair() {719if (serviceIterator == null) {720return spi.generateKeyPair();721}722RuntimeException failure = null;723KeyPairGeneratorSpi mySpi = spi;724do {725try {726return mySpi.generateKeyPair();727} catch (RuntimeException e) {728if (failure == null) {729failure = e;730}731mySpi = nextSpi(mySpi, true);732}733} while (mySpi != null);734throw failure;735}736}737738}739740741