Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/security/KeyPairGenerator.java
38829 views
/*1* Copyright (c) 1997, 2014, 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, or 1024, 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* three 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, while the87* 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* For example, the <i>Sun</i> provider uses a default modulus size (keysize)98* of 1024 bits.99*100* <p>Note that this class is abstract and extends from101* {@code KeyPairGeneratorSpi} for historical reasons.102* Application developers should only take notice of the methods defined in103* this {@code KeyPairGenerator} class; all the methods in104* the superclass are intended for cryptographic service providers who wish to105* supply their own implementations of key pair generators.106*107* <p> Every implementation of the Java platform is required to support the108* following standard {@code KeyPairGenerator} algorithms and keysizes in109* parentheses:110* <ul>111* <li>{@code DiffieHellman} (1024)</li>112* <li>{@code DSA} (1024)</li>113* <li>{@code RSA} (1024, 2048)</li>114* </ul>115* These algorithms are described in the <a href=116* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">117* KeyPairGenerator section</a> of the118* Java Cryptography Architecture Standard Algorithm Name Documentation.119* Consult the release documentation for your implementation to see if any120* other algorithms are supported.121*122* @author Benjamin Renaud123*124* @see java.security.spec.AlgorithmParameterSpec125*/126127public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {128129private static final Debug pdebug =130Debug.getInstance("provider", "Provider");131private static final boolean skipDebug =132Debug.isOn("engine=") && !Debug.isOn("keypairgenerator");133134private final String algorithm;135136// The provider137Provider provider;138139/**140* Creates a KeyPairGenerator object for the specified algorithm.141*142* @param algorithm the standard string name of the algorithm.143* See the KeyPairGenerator section in the <a href=144* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">145* Java Cryptography Architecture Standard Algorithm Name Documentation</a>146* for information about standard algorithm names.147*/148protected KeyPairGenerator(String algorithm) {149this.algorithm = algorithm;150}151152/**153* Returns the standard name of the algorithm for this key pair generator.154* See the KeyPairGenerator section in the <a href=155* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">156* Java Cryptography Architecture Standard Algorithm Name Documentation</a>157* for information about standard algorithm names.158*159* @return the standard string name of the algorithm.160*/161public String getAlgorithm() {162return this.algorithm;163}164165private static KeyPairGenerator getInstance(Instance instance,166String algorithm) {167KeyPairGenerator kpg;168if (instance.impl instanceof KeyPairGenerator) {169kpg = (KeyPairGenerator)instance.impl;170} else {171KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl;172kpg = new Delegate(spi, algorithm);173}174kpg.provider = instance.provider;175176if (!skipDebug && pdebug != null) {177pdebug.println("KeyPairGenerator." + algorithm +178" algorithm from: " + kpg.provider.getName());179}180181return kpg;182}183184/**185* Returns a KeyPairGenerator object that generates public/private186* key pairs for the specified algorithm.187*188* <p> This method traverses the list of registered security Providers,189* starting with the most preferred Provider.190* A new KeyPairGenerator object encapsulating the191* KeyPairGeneratorSpi implementation from the first192* Provider that supports the specified algorithm is returned.193*194* <p> Note that the list of registered providers may be retrieved via195* the {@link Security#getProviders() Security.getProviders()} method.196*197* @param algorithm the standard string name of the algorithm.198* See the KeyPairGenerator section in the <a href=199* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">200* Java Cryptography Architecture Standard Algorithm Name Documentation</a>201* for information about standard algorithm names.202*203* @return the new KeyPairGenerator object.204*205* @exception NoSuchAlgorithmException if no Provider supports a206* KeyPairGeneratorSpi implementation for the207* specified algorithm.208*209* @see Provider210*/211public static KeyPairGenerator getInstance(String algorithm)212throws NoSuchAlgorithmException {213List<Service> list =214GetInstance.getServices("KeyPairGenerator", algorithm);215Iterator<Service> t = list.iterator();216if (t.hasNext() == false) {217throw new NoSuchAlgorithmException218(algorithm + " KeyPairGenerator not available");219}220// find a working Spi or KeyPairGenerator subclass221NoSuchAlgorithmException failure = null;222do {223Service s = t.next();224try {225Instance instance =226GetInstance.getInstance(s, KeyPairGeneratorSpi.class);227if (instance.impl instanceof KeyPairGenerator) {228return getInstance(instance, algorithm);229} else {230return new Delegate(instance, t, algorithm);231}232} catch (NoSuchAlgorithmException e) {233if (failure == null) {234failure = e;235}236}237} while (t.hasNext());238throw failure;239}240241/**242* Returns a KeyPairGenerator object that generates public/private243* key pairs for the specified algorithm.244*245* <p> A new KeyPairGenerator object encapsulating the246* KeyPairGeneratorSpi implementation from the specified provider247* is returned. The specified provider must be registered248* in the security provider list.249*250* <p> Note that the list of registered providers may be retrieved via251* the {@link Security#getProviders() Security.getProviders()} method.252*253* @param algorithm the standard string name of the algorithm.254* See the KeyPairGenerator section in the <a href=255* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">256* Java Cryptography Architecture Standard Algorithm Name Documentation</a>257* for information about standard algorithm names.258*259* @param provider the string name of the provider.260*261* @return the new KeyPairGenerator object.262*263* @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi264* implementation for the specified algorithm is not265* available from the specified provider.266*267* @exception NoSuchProviderException if the specified provider is not268* registered in the security provider list.269*270* @exception IllegalArgumentException if the provider name is null271* or empty.272*273* @see Provider274*/275public static KeyPairGenerator getInstance(String algorithm,276String provider)277throws NoSuchAlgorithmException, NoSuchProviderException {278Instance instance = GetInstance.getInstance("KeyPairGenerator",279KeyPairGeneratorSpi.class, algorithm, provider);280return getInstance(instance, algorithm);281}282283/**284* Returns a KeyPairGenerator object that generates public/private285* key pairs for the specified algorithm.286*287* <p> A new KeyPairGenerator object encapsulating the288* KeyPairGeneratorSpi implementation from the specified Provider289* object is returned. Note that the specified Provider object290* does not have to be registered in the provider list.291*292* @param algorithm the standard string name of the algorithm.293* See the KeyPairGenerator section in the <a href=294* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">295* Java Cryptography Architecture Standard Algorithm Name Documentation</a>296* for information about standard algorithm names.297*298* @param provider the provider.299*300* @return the new KeyPairGenerator object.301*302* @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi303* implementation for the specified algorithm is not available304* from the specified Provider object.305*306* @exception IllegalArgumentException if the specified provider is null.307*308* @see Provider309*310* @since 1.4311*/312public static KeyPairGenerator getInstance(String algorithm,313Provider provider) throws NoSuchAlgorithmException {314Instance instance = GetInstance.getInstance("KeyPairGenerator",315KeyPairGeneratorSpi.class, algorithm, provider);316return getInstance(instance, algorithm);317}318319/**320* Returns the provider of this key pair generator object.321*322* @return the provider of this key pair generator object323*/324public final Provider getProvider() {325disableFailover();326return this.provider;327}328329void disableFailover() {330// empty, overridden in Delegate331}332333/**334* Initializes the key pair generator for a certain keysize using335* a default parameter set and the {@code SecureRandom}336* implementation of the highest-priority installed provider as the source337* of randomness.338* (If none of the installed providers supply an implementation of339* {@code SecureRandom}, a system-provided source of randomness is340* used.)341*342* @param keysize the keysize. This is an343* algorithm-specific metric, such as modulus length, specified in344* number of bits.345*346* @exception InvalidParameterException if the {@code keysize} is not347* supported by this KeyPairGenerator object.348*/349public void initialize(int keysize) {350initialize(keysize, JCAUtil.getSecureRandom());351}352353/**354* Initializes the key pair generator for a certain keysize with355* the given source of randomness (and a default parameter set).356*357* @param keysize the keysize. This is an358* algorithm-specific metric, such as modulus length, specified in359* number of bits.360* @param random the source of randomness.361*362* @exception InvalidParameterException if the {@code keysize} is not363* supported by this KeyPairGenerator object.364*365* @since 1.2366*/367public void initialize(int keysize, SecureRandom random) {368// This does nothing, because either369// 1. the implementation object returned by getInstance() is an370// instance of KeyPairGenerator which has its own371// initialize(keysize, random) method, so the application would372// be calling that method directly, or373// 2. the implementation returned by getInstance() is an instance374// of Delegate, in which case initialize(keysize, random) is375// overridden to call the corresponding SPI method.376// (This is a special case, because the API and SPI method have the377// same name.)378}379380/**381* Initializes the key pair generator using the specified parameter382* set and the {@code SecureRandom}383* implementation of the highest-priority installed provider as the source384* of randomness.385* (If none of the installed providers supply an implementation of386* {@code SecureRandom}, a system-provided source of randomness is387* used.).388*389* <p>This concrete method has been added to this previously-defined390* abstract class.391* This method calls the KeyPairGeneratorSpi392* {@link KeyPairGeneratorSpi#initialize(393* java.security.spec.AlgorithmParameterSpec,394* java.security.SecureRandom) initialize} method,395* passing it {@code params} and a source of randomness (obtained396* from the highest-priority installed provider or system-provided if none397* of the installed providers supply one).398* That {@code initialize} method always throws an399* UnsupportedOperationException if it is not overridden by the provider.400*401* @param params the parameter set used to generate the keys.402*403* @exception InvalidAlgorithmParameterException if the given parameters404* are inappropriate for this key pair generator.405*406* @since 1.2407*/408public void initialize(AlgorithmParameterSpec params)409throws InvalidAlgorithmParameterException {410initialize(params, JCAUtil.getSecureRandom());411}412413/**414* Initializes the key pair generator with the given parameter415* set and source of randomness.416*417* <p>This concrete method has been added to this previously-defined418* abstract class.419* This method calls the KeyPairGeneratorSpi {@link420* KeyPairGeneratorSpi#initialize(421* java.security.spec.AlgorithmParameterSpec,422* java.security.SecureRandom) initialize} method,423* passing it {@code params} and {@code random}.424* That {@code initialize}425* method always throws an426* UnsupportedOperationException if it is not overridden by the provider.427*428* @param params the parameter set used to generate the keys.429* @param random the source of randomness.430*431* @exception InvalidAlgorithmParameterException if the given parameters432* are inappropriate for this key pair generator.433*434* @since 1.2435*/436public void initialize(AlgorithmParameterSpec params,437SecureRandom random)438throws InvalidAlgorithmParameterException439{440// This does nothing, because either441// 1. the implementation object returned by getInstance() is an442// instance of KeyPairGenerator which has its own443// initialize(params, random) method, so the application would444// be calling that method directly, or445// 2. the implementation returned by getInstance() is an instance446// of Delegate, in which case initialize(params, random) is447// overridden to call the corresponding SPI method.448// (This is a special case, because the API and SPI method have the449// same name.)450}451452/**453* Generates a key pair.454*455* <p>If this KeyPairGenerator has not been initialized explicitly,456* provider-specific defaults will be used for the size and other457* (algorithm-specific) values of the generated keys.458*459* <p>This will generate a new key pair every time it is called.460*461* <p>This method is functionally equivalent to462* {@link #generateKeyPair() generateKeyPair}.463*464* @return the generated key pair465*466* @since 1.2467*/468public final KeyPair genKeyPair() {469return generateKeyPair();470}471472/**473* Generates a key pair.474*475* <p>If this KeyPairGenerator has not been initialized explicitly,476* provider-specific defaults will be used for the size and other477* (algorithm-specific) values of the generated keys.478*479* <p>This will generate a new key pair every time it is called.480*481* <p>This method is functionally equivalent to482* {@link #genKeyPair() genKeyPair}.483*484* @return the generated key pair485*/486public KeyPair generateKeyPair() {487// This does nothing (except returning null), because either:488//489// 1. the implementation object returned by getInstance() is an490// instance of KeyPairGenerator which has its own implementation491// of generateKeyPair (overriding this one), so the application492// would be calling that method directly, or493//494// 2. the implementation returned by getInstance() is an instance495// of Delegate, in which case generateKeyPair is496// overridden to invoke the corresponding SPI method.497//498// (This is a special case, because in JDK 1.1.x the generateKeyPair499// method was used both as an API and a SPI method.)500return null;501}502503504/*505* The following class allows providers to extend from KeyPairGeneratorSpi506* rather than from KeyPairGenerator. It represents a KeyPairGenerator507* with an encapsulated, provider-supplied SPI object (of type508* KeyPairGeneratorSpi).509* If the provider implementation is an instance of KeyPairGeneratorSpi,510* the getInstance() methods above return an instance of this class, with511* the SPI object encapsulated.512*513* Note: All SPI methods from the original KeyPairGenerator class have been514* moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has515* been interposed in the hierarchy between the API (KeyPairGenerator)516* and its original parent (Object).517*/518519//520// error failover notes:521//522// . we failover if the implementation throws an error during init523// by retrying the init on other providers524//525// . we also failover if the init succeeded but the subsequent call526// to generateKeyPair() fails. In order for this to work, we need527// to remember the parameters to the last successful call to init528// and initialize() the next spi using them.529//530// . although not specified, KeyPairGenerators could be thread safe,531// so we make sure we do not interfere with that532//533// . failover is not available, if:534// . getInstance(algorithm, provider) was used535// . a provider extends KeyPairGenerator rather than536// KeyPairGeneratorSpi (JDK 1.1 style)537// . once getProvider() is called538//539540private static final class Delegate extends KeyPairGenerator {541542// The provider implementation (delegate)543private volatile KeyPairGeneratorSpi spi;544545private final Object lock = new Object();546547private Iterator<Service> serviceIterator;548549private final static int I_NONE = 1;550private final static int I_SIZE = 2;551private final static int I_PARAMS = 3;552553private int initType;554private int initKeySize;555private AlgorithmParameterSpec initParams;556private SecureRandom initRandom;557558// constructor559Delegate(KeyPairGeneratorSpi spi, String algorithm) {560super(algorithm);561this.spi = spi;562}563564Delegate(Instance instance, Iterator<Service> serviceIterator,565String algorithm) {566super(algorithm);567spi = (KeyPairGeneratorSpi)instance.impl;568provider = instance.provider;569this.serviceIterator = serviceIterator;570initType = I_NONE;571572if (!skipDebug && pdebug != null) {573pdebug.println("KeyPairGenerator." + algorithm +574" algorithm from: " + provider.getName());575}576}577578/**579* Update the active spi of this class and return the next580* implementation for failover. If no more implemenations are581* available, this method returns null. However, the active spi of582* this class is never set to null.583*/584private KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi oldSpi,585boolean reinit) {586synchronized (lock) {587// somebody else did a failover concurrently588// try that spi now589if ((oldSpi != null) && (oldSpi != spi)) {590return spi;591}592if (serviceIterator == null) {593return null;594}595while (serviceIterator.hasNext()) {596Service s = serviceIterator.next();597try {598Object inst = s.newInstance(null);599// ignore non-spis600if (inst instanceof KeyPairGeneratorSpi == false) {601continue;602}603if (inst instanceof KeyPairGenerator) {604continue;605}606KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)inst;607if (reinit) {608if (initType == I_SIZE) {609spi.initialize(initKeySize, initRandom);610} else if (initType == I_PARAMS) {611spi.initialize(initParams, initRandom);612} else if (initType != I_NONE) {613throw new AssertionError614("KeyPairGenerator initType: " + initType);615}616}617provider = s.getProvider();618this.spi = spi;619return spi;620} catch (Exception e) {621// ignore622}623}624disableFailover();625return null;626}627}628629void disableFailover() {630serviceIterator = null;631initType = 0;632initParams = null;633initRandom = null;634}635636// engine method637public void initialize(int keysize, SecureRandom random) {638if (serviceIterator == null) {639spi.initialize(keysize, random);640return;641}642RuntimeException failure = null;643KeyPairGeneratorSpi mySpi = spi;644do {645try {646mySpi.initialize(keysize, random);647initType = I_SIZE;648initKeySize = keysize;649initParams = null;650initRandom = random;651return;652} catch (RuntimeException e) {653if (failure == null) {654failure = e;655}656mySpi = nextSpi(mySpi, false);657}658} while (mySpi != null);659throw failure;660}661662// engine method663public void initialize(AlgorithmParameterSpec params,664SecureRandom random) throws InvalidAlgorithmParameterException {665if (serviceIterator == null) {666spi.initialize(params, random);667return;668}669Exception failure = null;670KeyPairGeneratorSpi mySpi = spi;671do {672try {673mySpi.initialize(params, random);674initType = I_PARAMS;675initKeySize = 0;676initParams = params;677initRandom = random;678return;679} catch (Exception e) {680if (failure == null) {681failure = e;682}683mySpi = nextSpi(mySpi, false);684}685} while (mySpi != null);686if (failure instanceof RuntimeException) {687throw (RuntimeException)failure;688}689// must be an InvalidAlgorithmParameterException690throw (InvalidAlgorithmParameterException)failure;691}692693// engine method694public KeyPair generateKeyPair() {695if (serviceIterator == null) {696return spi.generateKeyPair();697}698RuntimeException failure = null;699KeyPairGeneratorSpi mySpi = spi;700do {701try {702return mySpi.generateKeyPair();703} catch (RuntimeException e) {704if (failure == null) {705failure = e;706}707mySpi = nextSpi(mySpi, true);708}709} while (mySpi != null);710throw failure;711}712}713714}715716717