Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java
38830 views
/*1* Copyright (c) 2003, 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.rsa;2627import java.math.BigInteger;2829import java.security.*;30import java.security.spec.AlgorithmParameterSpec;31import java.security.spec.RSAKeyGenParameterSpec;3233import sun.security.jca.JCAUtil;34import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE;35import static sun.security.util.SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE;36import sun.security.x509.AlgorithmId;37import static sun.security.rsa.RSAUtil.KeyType;3839/**40* RSA keypair generation. Standard algorithm, minimum key length 512 bit.41* We generate two random primes until we find two where phi is relative42* prime to the public exponent. Default exponent is 65537. It has only bit 043* and bit 4 set, which makes it particularly efficient.44*45* @since 1.546* @author Andreas Sterbenz47*/48public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi {4950// public exponent to use51private BigInteger publicExponent;5253// size of the key to generate, >= RSAKeyFactory.MIN_MODLEN54private int keySize;5556private final KeyType type;57private AlgorithmId rsaId;5859// PRNG to use60private SecureRandom random;6162RSAKeyPairGenerator(KeyType type, int defKeySize) {63this.type = type;64// initialize to default in case the app does not call initialize()65initialize(defKeySize, null);66}6768// initialize the generator. See JCA doc69public void initialize(int keySize, SecureRandom random) {70try {71initialize(new RSAKeyGenParameterSpec(keySize,72RSAKeyGenParameterSpec.F4), random);73} catch (InvalidAlgorithmParameterException iape) {74throw new InvalidParameterException(iape.getMessage());75}76}7778// second initialize method. See JCA doc.79public void initialize(AlgorithmParameterSpec params, SecureRandom random)80throws InvalidAlgorithmParameterException {81if (params instanceof RSAKeyGenParameterSpec == false) {82throw new InvalidAlgorithmParameterException83("Params must be instance of RSAKeyGenParameterSpec");84}8586RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;87int tmpKeySize = rsaSpec.getKeysize();88BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();89AlgorithmParameterSpec tmpParams = rsaSpec.getKeyParams();9091if (tmpPublicExponent == null) {92tmpPublicExponent = RSAKeyGenParameterSpec.F4;93} else {94if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {95throw new InvalidAlgorithmParameterException96("Public exponent must be 3 or larger");97}98if (tmpPublicExponent.bitLength() > tmpKeySize) {99throw new InvalidAlgorithmParameterException100("Public exponent must be smaller than key size");101}102}103104// do not allow unreasonably large key sizes, probably user error105try {106RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,107512, 64 * 1024);108} catch (InvalidKeyException e) {109throw new InvalidAlgorithmParameterException(110"Invalid key sizes", e);111}112113try {114this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams);115} catch (ProviderException e) {116throw new InvalidAlgorithmParameterException(117"Invalid key parameters", e);118}119120this.keySize = tmpKeySize;121this.publicExponent = tmpPublicExponent;122this.random = random;123}124125// generate the keypair. See JCA doc126public KeyPair generateKeyPair() {127// accommodate odd key sizes in case anybody wants to use them128int lp = (keySize + 1) >> 1;129int lq = keySize - lp;130if (random == null) {131random = JCAUtil.getSecureRandom();132}133BigInteger e = publicExponent;134while (true) {135// generate two random primes of size lp/lq136BigInteger p = BigInteger.probablePrime(lp, random);137BigInteger q, n;138do {139q = BigInteger.probablePrime(lq, random);140// convention is for p > q141if (p.compareTo(q) < 0) {142BigInteger tmp = p;143p = q;144q = tmp;145}146// modulus n = p * q147n = p.multiply(q);148// even with correctly sized p and q, there is a chance that149// n will be one bit short. re-generate the smaller prime if so150} while (n.bitLength() < keySize);151152// phi = (p - 1) * (q - 1) must be relative prime to e153// otherwise RSA just won't work ;-)154BigInteger p1 = p.subtract(BigInteger.ONE);155BigInteger q1 = q.subtract(BigInteger.ONE);156BigInteger phi = p1.multiply(q1);157// generate new p and q until they work. typically158// the first try will succeed when using F4159if (e.gcd(phi).equals(BigInteger.ONE) == false) {160continue;161}162163// private exponent d is the inverse of e mod phi164BigInteger d = e.modInverse(phi);165166// 1st prime exponent pe = d mod (p - 1)167BigInteger pe = d.mod(p1);168// 2nd prime exponent qe = d mod (q - 1)169BigInteger qe = d.mod(q1);170171// crt coefficient coeff is the inverse of q mod p172BigInteger coeff = q.modInverse(p);173174try {175PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e);176PrivateKey privateKey = new RSAPrivateCrtKeyImpl(177rsaId, n, e, d, p, q, pe, qe, coeff);178return new KeyPair(publicKey, privateKey);179} catch (InvalidKeyException exc) {180// invalid key exception only thrown for keys < 512 bit,181// will not happen here182throw new RuntimeException(exc);183}184}185}186187public static final class Legacy extends RSAKeyPairGenerator {188public Legacy() {189super(KeyType.RSA, DEF_RSA_KEY_SIZE);190}191}192193public static final class PSS extends RSAKeyPairGenerator {194public PSS() {195super(KeyType.PSS, DEF_RSASSA_PSS_KEY_SIZE);196}197}198}199200201