1package org.bouncycastle.jce.provider;
2
3import java.io.IOException;
4import java.security.InvalidKeyException;
5import java.security.Key;
6import java.security.KeyFactorySpi;
7import java.security.PrivateKey;
8import java.security.PublicKey;
9import java.security.interfaces.DSAPrivateKey;
10import java.security.interfaces.DSAPublicKey;
11import java.security.interfaces.RSAPrivateCrtKey;
12import java.security.interfaces.RSAPrivateKey;
13import java.security.interfaces.RSAPublicKey;
14import java.security.spec.DSAPrivateKeySpec;
15import java.security.spec.DSAPublicKeySpec;
16import java.security.spec.InvalidKeySpecException;
17import java.security.spec.KeySpec;
18import java.security.spec.PKCS8EncodedKeySpec;
19import java.security.spec.RSAPrivateCrtKeySpec;
20import java.security.spec.RSAPrivateKeySpec;
21import java.security.spec.RSAPublicKeySpec;
22import java.security.spec.X509EncodedKeySpec;
23
24import javax.crypto.interfaces.DHPrivateKey;
25import javax.crypto.interfaces.DHPublicKey;
26import javax.crypto.spec.DHPrivateKeySpec;
27import javax.crypto.spec.DHPublicKeySpec;
28
29import org.bouncycastle.asn1.ASN1Object;
30import org.bouncycastle.asn1.ASN1Sequence;
31import org.bouncycastle.asn1.DERObjectIdentifier;
32import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
33import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
34import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
35import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
36import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
37import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
38import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
39// BEGIN android-removed
40// import org.bouncycastle.jce.interfaces.ElGamalPrivateKey;
41// import org.bouncycastle.jce.interfaces.ElGamalPublicKey;
42// import org.bouncycastle.jce.spec.ElGamalPrivateKeySpec;
43// import org.bouncycastle.jce.spec.ElGamalPublicKeySpec;
44// import org.bouncycastle.jce.spec.GOST3410PrivateKeySpec;
45// import org.bouncycastle.jce.spec.GOST3410PublicKeySpec;
46// END android-removed
47
48public abstract class JDKKeyFactory
49    extends KeyFactorySpi
50{
51    // BEGIN android-removed
52    // protected boolean elGamalFactory = false;
53    // END android-removed
54
55    public JDKKeyFactory()
56    {
57    }
58
59    protected PrivateKey engineGeneratePrivate(
60        KeySpec keySpec)
61        throws InvalidKeySpecException
62    {
63        if (keySpec instanceof PKCS8EncodedKeySpec)
64        {
65            try
66            {
67                return JDKKeyFactory.createPrivateKeyFromDERStream(
68                    ((PKCS8EncodedKeySpec)keySpec).getEncoded());
69            }
70            catch (Exception e)
71            {
72                throw new InvalidKeySpecException(e.toString());
73            }
74        }
75
76        throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
77    }
78
79    protected PublicKey engineGeneratePublic(
80        KeySpec    keySpec)
81        throws InvalidKeySpecException
82    {
83        if (keySpec instanceof X509EncodedKeySpec)
84        {
85            try
86            {
87                return JDKKeyFactory.createPublicKeyFromDERStream(
88                    ((X509EncodedKeySpec)keySpec).getEncoded());
89            }
90            catch (Exception e)
91            {
92                throw new InvalidKeySpecException(e.toString());
93            }
94        }
95
96        throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
97    }
98
99    protected KeySpec engineGetKeySpec(
100        Key    key,
101        Class    spec)
102    throws InvalidKeySpecException
103    {
104       if (spec.isAssignableFrom(PKCS8EncodedKeySpec.class) && key.getFormat().equals("PKCS#8"))
105       {
106               return new PKCS8EncodedKeySpec(key.getEncoded());
107       }
108       else if (spec.isAssignableFrom(X509EncodedKeySpec.class) && key.getFormat().equals("X.509"))
109       {
110               return new X509EncodedKeySpec(key.getEncoded());
111       }
112       else if (spec.isAssignableFrom(RSAPublicKeySpec.class) && key instanceof RSAPublicKey)
113       {
114            RSAPublicKey    k = (RSAPublicKey)key;
115
116            return new RSAPublicKeySpec(k.getModulus(), k.getPublicExponent());
117       }
118       else if (spec.isAssignableFrom(RSAPrivateKeySpec.class) && key instanceof RSAPrivateKey)
119       {
120            RSAPrivateKey    k = (RSAPrivateKey)key;
121
122            return new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent());
123       }
124       else if (spec.isAssignableFrom(RSAPrivateCrtKeySpec.class) && key instanceof RSAPrivateCrtKey)
125       {
126            RSAPrivateCrtKey    k = (RSAPrivateCrtKey)key;
127
128            return new RSAPrivateCrtKeySpec(
129                            k.getModulus(), k.getPublicExponent(),
130                            k.getPrivateExponent(),
131                            k.getPrimeP(), k.getPrimeQ(),
132                            k.getPrimeExponentP(), k.getPrimeExponentQ(),
133                            k.getCrtCoefficient());
134       }
135       else if (spec.isAssignableFrom(DHPrivateKeySpec.class) && key instanceof DHPrivateKey)
136       {
137           DHPrivateKey k = (DHPrivateKey)key;
138
139           return new DHPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getG());
140       }
141       else if (spec.isAssignableFrom(DHPublicKeySpec.class) && key instanceof DHPublicKey)
142       {
143           DHPublicKey k = (DHPublicKey)key;
144
145           return new DHPublicKeySpec(k.getY(), k.getParams().getP(), k.getParams().getG());
146       }
147       // BEGIN android-added
148       else if (spec.isAssignableFrom(DSAPublicKeySpec.class) && key instanceof DSAPublicKey)
149       {
150            DSAPublicKey    k = (DSAPublicKey)key;
151
152            return new DSAPublicKeySpec(k.getY(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG());
153       }
154       else if (spec.isAssignableFrom(DSAPrivateKeySpec.class) && key instanceof DSAPrivateKey)
155       {
156            DSAPrivateKey    k = (DSAPrivateKey)key;
157
158            return new DSAPrivateKeySpec(k.getX(), k.getParams().getP(), k.getParams().getQ(), k.getParams().getG());
159       }
160       // END android-added
161
162       throw new RuntimeException("not implemented yet " + key + " " + spec);
163    }
164
165    protected Key engineTranslateKey(
166        Key    key)
167        throws InvalidKeyException
168    {
169        if (key instanceof RSAPublicKey)
170        {
171            return new JCERSAPublicKey((RSAPublicKey)key);
172        }
173        else if (key instanceof RSAPrivateCrtKey)
174        {
175            return new JCERSAPrivateCrtKey((RSAPrivateCrtKey)key);
176        }
177        else if (key instanceof RSAPrivateKey)
178        {
179            return new JCERSAPrivateKey((RSAPrivateKey)key);
180        }
181        else if (key instanceof DHPublicKey)
182        {
183            // BEGIN android-removed
184            // if (elGamalFactory)
185            // {
186            //     return new JCEElGamalPublicKey((DHPublicKey)key);
187            // }
188            // else
189            // {
190            // END android-removed
191                return new JCEDHPublicKey((DHPublicKey)key);
192            // BEGIN android-removed
193            // }
194            // END android-removed
195        }
196        else if (key instanceof DHPrivateKey)
197        {
198            // BEGIN android-removed
199            // if (elGamalFactory)
200            // {
201            //     return new JCEElGamalPrivateKey((DHPrivateKey)key);
202            // }
203            // else
204            // {
205            // END android-removed
206                return new JCEDHPrivateKey((DHPrivateKey)key);
207            // BEGIN android-removed
208            // }
209            // END android-removed
210        }
211        else if (key instanceof DSAPublicKey)
212        {
213            return new JDKDSAPublicKey((DSAPublicKey)key);
214        }
215        else if (key instanceof DSAPrivateKey)
216        {
217            return new JDKDSAPrivateKey((DSAPrivateKey)key);
218        }
219        // BEGIN android-removed
220        // else if (key instanceof ElGamalPublicKey)
221        // {
222        //     return new JCEElGamalPublicKey((ElGamalPublicKey)key);
223        // }
224        // else if (key instanceof ElGamalPrivateKey)
225        // {
226        //    return new JCEElGamalPrivateKey((ElGamalPrivateKey)key);
227        // }
228        // END android-removed
229
230        throw new InvalidKeyException("key type unknown");
231    }
232
233    /**
234     * create a public key from the given DER encoded input stream.
235     */
236    public static PublicKey createPublicKeyFromDERStream(
237        byte[]         in)
238        throws IOException
239    {
240        return createPublicKeyFromPublicKeyInfo(
241            new SubjectPublicKeyInfo((ASN1Sequence) ASN1Object.fromByteArray(in)));
242    }
243
244    /**
245     * create a public key from the given public key info object.
246     */
247    static PublicKey createPublicKeyFromPublicKeyInfo(
248        SubjectPublicKeyInfo         info)
249    {
250        DERObjectIdentifier     algOid = info.getAlgorithmId().getObjectId();
251
252        if (RSAUtil.isRsaOid(algOid))
253        {
254            return new JCERSAPublicKey(info);
255        }
256        else if (algOid.equals(PKCSObjectIdentifiers.dhKeyAgreement))
257        {
258            return new JCEDHPublicKey(info);
259        }
260        else if (algOid.equals(X9ObjectIdentifiers.dhpublicnumber))
261        {
262            return new JCEDHPublicKey(info);
263        }
264        // BEGIN android-removed
265        // else if (algOid.equals(OIWObjectIdentifiers.elGamalAlgorithm))
266        // {
267        //     return new JCEElGamalPublicKey(info);
268        // }
269        // END android-removed
270        else if (algOid.equals(X9ObjectIdentifiers.id_dsa))
271        {
272            return new JDKDSAPublicKey(info);
273        }
274        else if (algOid.equals(OIWObjectIdentifiers.dsaWithSHA1))
275        {
276            return new JDKDSAPublicKey(info);
277        }
278        else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey))
279        {
280            return new JCEECPublicKey(info);
281        }
282        // BEGIN android-removed
283        // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94))
284        // {
285        //     return new JDKGOST3410PublicKey(info);
286        // }
287        // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_2001))
288        // {
289        //     return new JCEECPublicKey(info);
290        // }
291        else
292        {
293            throw new RuntimeException("algorithm identifier " + algOid + " in key not recognised");
294        }
295    }
296
297    /**
298     * create a private key from the given DER encoded input stream.
299     */
300    protected static PrivateKey createPrivateKeyFromDERStream(
301        byte[]         in)
302        throws IOException
303    {
304        return createPrivateKeyFromPrivateKeyInfo(
305            new PrivateKeyInfo((ASN1Sequence) ASN1Object.fromByteArray(in)));
306    }
307
308    /**
309     * create a private key from the given public key info object.
310     */
311    static PrivateKey createPrivateKeyFromPrivateKeyInfo(
312        PrivateKeyInfo      info)
313    {
314        DERObjectIdentifier     algOid = info.getAlgorithmId().getObjectId();
315
316        if (RSAUtil.isRsaOid(algOid))
317        {
318              return new JCERSAPrivateCrtKey(info);
319        }
320        else if (algOid.equals(PKCSObjectIdentifiers.dhKeyAgreement))
321        {
322              return new JCEDHPrivateKey(info);
323        }
324        else if (algOid.equals(X9ObjectIdentifiers.dhpublicnumber))
325        {
326              return new JCEDHPrivateKey(info);
327        }
328        // BEGIN android-removed
329        // else if (algOid.equals(OIWObjectIdentifiers.elGamalAlgorithm))
330        // {
331        //       return new JCEElGamalPrivateKey(info);
332        // }
333        // END android-removed
334        else if (algOid.equals(X9ObjectIdentifiers.id_dsa))
335        {
336              return new JDKDSAPrivateKey(info);
337        }
338        else if (algOid.equals(X9ObjectIdentifiers.id_ecPublicKey))
339        {
340              return new JCEECPrivateKey(info);
341        }
342        // BEGIN android-removed
343        // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_94))
344        // {
345        //       return new JDKGOST3410PrivateKey(info);
346        // }
347        // else if (algOid.equals(CryptoProObjectIdentifiers.gostR3410_2001))
348        // {
349        //       return new JCEECPrivateKey(info);
350        // }
351        // END android-removed
352        else
353        {
354            throw new RuntimeException("algorithm identifier " + algOid + " in key not recognised");
355        }
356    }
357
358    public static class RSA
359        extends JDKKeyFactory
360    {
361        public RSA()
362        {
363        }
364
365        protected PrivateKey engineGeneratePrivate(
366            KeySpec    keySpec)
367            throws InvalidKeySpecException
368        {
369            if (keySpec instanceof PKCS8EncodedKeySpec)
370            {
371                try
372                {
373                    return JDKKeyFactory.createPrivateKeyFromDERStream(
374                                ((PKCS8EncodedKeySpec)keySpec).getEncoded());
375                }
376                catch (Exception e)
377                {
378                    //
379                    // in case it's just a RSAPrivateKey object...
380                    //
381                    try
382                    {
383                        return new JCERSAPrivateCrtKey(
384                            new RSAPrivateKeyStructure(
385                                (ASN1Sequence) ASN1Object.fromByteArray(((PKCS8EncodedKeySpec)keySpec).getEncoded())));
386                    }
387                    catch (Exception ex)
388                    {
389                        throw new InvalidKeySpecException(ex.toString());
390                    }
391                }
392            }
393            else if (keySpec instanceof RSAPrivateCrtKeySpec)
394            {
395                return new JCERSAPrivateCrtKey((RSAPrivateCrtKeySpec)keySpec);
396            }
397            else if (keySpec instanceof RSAPrivateKeySpec)
398            {
399                return new JCERSAPrivateKey((RSAPrivateKeySpec)keySpec);
400            }
401
402            throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
403        }
404
405        protected PublicKey engineGeneratePublic(
406            KeySpec    keySpec)
407            throws InvalidKeySpecException
408        {
409            if (keySpec instanceof RSAPublicKeySpec)
410            {
411                return new JCERSAPublicKey((RSAPublicKeySpec)keySpec);
412            }
413
414            return super.engineGeneratePublic(keySpec);
415        }
416    }
417
418    public static class DH
419        extends JDKKeyFactory
420    {
421        public DH()
422        {
423        }
424
425        protected PrivateKey engineGeneratePrivate(
426            KeySpec    keySpec)
427            throws InvalidKeySpecException
428        {
429            if (keySpec instanceof DHPrivateKeySpec)
430            {
431                return new JCEDHPrivateKey((DHPrivateKeySpec)keySpec);
432            }
433
434            return super.engineGeneratePrivate(keySpec);
435        }
436
437        protected PublicKey engineGeneratePublic(
438            KeySpec    keySpec)
439            throws InvalidKeySpecException
440        {
441            if (keySpec instanceof DHPublicKeySpec)
442            {
443                return new JCEDHPublicKey((DHPublicKeySpec)keySpec);
444            }
445
446            return super.engineGeneratePublic(keySpec);
447        }
448    }
449
450    public static class DSA
451        extends JDKKeyFactory
452    {
453        public DSA()
454        {
455        }
456
457        protected PrivateKey engineGeneratePrivate(
458            KeySpec    keySpec)
459            throws InvalidKeySpecException
460        {
461            if (keySpec instanceof DSAPrivateKeySpec)
462            {
463                return new JDKDSAPrivateKey((DSAPrivateKeySpec)keySpec);
464            }
465
466            return super.engineGeneratePrivate(keySpec);
467        }
468
469        protected PublicKey engineGeneratePublic(
470            KeySpec    keySpec)
471            throws InvalidKeySpecException
472        {
473            if (keySpec instanceof DSAPublicKeySpec)
474            {
475                return new JDKDSAPublicKey((DSAPublicKeySpec)keySpec);
476            }
477
478            return super.engineGeneratePublic(keySpec);
479        }
480    }
481
482    // BEGIN android-removed
483    // public static class GOST3410
484    //     extends JDKKeyFactory
485    // {
486    //     public GOST3410()
487    //     {
488    //     }
489    //
490    //     protected PrivateKey engineGeneratePrivate(
491    //             KeySpec    keySpec)
492    //     throws InvalidKeySpecException
493    //     {
494    //         if (keySpec instanceof GOST3410PrivateKeySpec)
495    //         {
496    //             return new JDKGOST3410PrivateKey((GOST3410PrivateKeySpec)keySpec);
497    //         }
498    //
499    //         return super.engineGeneratePrivate(keySpec);
500    //     }
501    //
502    //     protected PublicKey engineGeneratePublic(
503    //             KeySpec    keySpec)
504    //     throws InvalidKeySpecException
505    //     {
506    //         if (keySpec instanceof GOST3410PublicKeySpec)
507    //         {
508    //             return new JDKGOST3410PublicKey((GOST3410PublicKeySpec)keySpec);
509    //         }
510    //
511    //         return super.engineGeneratePublic(keySpec);
512    //     }
513    // }
514
515    // public static class ElGamal
516    //     extends JDKKeyFactory
517    // {
518    //     public ElGamal()
519    //     {
520    //         elGamalFactory = true;
521    //     }
522    //
523    //     protected PrivateKey engineGeneratePrivate(
524    //         KeySpec    keySpec)
525    //         throws InvalidKeySpecException
526    //     {
527    //         if (keySpec instanceof ElGamalPrivateKeySpec)
528    //         {
529    //             return new JCEElGamalPrivateKey((ElGamalPrivateKeySpec)keySpec);
530    //         }
531    //         else if (keySpec instanceof DHPrivateKeySpec)
532    //         {
533    //             return new JCEElGamalPrivateKey((DHPrivateKeySpec)keySpec);
534    //         }
535    //
536    //         return super.engineGeneratePrivate(keySpec);
537    //     }
538    //
539    //     protected PublicKey engineGeneratePublic(
540    //         KeySpec    keySpec)
541    //         throws InvalidKeySpecException
542    //     {
543    //         if (keySpec instanceof ElGamalPublicKeySpec)
544    //         {
545    //             return new JCEElGamalPublicKey((ElGamalPublicKeySpec)keySpec);
546    //         }
547    //         else if (keySpec instanceof DHPublicKeySpec)
548    //         {
549    //             return new JCEElGamalPublicKey((DHPublicKeySpec)keySpec);
550    //         }
551    //
552    //         return super.engineGeneratePublic(keySpec);
553    //     }
554    // }
555    //
556    //
557    //
558    // /**
559    //  * This isn't really correct, however the class path project API seems to think such
560    //  * a key factory will exist.
561    //  */
562    // public static class X509
563    //     extends JDKKeyFactory
564    // {
565    //     public X509()
566    //     {
567    //     }
568    // }
569    // END android-removed
570}
571