1 /* 2 * Copyright (c) 2003, 2017, 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.rsa; 27 28 import java.math.BigInteger; 29 30 import java.security.*; 31 import java.security.spec.AlgorithmParameterSpec; 32 import java.security.spec.RSAKeyGenParameterSpec; 33 34 import sun.security.jca.JCAUtil; 35 import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE; 36 37 /** 38 * RSA keypair generation. Standard algorithm, minimum key length 512 bit. 39 * We generate two random primes until we find two where phi is relative 40 * prime to the public exponent. Default exponent is 65537. It has only bit 0 41 * and bit 4 set, which makes it particularly efficient. 42 * 43 * @since 1.5 44 * @author Andreas Sterbenz 45 */ 46 public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { 47 48 // public exponent to use 49 private BigInteger publicExponent; 50 51 // size of the key to generate, >= RSAKeyFactory.MIN_MODLEN 52 private int keySize; 53 54 // PRNG to use 55 private SecureRandom random; 56 57 public RSAKeyPairGenerator() { 58 // initialize to default in case the app does not call initialize() 59 initialize(DEF_RSA_KEY_SIZE, null); 60 } 61 62 // initialize the generator. See JCA doc 63 public void initialize(int keySize, SecureRandom random) { 64 65 // do not allow unreasonably small or large key sizes, 66 // probably user error 67 try { 68 RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4, 69 512, 64 * 1024); 70 } catch (InvalidKeyException e) { 71 throw new InvalidParameterException(e.getMessage()); 72 } 73 74 this.keySize = keySize; 75 this.random = random; 76 this.publicExponent = RSAKeyGenParameterSpec.F4; 77 } 78 79 // second initialize method. See JCA doc. 80 public void initialize(AlgorithmParameterSpec params, SecureRandom random) 81 throws InvalidAlgorithmParameterException { 82 83 if (params instanceof RSAKeyGenParameterSpec == false) { 84 throw new InvalidAlgorithmParameterException 85 ("Params must be instance of RSAKeyGenParameterSpec"); 86 } 87 88 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params; 89 int tmpKeySize = rsaSpec.getKeysize(); 90 BigInteger tmpPublicExponent = rsaSpec.getPublicExponent(); 91 92 if (tmpPublicExponent == null) { 93 tmpPublicExponent = RSAKeyGenParameterSpec.F4; 94 } else { 95 if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) { 96 throw new InvalidAlgorithmParameterException 97 ("Public exponent must be 3 or larger"); 98 } 99 if (tmpPublicExponent.bitLength() > tmpKeySize) { 100 throw new InvalidAlgorithmParameterException 101 ("Public exponent must be smaller than key size"); 102 } 103 } 104 105 // do not allow unreasonably large key sizes, probably user error 106 try { 107 RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent, 108 512, 64 * 1024); 109 } catch (InvalidKeyException e) { 110 throw new InvalidAlgorithmParameterException( 111 "Invalid key sizes", e); 112 } 113 114 this.keySize = tmpKeySize; 115 this.publicExponent = tmpPublicExponent; 116 this.random = random; 117 } 118 119 // generate the keypair. See JCA doc 120 public KeyPair generateKeyPair() { 121 // accommodate odd key sizes in case anybody wants to use them 122 int lp = (keySize + 1) >> 1; 123 int lq = keySize - lp; 124 if (random == null) { 125 random = JCAUtil.getSecureRandom(); 126 } 127 BigInteger e = publicExponent; 128 while (true) { 129 // generate two random primes of size lp/lq 130 BigInteger p = BigInteger.probablePrime(lp, random); 131 BigInteger q, n; 132 do { 133 q = BigInteger.probablePrime(lq, random); 149 BigInteger q1 = q.subtract(BigInteger.ONE); 150 BigInteger phi = p1.multiply(q1); 151 // generate new p and q until they work. typically 152 // the first try will succeed when using F4 153 if (e.gcd(phi).equals(BigInteger.ONE) == false) { 154 continue; 155 } 156 157 // private exponent d is the inverse of e mod phi 158 BigInteger d = e.modInverse(phi); 159 160 // 1st prime exponent pe = d mod (p - 1) 161 BigInteger pe = d.mod(p1); 162 // 2nd prime exponent qe = d mod (q - 1) 163 BigInteger qe = d.mod(q1); 164 165 // crt coefficient coeff is the inverse of q mod p 166 BigInteger coeff = q.modInverse(p); 167 168 try { 169 PublicKey publicKey = new RSAPublicKeyImpl(n, e); 170 PrivateKey privateKey = 171 new RSAPrivateCrtKeyImpl(n, e, d, p, q, pe, qe, coeff); 172 return new KeyPair(publicKey, privateKey); 173 } catch (InvalidKeyException exc) { 174 // invalid key exception only thrown for keys < 512 bit, 175 // will not happen here 176 throw new RuntimeException(exc); 177 } 178 } 179 } 180 181 } | 1 /* 2 * Copyright (c) 2003, 2018, 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.rsa; 27 28 import java.math.BigInteger; 29 30 import java.security.*; 31 import java.security.spec.AlgorithmParameterSpec; 32 import java.security.spec.RSAKeyGenParameterSpec; 33 34 import sun.security.jca.JCAUtil; 35 import static sun.security.util.SecurityProviderConstants.DEF_RSA_KEY_SIZE; 36 import static sun.security.util.SecurityProviderConstants.DEF_RSASSA_PSS_KEY_SIZE; 37 import sun.security.x509.AlgorithmId; 38 import static sun.security.rsa.RSAUtil.KeyType; 39 40 /** 41 * RSA keypair generation. Standard algorithm, minimum key length 512 bit. 42 * We generate two random primes until we find two where phi is relative 43 * prime to the public exponent. Default exponent is 65537. It has only bit 0 44 * and bit 4 set, which makes it particularly efficient. 45 * 46 * @since 1.5 47 * @author Andreas Sterbenz 48 */ 49 public abstract class RSAKeyPairGenerator extends KeyPairGeneratorSpi { 50 51 // public exponent to use 52 private BigInteger publicExponent; 53 54 // size of the key to generate, >= RSAKeyFactory.MIN_MODLEN 55 private int keySize; 56 57 private final KeyType type; 58 private AlgorithmId rsaId; 59 60 // PRNG to use 61 private SecureRandom random; 62 63 RSAKeyPairGenerator(KeyType type, int defKeySize) { 64 this.type = type; 65 // initialize to default in case the app does not call initialize() 66 initialize(defKeySize, null); 67 } 68 69 // initialize the generator. See JCA doc 70 public void initialize(int keySize, SecureRandom random) { 71 try { 72 initialize(new RSAKeyGenParameterSpec(keySize, 73 RSAKeyGenParameterSpec.F4), null); 74 } catch (InvalidAlgorithmParameterException iape) { 75 throw new InvalidParameterException(iape.getMessage()); 76 } 77 } 78 79 // second initialize method. See JCA doc. 80 public void initialize(AlgorithmParameterSpec params, SecureRandom random) 81 throws InvalidAlgorithmParameterException { 82 if (params instanceof RSAKeyGenParameterSpec == false) { 83 throw new InvalidAlgorithmParameterException 84 ("Params must be instance of RSAKeyGenParameterSpec"); 85 } 86 87 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params; 88 int tmpKeySize = rsaSpec.getKeysize(); 89 BigInteger tmpPublicExponent = rsaSpec.getPublicExponent(); 90 AlgorithmParameterSpec tmpParams = rsaSpec.getKeyParams(); 91 92 if (tmpPublicExponent == null) { 93 tmpPublicExponent = RSAKeyGenParameterSpec.F4; 94 } else { 95 if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) { 96 throw new InvalidAlgorithmParameterException 97 ("Public exponent must be 3 or larger"); 98 } 99 if (tmpPublicExponent.bitLength() > tmpKeySize) { 100 throw new InvalidAlgorithmParameterException 101 ("Public exponent must be smaller than key size"); 102 } 103 } 104 105 // do not allow unreasonably large key sizes, probably user error 106 try { 107 RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent, 108 512, 64 * 1024); 109 } catch (InvalidKeyException e) { 110 throw new InvalidAlgorithmParameterException( 111 "Invalid key sizes", e); 112 } 113 114 try { 115 this.rsaId = RSAUtil.createAlgorithmId(type, tmpParams); 116 } catch (ProviderException e) { 117 throw new InvalidAlgorithmParameterException( 118 "Invalid key parameters", e); 119 } 120 121 this.keySize = tmpKeySize; 122 this.publicExponent = tmpPublicExponent; 123 this.random = random; 124 } 125 126 // generate the keypair. See JCA doc 127 public KeyPair generateKeyPair() { 128 // accommodate odd key sizes in case anybody wants to use them 129 int lp = (keySize + 1) >> 1; 130 int lq = keySize - lp; 131 if (random == null) { 132 random = JCAUtil.getSecureRandom(); 133 } 134 BigInteger e = publicExponent; 135 while (true) { 136 // generate two random primes of size lp/lq 137 BigInteger p = BigInteger.probablePrime(lp, random); 138 BigInteger q, n; 139 do { 140 q = BigInteger.probablePrime(lq, random); 156 BigInteger q1 = q.subtract(BigInteger.ONE); 157 BigInteger phi = p1.multiply(q1); 158 // generate new p and q until they work. typically 159 // the first try will succeed when using F4 160 if (e.gcd(phi).equals(BigInteger.ONE) == false) { 161 continue; 162 } 163 164 // private exponent d is the inverse of e mod phi 165 BigInteger d = e.modInverse(phi); 166 167 // 1st prime exponent pe = d mod (p - 1) 168 BigInteger pe = d.mod(p1); 169 // 2nd prime exponent qe = d mod (q - 1) 170 BigInteger qe = d.mod(q1); 171 172 // crt coefficient coeff is the inverse of q mod p 173 BigInteger coeff = q.modInverse(p); 174 175 try { 176 PublicKey publicKey = new RSAPublicKeyImpl(rsaId, n, e); 177 PrivateKey privateKey = new RSAPrivateCrtKeyImpl( 178 rsaId, n, e, d, p, q, pe, qe, coeff); 179 return new KeyPair(publicKey, privateKey); 180 } catch (InvalidKeyException exc) { 181 // invalid key exception only thrown for keys < 512 bit, 182 // will not happen here 183 throw new RuntimeException(exc); 184 } 185 } 186 } 187 188 public static final class Legacy extends RSAKeyPairGenerator { 189 public Legacy() { 190 super(KeyType.RSA, DEF_RSA_KEY_SIZE); 191 } 192 } 193 194 public static final class PSS extends RSAKeyPairGenerator { 195 public PSS() { 196 super(KeyType.PSS, DEF_RSASSA_PSS_KEY_SIZE); 197 } 198 } 199 } |