1 /* EncodedKeyFactory.java -- JCE Encoded key factory Adapter
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu
.java
.security
.jce
.sig
;
41 import gnu
.java
.security
.Registry
;
42 import gnu
.java
.security
.key
.dss
.DSSPrivateKey
;
43 import gnu
.java
.security
.key
.dss
.DSSPublicKey
;
44 import gnu
.java
.security
.key
.rsa
.GnuRSAPrivateKey
;
45 import gnu
.java
.security
.key
.rsa
.GnuRSAPublicKey
;
47 import java
.lang
.reflect
.Constructor
;
48 import java
.lang
.reflect
.InvocationTargetException
;
49 import java
.lang
.reflect
.Method
;
50 import java
.math
.BigInteger
;
51 import java
.security
.InvalidKeyException
;
52 import java
.security
.InvalidParameterException
;
53 import java
.security
.Key
;
54 import java
.security
.KeyFactorySpi
;
55 import java
.security
.PrivateKey
;
56 import java
.security
.PublicKey
;
57 import java
.security
.spec
.DSAPrivateKeySpec
;
58 import java
.security
.spec
.DSAPublicKeySpec
;
59 import java
.security
.spec
.InvalidKeySpecException
;
60 import java
.security
.spec
.KeySpec
;
61 import java
.security
.spec
.PKCS8EncodedKeySpec
;
62 import java
.security
.spec
.RSAPrivateCrtKeySpec
;
63 import java
.security
.spec
.RSAPublicKeySpec
;
64 import java
.security
.spec
.X509EncodedKeySpec
;
65 import java
.util
.logging
.Level
;
66 import java
.util
.logging
.Logger
;
68 import javax
.crypto
.interfaces
.DHPrivateKey
;
69 import javax
.crypto
.interfaces
.DHPublicKey
;
70 import javax
.crypto
.spec
.DHPrivateKeySpec
;
71 import javax
.crypto
.spec
.DHPublicKeySpec
;
74 * A factory for keys encoded in either the X.509 format (for public keys) or
75 * the PKCS#8 format (for private keys).
77 public class EncodedKeyFactory
80 private static final Logger log
= Logger
.getLogger(EncodedKeyFactory
.class.getName());
82 // implicit 0-arguments constructor
85 // --------------------------------------------------------------------------
87 private static Object
invokeConstructor(String className
, Object
[] params
)
88 throws InvalidKeySpecException
90 Class clazz
= getConcreteClass(className
);
93 Constructor ctor
= getConcreteCtor(clazz
);
94 Object result
= ctor
.newInstance(params
);
97 catch (InstantiationException x
)
99 InvalidKeySpecException y
= new InvalidKeySpecException();
103 catch (IllegalAccessException x
)
105 InvalidKeySpecException y
= new InvalidKeySpecException();
109 catch (InvocationTargetException x
)
111 InvalidKeySpecException y
= new InvalidKeySpecException();
117 private static Class
getConcreteClass(String className
)
118 throws InvalidKeySpecException
122 Class result
= Class
.forName(className
);
125 catch (ClassNotFoundException x
)
127 InvalidKeySpecException y
= new InvalidKeySpecException();
133 private static Constructor
getConcreteCtor(Class clazz
)
134 throws InvalidKeySpecException
138 Constructor result
= clazz
.getConstructor(new Class
[] {int.class,
145 catch (NoSuchMethodException x
)
147 InvalidKeySpecException y
= new InvalidKeySpecException();
153 private static Object
invokeValueOf(String className
, byte[] encoded
)
154 throws InvalidKeySpecException
156 Class clazz
= getConcreteClass(className
);
159 Method valueOf
= getValueOfMethod(clazz
);
160 Object result
= valueOf
.invoke(null, new Object
[] { encoded
});
163 catch (IllegalAccessException x
)
165 InvalidKeySpecException y
= new InvalidKeySpecException();
169 catch (InvocationTargetException x
)
171 InvalidKeySpecException y
= new InvalidKeySpecException();
177 private static Method
getValueOfMethod(Class clazz
)
178 throws InvalidKeySpecException
182 Method result
= clazz
.getMethod("valueOf", new Class
[] {byte[].class});
185 catch (NoSuchMethodException x
)
187 InvalidKeySpecException y
= new InvalidKeySpecException();
194 // --------------------------------------------------------------------------
196 protected PublicKey
engineGeneratePublic(KeySpec keySpec
)
197 throws InvalidKeySpecException
199 log
.entering(this.getClass().getName(), "engineGeneratePublic()", keySpec
);
201 PublicKey result
= null;
202 if (keySpec
instanceof DSAPublicKeySpec
)
203 result
= decodeDSSPublicKey((DSAPublicKeySpec
) keySpec
);
204 else if (keySpec
instanceof RSAPublicKeySpec
)
205 result
= decodeRSAPublicKey((RSAPublicKeySpec
) keySpec
);
206 else if (keySpec
instanceof DHPublicKeySpec
)
207 result
= decodeDHPublicKey((DHPublicKeySpec
) keySpec
);
210 if (! (keySpec
instanceof X509EncodedKeySpec
))
211 throw new InvalidKeySpecException("Unsupported key specification");
213 byte[] input
= ((X509EncodedKeySpec
) keySpec
).getEncoded();
218 result
= DSSPublicKey
.valueOf(input
);
221 catch (InvalidParameterException ignored
)
223 log
.log(Level
.FINE
, "Exception in DSSPublicKey.valueOf(). Ignore",
230 result
= GnuRSAPublicKey
.valueOf(input
);
233 catch (InvalidParameterException ignored
)
236 "Exception in GnuRSAPublicKey.valueOf(). Ignore",
241 result
= decodeDHPublicKey(input
);
244 log
.exiting(this.getClass().getName(), "engineGeneratePublic()", result
);
248 protected PrivateKey
engineGeneratePrivate(KeySpec keySpec
)
249 throws InvalidKeySpecException
251 log
.entering(this.getClass().getName(), "engineGeneratePrivate()", keySpec
);
253 PrivateKey result
= null;
254 if (keySpec
instanceof DSAPrivateKeySpec
)
255 result
= decodeDSSPrivateKey((DSAPrivateKeySpec
) keySpec
);
256 else if (keySpec
instanceof RSAPrivateCrtKeySpec
)
257 result
= decodeRSAPrivateKey((RSAPrivateCrtKeySpec
) keySpec
);
258 else if (keySpec
instanceof DHPrivateKeySpec
)
259 result
= decodeDHPrivateKey((DHPrivateKeySpec
) keySpec
);
262 if (! (keySpec
instanceof PKCS8EncodedKeySpec
))
263 throw new InvalidKeySpecException("Unsupported key specification");
265 byte[] input
= ((PKCS8EncodedKeySpec
) keySpec
).getEncoded();
270 result
= DSSPrivateKey
.valueOf(input
);
273 catch (InvalidParameterException ignored
)
275 log
.log(Level
.FINE
, "Exception in DSSPrivateKey.valueOf(). Ignore",
282 result
= GnuRSAPrivateKey
.valueOf(input
);
285 catch (InvalidParameterException ignored
)
288 "Exception in GnuRSAPrivateKey.valueOf(). Ignore",
293 result
= decodeDHPrivateKey(input
);
296 log
.exiting(this.getClass().getName(), "engineGeneratePrivate()", result
);
300 protected KeySpec
engineGetKeySpec(Key key
, Class keySpec
)
301 throws InvalidKeySpecException
303 if (key
instanceof PublicKey
304 && Registry
.X509_ENCODING_SORT_NAME
.equalsIgnoreCase(key
.getFormat())
305 && keySpec
.isAssignableFrom(X509EncodedKeySpec
.class))
306 return new X509EncodedKeySpec(key
.getEncoded());
308 if (key
instanceof PrivateKey
309 && Registry
.PKCS8_ENCODING_SHORT_NAME
.equalsIgnoreCase(key
.getFormat())
310 && keySpec
.isAssignableFrom(PKCS8EncodedKeySpec
.class))
311 return new PKCS8EncodedKeySpec(key
.getEncoded());
313 throw new InvalidKeySpecException("Unsupported format or invalid key spec class");
316 protected Key
engineTranslateKey(Key key
) throws InvalidKeyException
318 throw new InvalidKeyException("Key translation not supported");
322 * @param spec an instance of {@link DSAPublicKeySpec} to decode.
323 * @return an instance of {@link DSSPublicKey} constructed from the
324 * information in the designated key-specification.
326 private DSSPublicKey
decodeDSSPublicKey(DSAPublicKeySpec spec
)
328 BigInteger p
= spec
.getP();
329 BigInteger q
= spec
.getQ();
330 BigInteger g
= spec
.getG();
331 BigInteger y
= spec
.getY();
332 return new DSSPublicKey(Registry
.X509_ENCODING_ID
, p
, q
, g
, y
);
336 * @param spec an instance of {@link RSAPublicKeySpec} to decode.
337 * @return an instance of {@link GnuRSAPublicKey} constructed from the
338 * information in the designated key-specification.
340 private GnuRSAPublicKey
decodeRSAPublicKey(RSAPublicKeySpec spec
)
342 BigInteger n
= spec
.getModulus();
343 BigInteger e
= spec
.getPublicExponent();
344 return new GnuRSAPublicKey(Registry
.X509_ENCODING_ID
, n
, e
);
348 * @param spec an instance of {@link DHPublicKeySpec} to decode.
349 * @return an instance of a {@link DHPublicKey} constructed from the
350 * information in the designated key-specification.
351 * @throws InvalidKeySpecException if no concrete implementation of the
352 * {@link DHPublicKey} interface exists at run-time, or if an
353 * exception occurs during its instantiation.
355 private DHPublicKey
decodeDHPublicKey(DHPublicKeySpec spec
)
356 throws InvalidKeySpecException
358 BigInteger p
= spec
.getP();
359 BigInteger g
= spec
.getG();
360 BigInteger y
= spec
.getY();
361 Object
[] params
= new Object
[] {new Integer(Registry
.X509_ENCODING_ID
),
363 Object obj
= invokeConstructor("gnu.javax.crypto.key.dh.GnuDHPublicKey",
365 return (DHPublicKey
) obj
;
369 * @param encoded the bytes to decode.
370 * @return an instance of a {@link DHPublicKey} constructed from the
371 * information in the designated key-specification.
372 * @throws InvalidKeySpecException if no concrete implementation of the
373 * {@link DHPublicKey} interface exists at run-time, or if an
374 * exception occurs during its instantiation.
376 private DHPublicKey
decodeDHPublicKey(byte[] encoded
)
377 throws InvalidKeySpecException
379 Object obj
= invokeValueOf("gnu.javax.crypto.key.dh.GnuDHPublicKey",
381 return (DHPublicKey
) obj
;
385 * @param spec an instance of {@link DSAPrivateKeySpec} to decode.
386 * @return an instance of {@link DSSPrivateKey} constructed from the
387 * information in the designated key-specification.
389 private PrivateKey
decodeDSSPrivateKey(DSAPrivateKeySpec spec
)
391 BigInteger p
= spec
.getP();
392 BigInteger q
= spec
.getQ();
393 BigInteger g
= spec
.getG();
394 BigInteger x
= spec
.getX();
395 return new DSSPrivateKey(Registry
.PKCS8_ENCODING_ID
, p
, q
, g
, x
);
399 * @param spec an instance of {@link RSAPrivateCrtKeySpec} to decode.
400 * @return an instance of {@link GnuRSAPrivateKey} constructed from the
401 * information in the designated key-specification.
403 private PrivateKey
decodeRSAPrivateKey(RSAPrivateCrtKeySpec spec
)
405 BigInteger n
= spec
.getModulus();
406 BigInteger e
= spec
.getPublicExponent();
407 BigInteger d
= spec
.getPrivateExponent();
408 BigInteger p
= spec
.getPrimeP();
409 BigInteger q
= spec
.getPrimeQ();
410 BigInteger dP
= spec
.getPrimeExponentP();
411 BigInteger dQ
= spec
.getPrimeExponentQ();
412 BigInteger qInv
= spec
.getCrtCoefficient();
413 return new GnuRSAPrivateKey(Registry
.PKCS8_ENCODING_ID
,
414 n
, e
, d
, p
, q
, dP
, dQ
, qInv
);
418 * @param spec an instance of {@link DHPrivateKeySpec} to decode.
419 * @return an instance of a {@link DHPrivateKey} constructed from the
420 * information in the designated key-specification.
421 * @throws InvalidKeySpecException if no concrete implementation of the
422 * {@link DHPrivateKey} interface exists at run-time, or if an
423 * exception occurs during its instantiation.
425 private DHPrivateKey
decodeDHPrivateKey(DHPrivateKeySpec spec
)
426 throws InvalidKeySpecException
428 BigInteger p
= spec
.getP();
429 BigInteger g
= spec
.getG();
430 BigInteger x
= spec
.getX();
431 Object
[] params
= new Object
[] {new Integer(Registry
.PKCS8_ENCODING_ID
),
433 Object obj
= invokeConstructor("gnu.javax.crypto.key.dh.GnuDHPrivateKey",
435 return (DHPrivateKey
) obj
;
439 * @param encoded the bytes to decode.
440 * @return an instance of a {@link DHPrivateKey} constructed from the
441 * information in the designated key-specification.
442 * @throws InvalidKeySpecException if no concrete implementation of the
443 * {@link DHPrivateKey} interface exists at run-time, or if an
444 * exception occurs during its instantiation.
446 private DHPrivateKey
decodeDHPrivateKey(byte[] encoded
)
447 throws InvalidKeySpecException
449 Object obj
= invokeValueOf("gnu.javax.crypto.key.dh.GnuDHPrivateKey",
451 return (DHPrivateKey
) obj
;