blob: f800dec543b4292485cb1be978176a354da9d133 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.rsa;
27
28import java.math.BigInteger;
29
30import java.security.*;
31import java.security.spec.AlgorithmParameterSpec;
32import java.security.spec.RSAKeyGenParameterSpec;
33
34import sun.security.jca.JCAUtil;
35
36/**
37 * RSA keypair generation. Standard algorithm, minimum key length 512 bit.
38 * We generate two random primes until we find two where phi is relative
39 * prime to the public exponent. Default exponent is 65537. It has only bit 0
40 * and bit 4 set, which makes it particularly efficient.
41 *
42 * @since 1.5
43 * @author Andreas Sterbenz
44 */
45public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
46
47 // public exponent to use
48 private BigInteger publicExponent;
49
50 // size of the key to generate, >= 512
51 private int keySize;
52
53 // PRNG to use
54 private SecureRandom random;
55
56 public RSAKeyPairGenerator() {
57 // initialize to default in case the app does not call initialize()
58 initialize(1024, null);
59 }
60
61 // initialize the generator. See JCA doc
62 public void initialize(int keySize, SecureRandom random) {
63 if (keySize < 512) {
64 throw new InvalidParameterException
65 ("Key size must be at least 512 bits");
66 }
67 if (keySize > 64 * 1024) {
68 // do not allow unreasonably large key sizes, probably user error
69 throw new InvalidParameterException
70 ("Key size must be 65536 bits or less");
71 }
72 this.keySize = keySize;
73 this.random = random;
74 this.publicExponent = RSAKeyGenParameterSpec.F4;
75 }
76
77 // second initialize method. See JCA doc.
78 public void initialize(AlgorithmParameterSpec params, SecureRandom random)
79 throws InvalidAlgorithmParameterException {
80 if (params instanceof RSAKeyGenParameterSpec == false) {
81 throw new InvalidAlgorithmParameterException
82 ("Params must be instance of RSAKeyGenParameterSpec");
83 }
84 RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
85 keySize = rsaSpec.getKeysize();
86 publicExponent = rsaSpec.getPublicExponent();
87 this.random = random;
88 if (keySize < 512) {
89 throw new InvalidAlgorithmParameterException
90 ("Key size must be at least 512 bits");
91 }
92 if (keySize > 64 * 1024) {
93 // do not allow unreasonably large key sizes, probably user error
94 throw new InvalidAlgorithmParameterException
95 ("Key size must be 65536 bits or less");
96 }
97 if (publicExponent == null) {
98 publicExponent = RSAKeyGenParameterSpec.F4;
99 } else {
100 if (publicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
101 throw new InvalidAlgorithmParameterException
102 ("Public exponent must be 3 or larger");
103 }
104 if (publicExponent.bitLength() > keySize) {
105 throw new InvalidAlgorithmParameterException
106 ("Public exponent must be smaller than key size");
107 }
108 }
109 }
110
111 // generate the keypair. See JCA doc
112 public KeyPair generateKeyPair() {
113 // accomodate odd key sizes in case anybody wants to use them
114 int lp = (keySize + 1) >> 1;
115 int lq = keySize - lp;
116 if (random == null) {
117 random = JCAUtil.getSecureRandom();
118 }
119 BigInteger e = publicExponent;
120 while (true) {
121 // generate two random primes of size lp/lq
122 BigInteger p = BigInteger.probablePrime(lp, random);
123 BigInteger q, n;
124 do {
125 q = BigInteger.probablePrime(lq, random);
126 // convention is for p > q
127 if (p.compareTo(q) < 0) {
128 BigInteger tmp = p;
129 p = q;
130 q = tmp;
131 }
132 // modulus n = p * q
133 n = p.multiply(q);
134 // even with correctly sized p and q, there is a chance that
135 // n will be one bit short. re-generate the smaller prime if so
136 } while (n.bitLength() < keySize);
137
138 // phi = (p - 1) * (q - 1) must be relative prime to e
139 // otherwise RSA just won't work ;-)
140 BigInteger p1 = p.subtract(BigInteger.ONE);
141 BigInteger q1 = q.subtract(BigInteger.ONE);
142 BigInteger phi = p1.multiply(q1);
143 // generate new p and q until they work. typically
144 // the first try will succeed when using F4
145 if (e.gcd(phi).equals(BigInteger.ONE) == false) {
146 continue;
147 }
148
149 // private exponent d is the inverse of e mod phi
150 BigInteger d = e.modInverse(phi);
151
152 // 1st prime exponent pe = d mod (p - 1)
153 BigInteger pe = d.mod(p1);
154 // 2nd prime exponent qe = d mod (q - 1)
155 BigInteger qe = d.mod(q1);
156
157 // crt coefficient coeff is the inverse of q mod p
158 BigInteger coeff = q.modInverse(p);
159
160 try {
161 PublicKey publicKey = new RSAPublicKeyImpl(n, e);
162 PrivateKey privateKey =
163 new RSAPrivateCrtKeyImpl(n, e, d, p, q, pe, qe, coeff);
164 return new KeyPair(publicKey, privateKey);
165 } catch (InvalidKeyException exc) {
166 // invalid key exception only thrown for keys < 512 bit,
167 // will not happen here
168 throw new RuntimeException(exc);
169 }
170 }
171 }
172
173}