History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/rsa/RSAKeyFactory.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/rsa/RSAKeyFactory.java+401−0
@@ -0,0 +1,401 @@
1/*
2 * Copyright (c) 2003, 2008, 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
26package sun.security.rsa;
27
28import java.math.BigInteger;
29
30import java.security.*;
31import java.security.interfaces.*;
32import java.security.spec.*;
33
34import sun.security.action.GetPropertyAction;
35
36/**
37 * KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
38 * and getAlgorithm() must return "RSA". For such keys, it supports conversion
39 * between the following:
40 *
41 * For public keys:
42 * . PublicKey with an X.509 encoding
43 * . RSAPublicKey
44 * . RSAPublicKeySpec
45 * . X509EncodedKeySpec
46 *
47 * For private keys:
48 * . PrivateKey with a PKCS#8 encoding
49 * . RSAPrivateKey
50 * . RSAPrivateCrtKey
51 * . RSAPrivateKeySpec
52 * . RSAPrivateCrtKeySpec
53 * . PKCS8EncodedKeySpec
54 * (of course, CRT variants only for CRT keys)
55 *
56 * Note: as always, RSA keys should be at least 512 bits long
57 *
58 * @since 1.5
59 * @author Andreas Sterbenz
60 */
61public final class RSAKeyFactory extends KeyFactorySpi {
62
63 private final static Class<?> rsaPublicKeySpecClass =
64 RSAPublicKeySpec.class;
65 private final static Class<?> rsaPrivateKeySpecClass =
66 RSAPrivateKeySpec.class;
67 private final static Class<?> rsaPrivateCrtKeySpecClass =
68 RSAPrivateCrtKeySpec.class;
69
70 private final static Class<?> x509KeySpecClass = X509EncodedKeySpec.class;
71 private final static Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
72
73 public final static int MIN_MODLEN = 512;
74 public final static int MAX_MODLEN = 16384;
75
76 /*
77 * If the modulus length is above this value, restrict the size of
78 * the exponent to something that can be reasonably computed. We
79 * could simply hardcode the exp len to something like 64 bits, but
80 * this approach allows flexibility in case impls would like to use
81 * larger module and exponent values.
82 */
83 public final static int MAX_MODLEN_RESTRICT_EXP = 3072;
84 public final static int MAX_RESTRICTED_EXPLEN = 64;
85
86 private static final boolean restrictExpLen =
87 "true".equalsIgnoreCase(AccessController.doPrivileged(
88 new GetPropertyAction(
89 "sun.security.rsa.restrictRSAExponent", "true")));
90
91 // instance used for static translateKey();
92 private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
93
94 public RSAKeyFactory() {
95 // empty
96 }
97
98 /**
99 * Static method to convert Key into an instance of RSAPublicKeyImpl
100 * or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
101 * used, throw an InvalidKeyException.
102 *
103 * Used by RSASignature and RSACipher.
104 */
105 public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
106 if ((key instanceof RSAPrivateKeyImpl) ||
107 (key instanceof RSAPrivateCrtKeyImpl) ||
108 (key instanceof RSAPublicKeyImpl)) {
109 return (RSAKey)key;
110 } else {
111 return (RSAKey)INSTANCE.engineTranslateKey(key);
112 }
113 }
114
115 /*
116 * Single test entry point for all of the mechanisms in the SunRsaSign
117 * provider (RSA*KeyImpls). All of the tests are the same.
118 *
119 * For compatibility, we round up to the nearest byte here:
120 * some Key impls might pass in a value within a byte of the
121 * real value.
122 */
123 static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
124 throws InvalidKeyException {
125 checkKeyLengths(((modulusLen + 7) & ~7), exponent,
126 RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
127 }
128
129 /**
130 * Check the length of an RSA key modulus/exponent to make sure it
131 * is not too short or long. Some impls have their own min and
132 * max key sizes that may or may not match with a system defined value.
133 *
134 * @param modulusLen the bit length of the RSA modulus.
135 * @param exponent the RSA exponent
136 * @param minModulusLen if > 0, check to see if modulusLen is at
137 * least this long, otherwise unused.
138 * @param maxModulusLen caller will allow this max number of bits.
139 * Allow the smaller of the system-defined maximum and this param.
140 *
141 * @throws InvalidKeyException if any of the values are unacceptable.
142 */
143 public static void checkKeyLengths(int modulusLen, BigInteger exponent,
144 int minModulusLen, int maxModulusLen) throws InvalidKeyException {
145
146 if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
147 throw new InvalidKeyException( "RSA keys must be at least " +
148 minModulusLen + " bits long");
149 }
150
151 // Even though our policy file may allow this, we don't want
152 // either value (mod/exp) to be too big.
153
154 int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
155
156 // If a RSAPrivateKey/RSAPublicKey, make sure the
157 // modulus len isn't too big.
158 if (modulusLen > maxLen) {
159 throw new InvalidKeyException(
160 "RSA keys must be no longer than " + maxLen + " bits");
161 }
162
163 // If a RSAPublicKey, make sure the exponent isn't too big.
164 if (restrictExpLen && (exponent != null) &&
165 (modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
166 (exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
167 throw new InvalidKeyException(
168 "RSA exponents can be no longer than " +
169 MAX_RESTRICTED_EXPLEN + " bits " +
170 " if modulus is greater than " +
171 MAX_MODLEN_RESTRICT_EXP + " bits");
172 }
173 }
174
175 /**
176 * Translate an RSA key into a SunRsaSign RSA key. If conversion is
177 * not possible, throw an InvalidKeyException.
178 * See also JCA doc.
179 */
180 protected Key engineTranslateKey(Key key) throws InvalidKeyException {
181 if (key == null) {
182 throw new InvalidKeyException("Key must not be null");
183 }
184 String keyAlg = key.getAlgorithm();
185 if (keyAlg.equals("RSA") == false) {
186 throw new InvalidKeyException("Not an RSA key: " + keyAlg);
187 }
188 if (key instanceof PublicKey) {
189 return translatePublicKey((PublicKey)key);
190 } else if (key instanceof PrivateKey) {
191 return translatePrivateKey((PrivateKey)key);
192 } else {
193 throw new InvalidKeyException("Neither a public nor a private key");
194 }
195 }
196
197 // see JCA doc
198 protected PublicKey engineGeneratePublic(KeySpec keySpec)
199 throws InvalidKeySpecException {
200 try {
201 return generatePublic(keySpec);
202 } catch (InvalidKeySpecException e) {
203 throw e;
204 } catch (GeneralSecurityException e) {
205 throw new InvalidKeySpecException(e);
206 }
207 }
208
209 // see JCA doc
210 protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
211 throws InvalidKeySpecException {
212 try {
213 return generatePrivate(keySpec);
214 } catch (InvalidKeySpecException e) {
215 throw e;
216 } catch (GeneralSecurityException e) {
217 throw new InvalidKeySpecException(e);
218 }
219 }
220
221 // internal implementation of translateKey() for public keys. See JCA doc
222 private PublicKey translatePublicKey(PublicKey key)
223 throws InvalidKeyException {
224 if (key instanceof RSAPublicKey) {
225 if (key instanceof RSAPublicKeyImpl) {
226 return key;
227 }
228 RSAPublicKey rsaKey = (RSAPublicKey)key;
229 try {
230 return new RSAPublicKeyImpl(
231 rsaKey.getModulus(),
232 rsaKey.getPublicExponent()
233 );
234 } catch (RuntimeException e) {
235 // catch providers that incorrectly implement RSAPublicKey
236 throw new InvalidKeyException("Invalid key", e);
237 }
238 } else if ("X.509".equals(key.getFormat())) {
239 byte[] encoded = key.getEncoded();
240 return new RSAPublicKeyImpl(encoded);
241 } else {
242 throw new InvalidKeyException("Public keys must be instance "
243 + "of RSAPublicKey or have X.509 encoding");
244 }
245 }
246
247 // internal implementation of translateKey() for private keys. See JCA doc
248 private PrivateKey translatePrivateKey(PrivateKey key)
249 throws InvalidKeyException {
250 if (key instanceof RSAPrivateCrtKey) {
251 if (key instanceof RSAPrivateCrtKeyImpl) {
252 return key;
253 }
254 RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey)key;
255 try {
256 return new RSAPrivateCrtKeyImpl(
257 rsaKey.getModulus(),
258 rsaKey.getPublicExponent(),
259 rsaKey.getPrivateExponent(),
260 rsaKey.getPrimeP(),
261 rsaKey.getPrimeQ(),
262 rsaKey.getPrimeExponentP(),
263 rsaKey.getPrimeExponentQ(),
264 rsaKey.getCrtCoefficient()
265 );
266 } catch (RuntimeException e) {
267 // catch providers that incorrectly implement RSAPrivateCrtKey
268 throw new InvalidKeyException("Invalid key", e);
269 }
270 } else if (key instanceof RSAPrivateKey) {
271 if (key instanceof RSAPrivateKeyImpl) {
272 return key;
273 }
274 RSAPrivateKey rsaKey = (RSAPrivateKey)key;
275 try {
276 return new RSAPrivateKeyImpl(
277 rsaKey.getModulus(),
278 rsaKey.getPrivateExponent()
279 );
280 } catch (RuntimeException e) {
281 // catch providers that incorrectly implement RSAPrivateKey
282 throw new InvalidKeyException("Invalid key", e);
283 }
284 } else if ("PKCS#8".equals(key.getFormat())) {
285 byte[] encoded = key.getEncoded();
286 return RSAPrivateCrtKeyImpl.newKey(encoded);
287 } else {
288 throw new InvalidKeyException("Private keys must be instance "
289 + "of RSAPrivate(Crt)Key or have PKCS#8 encoding");
290 }
291 }
292
293 // internal implementation of generatePublic. See JCA doc
294 private PublicKey generatePublic(KeySpec keySpec)
295 throws GeneralSecurityException {
296 if (keySpec instanceof X509EncodedKeySpec) {
297 X509EncodedKeySpec x509Spec = (X509EncodedKeySpec)keySpec;
298 return new RSAPublicKeyImpl(x509Spec.getEncoded());
299 } else if (keySpec instanceof RSAPublicKeySpec) {
300 RSAPublicKeySpec rsaSpec = (RSAPublicKeySpec)keySpec;
301 return new RSAPublicKeyImpl(
302 rsaSpec.getModulus(),
303 rsaSpec.getPublicExponent()
304 );
305 } else {
306 throw new InvalidKeySpecException("Only RSAPublicKeySpec "
307 + "and X509EncodedKeySpec supported for RSA public keys");
308 }
309 }
310
311 // internal implementation of generatePrivate. See JCA doc
312 private PrivateKey generatePrivate(KeySpec keySpec)
313 throws GeneralSecurityException {
314 if (keySpec instanceof PKCS8EncodedKeySpec) {
315 PKCS8EncodedKeySpec pkcsSpec = (PKCS8EncodedKeySpec)keySpec;
316 return RSAPrivateCrtKeyImpl.newKey(pkcsSpec.getEncoded());
317 } else if (keySpec instanceof RSAPrivateCrtKeySpec) {
318 RSAPrivateCrtKeySpec rsaSpec = (RSAPrivateCrtKeySpec)keySpec;
319 return new RSAPrivateCrtKeyImpl(
320 rsaSpec.getModulus(),
321 rsaSpec.getPublicExponent(),
322 rsaSpec.getPrivateExponent(),
323 rsaSpec.getPrimeP(),
324 rsaSpec.getPrimeQ(),
325 rsaSpec.getPrimeExponentP(),
326 rsaSpec.getPrimeExponentQ(),
327 rsaSpec.getCrtCoefficient()
328 );
329 } else if (keySpec instanceof RSAPrivateKeySpec) {
330 RSAPrivateKeySpec rsaSpec = (RSAPrivateKeySpec)keySpec;
331 return new RSAPrivateKeyImpl(
332 rsaSpec.getModulus(),
333 rsaSpec.getPrivateExponent()
334 );
335 } else {
336 throw new InvalidKeySpecException("Only RSAPrivate(Crt)KeySpec "
337 + "and PKCS8EncodedKeySpec supported for RSA private keys");
338 }
339 }
340
341 protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
342 throws InvalidKeySpecException {
343 try {
344 // convert key to one of our keys
345 // this also verifies that the key is a valid RSA key and ensures
346 // that the encoding is X.509/PKCS#8 for public/private keys
347 key = engineTranslateKey(key);
348 } catch (InvalidKeyException e) {
349 throw new InvalidKeySpecException(e);
350 }
351 if (key instanceof RSAPublicKey) {
352 RSAPublicKey rsaKey = (RSAPublicKey)key;
353 if (rsaPublicKeySpecClass.isAssignableFrom(keySpec)) {
354 return (T) new RSAPublicKeySpec(
355 rsaKey.getModulus(),
356 rsaKey.getPublicExponent()
357 );
358 } else if (x509KeySpecClass.isAssignableFrom(keySpec)) {
359 return (T) new X509EncodedKeySpec(key.getEncoded());
360 } else {
361 throw new InvalidKeySpecException
362 ("KeySpec must be RSAPublicKeySpec or "
363 + "X509EncodedKeySpec for RSA public keys");
364 }
365 } else if (key instanceof RSAPrivateKey) {
366 if (pkcs8KeySpecClass.isAssignableFrom(keySpec)) {
367 return (T) new PKCS8EncodedKeySpec(key.getEncoded());
368 } else if (rsaPrivateCrtKeySpecClass.isAssignableFrom(keySpec)) {
369 if (key instanceof RSAPrivateCrtKey) {
370 RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)key;
371 return (T) new RSAPrivateCrtKeySpec(
372 crtKey.getModulus(),
373 crtKey.getPublicExponent(),
374 crtKey.getPrivateExponent(),
375 crtKey.getPrimeP(),
376 crtKey.getPrimeQ(),
377 crtKey.getPrimeExponentP(),
378 crtKey.getPrimeExponentQ(),
379 crtKey.getCrtCoefficient()
380 );
381 } else {
382 throw new InvalidKeySpecException
383 ("RSAPrivateCrtKeySpec can only be used with CRT keys");
384 }
385 } else if (rsaPrivateKeySpecClass.isAssignableFrom(keySpec)) {
386 RSAPrivateKey rsaKey = (RSAPrivateKey)key;
387 return (T) new RSAPrivateKeySpec(
388 rsaKey.getModulus(),
389 rsaKey.getPrivateExponent()
390 );
391 } else {
392 throw new InvalidKeySpecException
393 ("KeySpec must be RSAPrivate(Crt)KeySpec or "
394 + "PKCS8EncodedKeySpec for RSA private keys");
395 }
396 } else {
397 // should not occur, caught in engineTranslateKey()
398 throw new InvalidKeySpecException("Neither public nor private key");
399 }
400 }
401}