001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    
018    package org.apache.geronimo.util.jce.provider;
019    
020    import java.io.ByteArrayInputStream;
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.security.InvalidKeyException;
024    import java.security.Key;
025    import java.security.KeyFactorySpi;
026    import java.security.PrivateKey;
027    import java.security.PublicKey;
028    import java.security.interfaces.DSAPrivateKey;
029    import java.security.interfaces.DSAPublicKey;
030    import java.security.interfaces.RSAPrivateCrtKey;
031    import java.security.interfaces.RSAPrivateKey;
032    import java.security.interfaces.RSAPublicKey;
033    import java.security.spec.DSAPrivateKeySpec;
034    import java.security.spec.DSAPublicKeySpec;
035    import java.security.spec.InvalidKeySpecException;
036    import java.security.spec.KeySpec;
037    import java.security.spec.PKCS8EncodedKeySpec;
038    import java.security.spec.RSAPrivateCrtKeySpec;
039    import java.security.spec.RSAPrivateKeySpec;
040    import java.security.spec.RSAPublicKeySpec;
041    import java.security.spec.X509EncodedKeySpec;
042    
043    import javax.crypto.interfaces.DHPrivateKey;
044    import javax.crypto.interfaces.DHPublicKey;
045    import javax.crypto.spec.DHPrivateKeySpec;
046    import javax.crypto.spec.DHPublicKeySpec;
047    
048    import org.apache.geronimo.util.asn1.ASN1InputStream;
049    import org.apache.geronimo.util.asn1.ASN1Sequence;
050    import org.apache.geronimo.util.asn1.cryptopro.CryptoProObjectIdentifiers;
051    import org.apache.geronimo.util.asn1.oiw.OIWObjectIdentifiers;
052    import org.apache.geronimo.util.asn1.pkcs.PKCSObjectIdentifiers;
053    import org.apache.geronimo.util.asn1.pkcs.PrivateKeyInfo;
054    import org.apache.geronimo.util.asn1.pkcs.RSAPrivateKeyStructure;
055    import org.apache.geronimo.util.asn1.x509.AlgorithmIdentifier;
056    import org.apache.geronimo.util.asn1.x509.SubjectPublicKeyInfo;
057    import org.apache.geronimo.util.asn1.x509.X509ObjectIdentifiers;
058    import org.apache.geronimo.util.asn1.x9.X9ObjectIdentifiers;
059    import org.apache.geronimo.util.jce.provider.JCEDHPrivateKey;
060    import org.apache.geronimo.util.jce.provider.JCEDHPublicKey;
061    
062    public abstract class JDKKeyFactory
063        extends KeyFactorySpi
064    {
065        public JDKKeyFactory()
066        {
067        }
068    
069        protected KeySpec engineGetKeySpec(
070            Key    key,
071            Class    spec)
072        throws InvalidKeySpecException
073        {
074           if (spec.isAssignableFrom(PKCS8EncodedKeySpec.class) && key.getFormat().equals("PKCS#8"))
075           {
076                   return new PKCS8EncodedKeySpec(key.getEncoded());
077           }
078           else if (spec.isAssignableFrom(X509EncodedKeySpec.class) && key.getFormat().equals("X.509"))
079           {
080                   return new X509EncodedKeySpec(key.getEncoded());
081           }
082           else if (spec.isAssignableFrom(RSAPublicKeySpec.class) && key instanceof RSAPublicKey)
083           {
084                RSAPublicKey    k = (RSAPublicKey)key;
085    
086                return new RSAPublicKeySpec(k.getModulus(), k.getPublicExponent());
087           }
088           else if (spec.isAssignableFrom(RSAPrivateKeySpec.class) && key instanceof RSAPrivateKey)
089           {
090                RSAPrivateKey    k = (RSAPrivateKey)key;
091    
092                return new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent());
093           }
094           else if (spec.isAssignableFrom(RSAPrivateCrtKeySpec.class) && key instanceof RSAPrivateCrtKey)
095           {
096                RSAPrivateCrtKey    k = (RSAPrivateCrtKey)key;
097    
098                return new RSAPrivateCrtKeySpec(
099                                k.getModulus(), k.getPublicExponent(),
100                                k.getPrivateExponent(),
101                                k.getPrimeP(), k.getPrimeQ(),
102                                k.getPrimeExponentP(), k.getPrimeExponentQ(),
103                                k.getCrtCoefficient());
104           }
105           else if (spec.isAssignableFrom(DHPrivateKeySpec.class) && key instanceof DHPrivateKey)
106           {
107               DHPrivateKey k = (DHPrivateKey)key;
108    
109               return new DHPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getG());
110           }
111           else if (spec.isAssignableFrom(DHPublicKeySpec.class) && key instanceof DHPublicKey)
112           {
113               DHPublicKey k = (DHPublicKey)key;
114    
115               return new DHPublicKeySpec(k.getY(), k.getParams().getP(), k.getParams().getG());
116           }
117    
118            throw new RuntimeException("not implemented yet " + key + " " + spec);
119        }
120    
121        protected Key engineTranslateKey(
122            Key    key)
123            throws InvalidKeyException
124        {
125            if (key instanceof RSAPublicKey)
126            {
127                return new JCERSAPublicKey((RSAPublicKey)key);
128            }
129            else if (key instanceof RSAPrivateCrtKey)
130            {
131                return new JCERSAPrivateCrtKey((RSAPrivateCrtKey)key);
132            }
133            else if (key instanceof RSAPrivateKey)
134            {
135                return new JCERSAPrivateKey((RSAPrivateKey)key);
136            }
137            else if (key instanceof DHPublicKey)
138            {
139                return new JCEDHPublicKey((DHPublicKey)key);
140            }
141            else if (key instanceof DHPrivateKey)
142            {
143                return new JCEDHPrivateKey((DHPrivateKey)key);
144            }
145            else if (key instanceof DSAPublicKey)
146            {
147                return new JDKDSAPublicKey((DSAPublicKey)key);
148            }
149            else if (key instanceof DSAPrivateKey)
150            {
151                return new JDKDSAPrivateKey((DSAPrivateKey)key);
152            }
153            throw new InvalidKeyException("key type unknown");
154        }
155    
156        /**
157         * create a public key from the given DER encoded input stream.
158         */
159        static PublicKey createPublicKeyFromDERStream(
160            InputStream         in)
161            throws IOException
162        {
163            return createPublicKeyFromPublicKeyInfo(
164                    new SubjectPublicKeyInfo((ASN1Sequence)(new ASN1InputStream(in).readObject())));
165        }
166    
167        /**
168         * create a public key from the given public key info object.
169         */
170        static PublicKey createPublicKeyFromPublicKeyInfo(
171            SubjectPublicKeyInfo         info)
172        {
173            AlgorithmIdentifier     algId = info.getAlgorithmId();
174    
175            if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption)
176                || algId.getObjectId().equals(X509ObjectIdentifiers.id_ea_rsa))
177            {
178                  return new JCERSAPublicKey(info);
179            }
180            else if (algId.getObjectId().equals(PKCSObjectIdentifiers.dhKeyAgreement))
181            {
182                  return new JCEDHPublicKey(info);
183            }
184            else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
185            {
186                  return new JCEDHPublicKey(info);
187            }
188            else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa))
189            {
190                  return new JDKDSAPublicKey(info);
191            }
192            else if (algId.getObjectId().equals(OIWObjectIdentifiers.dsaWithSHA1))
193            {
194                  return new JDKDSAPublicKey(info);
195            }
196            else
197            {
198                throw new RuntimeException("algorithm identifier in key not recognised");
199            }
200        }
201    
202        /**
203         * create a private key from the given DER encoded input stream.
204         */
205        static PrivateKey createPrivateKeyFromDERStream(
206            InputStream         in)
207            throws IOException
208        {
209            return createPrivateKeyFromPrivateKeyInfo(
210                    new PrivateKeyInfo((ASN1Sequence)(new ASN1InputStream(in).readObject())));
211        }
212    
213        /**
214         * create a private key from the given public key info object.
215         */
216        static PrivateKey createPrivateKeyFromPrivateKeyInfo(
217            PrivateKeyInfo      info)
218        {
219            AlgorithmIdentifier     algId = info.getAlgorithmId();
220    
221            if (algId.getObjectId().equals(PKCSObjectIdentifiers.rsaEncryption))
222            {
223                  return new JCERSAPrivateCrtKey(info);
224            }
225            else if (algId.getObjectId().equals(PKCSObjectIdentifiers.dhKeyAgreement))
226            {
227                  return new JCEDHPrivateKey(info);
228            }
229            else if (algId.getObjectId().equals(X9ObjectIdentifiers.id_dsa))
230            {
231                  return new JDKDSAPrivateKey(info);
232            }
233            else
234            {
235                throw new RuntimeException("algorithm identifier in key not recognised");
236            }
237        }
238    
239        public static class RSA
240            extends JDKKeyFactory
241        {
242            public RSA()
243            {
244            }
245    
246            protected PrivateKey engineGeneratePrivate(
247                KeySpec    keySpec)
248                throws InvalidKeySpecException
249            {
250                if (keySpec instanceof PKCS8EncodedKeySpec)
251                {
252                    try
253                    {
254                        return JDKKeyFactory.createPrivateKeyFromDERStream(
255                                    new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
256                    }
257                    catch (Exception e)
258                    {
259                        //
260                        // in case it's just a RSAPrivateKey object...
261                        //
262                        try
263                        {
264                            return new JCERSAPrivateCrtKey(
265                                new RSAPrivateKeyStructure(
266                                    (ASN1Sequence)new ASN1InputStream(new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded())).readObject()));
267                        }
268                        catch (Exception ex)
269                        {
270                            throw (InvalidKeySpecException)new InvalidKeySpecException(ex.getMessage()).initCause(ex);
271                        }
272                    }
273                }
274                else if (keySpec instanceof RSAPrivateCrtKeySpec)
275                {
276                    return new JCERSAPrivateCrtKey((RSAPrivateCrtKeySpec)keySpec);
277                }
278                else if (keySpec instanceof RSAPrivateKeySpec)
279                {
280                    return new JCERSAPrivateKey((RSAPrivateKeySpec)keySpec);
281                }
282    
283                throw new InvalidKeySpecException("Unknown KeySpec type.");
284            }
285    
286            protected PublicKey engineGeneratePublic(
287                KeySpec    keySpec)
288                throws InvalidKeySpecException
289            {
290                if (keySpec instanceof X509EncodedKeySpec)
291                {
292                    try
293                    {
294                        return JDKKeyFactory.createPublicKeyFromDERStream(
295                                    new ByteArrayInputStream(((X509EncodedKeySpec)keySpec).getEncoded()));
296                    }
297                    catch (Exception e)
298                    {
299                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
300                    }
301                }
302                else if (keySpec instanceof RSAPublicKeySpec)
303                {
304                    return new JCERSAPublicKey((RSAPublicKeySpec)keySpec);
305                }
306    
307                throw new InvalidKeySpecException("Unknown KeySpec type.");
308            }
309        }
310    
311        public static class DH
312            extends JDKKeyFactory
313        {
314            public DH()
315            {
316            }
317    
318            protected PrivateKey engineGeneratePrivate(
319                KeySpec    keySpec)
320                throws InvalidKeySpecException
321            {
322                if (keySpec instanceof PKCS8EncodedKeySpec)
323                {
324                    try
325                    {
326                        return JDKKeyFactory.createPrivateKeyFromDERStream(
327                                    new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
328                    }
329                    catch (Exception e)
330                    {
331                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
332                    }
333                }
334                else if (keySpec instanceof DHPrivateKeySpec)
335                {
336                    return new JCEDHPrivateKey((DHPrivateKeySpec)keySpec);
337                }
338    
339                throw new InvalidKeySpecException("Unknown KeySpec type.");
340            }
341    
342            protected PublicKey engineGeneratePublic(
343                KeySpec    keySpec)
344                throws InvalidKeySpecException
345            {
346                if (keySpec instanceof X509EncodedKeySpec)
347                {
348                    try
349                    {
350                        return JDKKeyFactory.createPublicKeyFromDERStream(
351                                    new ByteArrayInputStream(((X509EncodedKeySpec)keySpec).getEncoded()));
352                    }
353                    catch (Exception e)
354                    {
355                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
356                    }
357                }
358                else if (keySpec instanceof DHPublicKeySpec)
359                {
360                    return new JCEDHPublicKey((DHPublicKeySpec)keySpec);
361                }
362    
363                throw new InvalidKeySpecException("Unknown KeySpec type.");
364            }
365        }
366    
367        public static class DSA
368            extends JDKKeyFactory
369        {
370            public DSA()
371            {
372            }
373    
374            protected PrivateKey engineGeneratePrivate(
375                KeySpec    keySpec)
376                throws InvalidKeySpecException
377            {
378                if (keySpec instanceof PKCS8EncodedKeySpec)
379                {
380                    try
381                    {
382                        return JDKKeyFactory.createPrivateKeyFromDERStream(
383                                    new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
384                    }
385                    catch (Exception e)
386                    {
387                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
388                    }
389                }
390                else if (keySpec instanceof DSAPrivateKeySpec)
391                {
392                    return new JDKDSAPrivateKey((DSAPrivateKeySpec)keySpec);
393                }
394    
395                throw new InvalidKeySpecException("Unknown KeySpec type.");
396            }
397    
398            protected PublicKey engineGeneratePublic(
399                KeySpec    keySpec)
400                throws InvalidKeySpecException
401            {
402                if (keySpec instanceof X509EncodedKeySpec)
403                {
404                    try
405                    {
406                        return JDKKeyFactory.createPublicKeyFromDERStream(
407                                    new ByteArrayInputStream(((X509EncodedKeySpec)keySpec).getEncoded()));
408                    }
409                    catch (Exception e)
410                    {
411                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
412                    }
413                }
414                else if (keySpec instanceof DSAPublicKeySpec)
415                {
416                    return new JDKDSAPublicKey((DSAPublicKeySpec)keySpec);
417                }
418    
419                throw new InvalidKeySpecException("Unknown KeySpec type.");
420            }
421        }
422    
423    
424        public static class EC
425            extends JDKKeyFactory
426        {
427            String  algorithm;
428    
429            public EC()
430            {
431                this("EC");
432            }
433    
434            public EC(
435                String  algorithm)
436            {
437                this.algorithm = algorithm;
438            }
439    
440            protected PrivateKey engineGeneratePrivate(
441                KeySpec    keySpec)
442                throws InvalidKeySpecException
443            {
444                if (keySpec instanceof PKCS8EncodedKeySpec)
445                {
446                    try
447                    {
448                        return JDKKeyFactory.createPrivateKeyFromDERStream(
449                                    new ByteArrayInputStream(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
450                    }
451                    catch (Exception e)
452                    {
453                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
454                    }
455                }
456    
457                throw new InvalidKeySpecException("Unknown KeySpec type.");
458            }
459    
460            protected PublicKey engineGeneratePublic(
461                KeySpec    keySpec)
462                throws InvalidKeySpecException
463            {
464                if (keySpec instanceof X509EncodedKeySpec)
465                {
466                    try
467                    {
468                        return JDKKeyFactory.createPublicKeyFromDERStream(
469                                    new ByteArrayInputStream(((X509EncodedKeySpec)keySpec).getEncoded()));
470                    }
471                    catch (Exception e)
472                    {
473                        throw (InvalidKeySpecException)new InvalidKeySpecException(e.getMessage()).initCause(e);
474                    }
475                }
476    
477                throw new InvalidKeySpecException("Unknown KeySpec type.");
478            }
479        }
480    }