1 /*
2 * Copyright (c) 1997, 2012, 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.provider;
27
28 import java.math.BigInteger;
29
30 import java.security.*;
31 import java.security.SecureRandom;
32 import java.security.interfaces.DSAParams;
33 import java.security.spec.AlgorithmParameterSpec;
34 import java.security.spec.InvalidParameterSpecException;
35 import java.security.spec.DSAParameterSpec;
36
37 import sun.security.jca.JCAUtil;
38
39 /**
40 * This class generates DSA key parameters and public/private key
41 * pairs according to the DSS standard NIST FIPS 186. It uses the
42 * updated version of SHA, SHA-1 as described in FIPS 180-1.
43 *
44 * @author Benjamin Renaud
45 * @author Andreas Sterbenz
46 *
47 */
48 public class DSAKeyPairGenerator extends KeyPairGenerator
49 implements java.security.interfaces.DSAKeyPairGenerator {
50
51 /* Length for prime P and subPrime Q in bits */
52 private int plen;
53 private int qlen;
54
55 /* whether to force new parameters to be generated for each KeyPair */
56 private boolean forceNewParameters;
57
58 /* preset algorithm parameters. */
59 private DSAParameterSpec params;
60
61 /* The source of random bits to use */
62 private SecureRandom random;
63
64 public DSAKeyPairGenerator() {
65 super("DSA");
66 initialize(1024, null);
67 }
68
69 private static void checkStrength(int sizeP, int sizeQ) {
70 if ((sizeP >= 512) && (sizeP <= 1024) && (sizeP % 64 == 0)
71 && sizeQ == 160) {
72 // traditional - allow for backward compatibility
73 // L=multiples of 64 and between 512 and 1024 (inclusive)
74 // N=160
75 } else if (sizeP == 2048 && (sizeQ == 224 || sizeQ == 256)) {
76 // L=2048, N=224 or 256
77 } else {
78 throw new InvalidParameterException
79 ("Unsupported prime and subprime size combination: " +
80 sizeP + ", " + sizeQ);
81 }
82 }
83
84 public void initialize(int modlen, SecureRandom random) {
85 // generate new parameters when no precomputed ones available.
86 initialize(modlen, true, random);
87 this.forceNewParameters = false;
88 }
89
90 /**
91 * Initializes the DSA key pair generator. If <code>genParams</code>
92 * is false, a set of pre-computed parameters is used.
93 */
94 public void initialize(int modlen, boolean genParams, SecureRandom random) {
95 int subPrimeLen = -1;
96 if (modlen <= 1024) {
97 subPrimeLen = 160;
98 } else if (modlen == 2048) {
99 subPrimeLen = 224;
100 }
101 checkStrength(modlen, subPrimeLen);
102 if (genParams) {
103 params = null;
104 } else {
105 params = ParameterCache.getCachedDSAParameterSpec(modlen,
106 subPrimeLen);
107 if (params == null) {
108 throw new InvalidParameterException
109 ("No precomputed parameters for requested modulus size "
110 + "available");
111 }
112
113 }
114 this.plen = modlen;
115 this.qlen = subPrimeLen;
116 this.random = random;
117 this.forceNewParameters = genParams;
118 }
119
120 /**
121 * Initializes the DSA object using a DSA parameter object.
122 *
123 * @param params a fully initialized DSA parameter object.
124 */
125 public void initialize(DSAParams params, SecureRandom random) {
126 if (params == null) {
127 throw new InvalidParameterException("Params must not be null");
128 }
129 DSAParameterSpec spec = new DSAParameterSpec
130 (params.getP(), params.getQ(), params.getG());
131 initialize0(spec, random);
132 }
133
134 /**
135 * Initializes the DSA object using a parameter object.
136 *
137 * @param params the parameter set to be used to generate
138 * the keys.
139 * @param random the source of randomness for this generator.
140 *
141 * @exception InvalidAlgorithmParameterException if the given parameters
142 * are inappropriate for this key pair generator
143 */
144 public void initialize(AlgorithmParameterSpec params, SecureRandom random)
145 throws InvalidAlgorithmParameterException {
146 if (!(params instanceof DSAParameterSpec)) {
147 throw new InvalidAlgorithmParameterException
148 ("Inappropriate parameter");
149 }
150 initialize0((DSAParameterSpec)params, random);
151 }
152
153 private void initialize0(DSAParameterSpec params, SecureRandom random) {
154 int sizeP = params.getP().bitLength();
155 int sizeQ = params.getQ().bitLength();
156 checkStrength(sizeP, sizeQ);
157 this.plen = sizeP;
158 this.qlen = sizeQ;
159 this.params = params;
160 this.random = random;
161 this.forceNewParameters = false;
162 }
163
164 /**
165 * Generates a pair of keys usable by any JavaSecurity compliant
166 * DSA implementation.
167 */
168 public KeyPair generateKeyPair() {
169 if (random == null) {
170 random = JCAUtil.getSecureRandom();
171 }
172 DSAParameterSpec spec;
173 try {
174 if (forceNewParameters) {
175 // generate new parameters each time
176 spec = ParameterCache.getNewDSAParameterSpec(plen, qlen, random);
177 } else {
178 if (params == null) {
179 params =
180 ParameterCache.getDSAParameterSpec(plen, qlen, random);
181 }
182 spec = params;
183 }
184 } catch (GeneralSecurityException e) {
185 throw new ProviderException(e);
186 }
187 return generateKeyPair(spec.getP(), spec.getQ(), spec.getG(), random);
188 }
189
190 public KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g,
191 SecureRandom random) {
192
193 BigInteger x = generateX(random, q);
194 BigInteger y = generateY(x, p, g);
195
196 try {
197
198 // See the comments in DSAKeyFactory, 4532506, and 6232513.
199
200 DSAPublicKey pub;
201 if (DSAKeyFactory.SERIAL_INTEROP) {
202 pub = new DSAPublicKey(y, p, q, g);
203 } else {
204 pub = new DSAPublicKeyImpl(y, p, q, g);
205 }
206 DSAPrivateKey priv = new DSAPrivateKey(x, p, q, g);
207
208 KeyPair pair = new KeyPair(pub, priv);
209 return pair;
210 } catch (InvalidKeyException e) {
225 random.nextBytes(temp);
226 x = new BigInteger(1, temp).mod(q);
227 if (x.signum() > 0 && (x.compareTo(q) < 0)) {
228 return x;
229 }
230 }
231 }
232
233 /**
234 * Generate the public key component y of the key pair.
235 *
236 * @param x the private key component.
237 *
238 * @param p the base parameter.
239 */
240 BigInteger generateY(BigInteger x, BigInteger p, BigInteger g) {
241 BigInteger y = g.modPow(x, p);
242 return y;
243 }
244
245 }
|
1 /*
2 * Copyright (c) 1997, 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.provider;
27
28 import java.math.BigInteger;
29
30 import java.security.*;
31 import java.security.SecureRandom;
32 import java.security.interfaces.DSAParams;
33 import java.security.spec.AlgorithmParameterSpec;
34 import java.security.spec.InvalidParameterSpecException;
35 import java.security.spec.DSAParameterSpec;
36
37 import sun.security.jca.JCAUtil;
38 import static sun.security.util.SecurityProviderConstants.DEF_DSA_KEY_SIZE;
39 import static sun.security.util.SecurityProviderConstants.getDefDSASubprimeSize;
40
41 /**
42 * This class generates DSA key parameters and public/private key
43 * pairs according to the DSS standard NIST FIPS 186. It uses the
44 * updated version of SHA, SHA-1 as described in FIPS 180-1.
45 *
46 * @author Benjamin Renaud
47 * @author Andreas Sterbenz
48 *
49 */
50 class DSAKeyPairGenerator extends KeyPairGenerator {
51
52 /* Length for prime P and subPrime Q in bits */
53 private int plen;
54 private int qlen;
55
56 /* whether to force new parameters to be generated for each KeyPair */
57 boolean forceNewParameters;
58
59 /* preset algorithm parameters. */
60 private DSAParameterSpec params;
61
62 /* The source of random bits to use */
63 private SecureRandom random;
64
65 DSAKeyPairGenerator(int defaultKeySize) {
66 super("DSA");
67 initialize(defaultKeySize, null);
68 }
69
70 private static void checkStrength(int sizeP, int sizeQ) {
71 if ((sizeP >= 512) && (sizeP <= 1024) && (sizeP % 64 == 0)
72 && sizeQ == 160) {
73 // traditional - allow for backward compatibility
74 // L=multiples of 64 and between 512 and 1024 (inclusive)
75 // N=160
76 } else if (sizeP == 2048 && (sizeQ == 224 || sizeQ == 256)) {
77 // L=2048, N=224 or 256
78 } else {
79 throw new InvalidParameterException
80 ("Unsupported prime and subprime size combination: " +
81 sizeP + ", " + sizeQ);
82 }
83 }
84
85 public void initialize(int modlen, SecureRandom random) {
86 init(modlen, random, false);
87 }
88
89 /**
90 * Initializes the DSA object using a parameter object.
91 *
92 * @param params the parameter set to be used to generate
93 * the keys.
94 * @param random the source of randomness for this generator.
95 *
96 * @exception InvalidAlgorithmParameterException if the given parameters
97 * are inappropriate for this key pair generator
98 */
99 public void initialize(AlgorithmParameterSpec params, SecureRandom random)
100 throws InvalidAlgorithmParameterException {
101 if (!(params instanceof DSAParameterSpec)) {
102 throw new InvalidAlgorithmParameterException
103 ("Inappropriate parameter");
104 }
105 init((DSAParameterSpec)params, random, false);
106 }
107
108 void init(int modlen, SecureRandom random, boolean forceNew) {
109 int subPrimeLen = getDefDSASubprimeSize(modlen);
110 checkStrength(modlen, subPrimeLen);
111 this.plen = modlen;
112 this.qlen = subPrimeLen;
113 this.params = null;
114 this.random = random;
115 this.forceNewParameters = forceNew;
116 }
117
118 void init(DSAParameterSpec params, SecureRandom random,
119 boolean forceNew) {
120 int sizeP = params.getP().bitLength();
121 int sizeQ = params.getQ().bitLength();
122 checkStrength(sizeP, sizeQ);
123 this.plen = sizeP;
124 this.qlen = sizeQ;
125 this.params = params;
126 this.random = random;
127 this.forceNewParameters = forceNew;
128 }
129
130 /**
131 * Generates a pair of keys usable by any JavaSecurity compliant
132 * DSA implementation.
133 */
134 public KeyPair generateKeyPair() {
135 if (random == null) {
136 random = JCAUtil.getSecureRandom();
137 }
138 DSAParameterSpec spec;
139 try {
140 if (forceNewParameters) {
141 // generate new parameters each time
142 spec = ParameterCache.getNewDSAParameterSpec(plen, qlen, random);
143 } else {
144 if (params == null) {
145 params =
146 ParameterCache.getDSAParameterSpec(plen, qlen, random);
147 }
148 spec = params;
149 }
150 } catch (GeneralSecurityException e) {
151 throw new ProviderException(e);
152 }
153 return generateKeyPair(spec.getP(), spec.getQ(), spec.getG(), random);
154 }
155
156 private KeyPair generateKeyPair(BigInteger p, BigInteger q, BigInteger g,
157 SecureRandom random) {
158
159 BigInteger x = generateX(random, q);
160 BigInteger y = generateY(x, p, g);
161
162 try {
163
164 // See the comments in DSAKeyFactory, 4532506, and 6232513.
165
166 DSAPublicKey pub;
167 if (DSAKeyFactory.SERIAL_INTEROP) {
168 pub = new DSAPublicKey(y, p, q, g);
169 } else {
170 pub = new DSAPublicKeyImpl(y, p, q, g);
171 }
172 DSAPrivateKey priv = new DSAPrivateKey(x, p, q, g);
173
174 KeyPair pair = new KeyPair(pub, priv);
175 return pair;
176 } catch (InvalidKeyException e) {
191 random.nextBytes(temp);
192 x = new BigInteger(1, temp).mod(q);
193 if (x.signum() > 0 && (x.compareTo(q) < 0)) {
194 return x;
195 }
196 }
197 }
198
199 /**
200 * Generate the public key component y of the key pair.
201 *
202 * @param x the private key component.
203 *
204 * @param p the base parameter.
205 */
206 BigInteger generateY(BigInteger x, BigInteger p, BigInteger g) {
207 BigInteger y = g.modPow(x, p);
208 return y;
209 }
210
211 public static final class Current extends DSAKeyPairGenerator {
212 public Current() {
213 super(DEF_DSA_KEY_SIZE);
214 }
215 }
216
217 public static final class Legacy extends DSAKeyPairGenerator
218 implements java.security.interfaces.DSAKeyPairGenerator {
219
220 public Legacy() {
221 super(1024);
222 }
223
224 /**
225 * Initializes the DSA key pair generator. If <code>genParams</code>
226 * is false, a set of pre-computed parameters is used.
227 */
228 @Override
229 public void initialize(int modlen, boolean genParams,
230 SecureRandom random) throws InvalidParameterException {
231 if (genParams) {
232 super.init(modlen, random, true);
233 } else {
234 DSAParameterSpec cachedParams =
235 ParameterCache.getCachedDSAParameterSpec(modlen,
236 getDefDSASubprimeSize(modlen));
237 if (cachedParams == null) {
238 throw new InvalidParameterException
239 ("No precomputed parameters for requested modulus" +
240 " size available");
241 }
242 super.init(cachedParams, random, false);
243 }
244 }
245
246 /**
247 * Initializes the DSA object using a DSA parameter object.
248 *
249 * @param params a fully initialized DSA parameter object.
250 */
251 @Override
252 public void initialize(DSAParams params, SecureRandom random)
253 throws InvalidParameterException {
254 if (params == null) {
255 throw new InvalidParameterException("Params must not be null");
256 }
257 DSAParameterSpec spec = new DSAParameterSpec
258 (params.getP(), params.getQ(), params.getG());
259 super.init(spec, random, false);
260 }
261 }
262 }
|