1 package org.bouncycastle.jcajce.provider.asymmetric.rsa;
2 
3 import java.io.IOException;
4 import java.security.InvalidKeyException;
5 import java.security.Key;
6 import java.security.PrivateKey;
7 import java.security.PublicKey;
8 import java.security.interfaces.RSAPrivateCrtKey;
9 import java.security.interfaces.RSAPublicKey;
10 import java.security.spec.InvalidKeySpecException;
11 import java.security.spec.KeySpec;
12 import java.security.spec.PKCS8EncodedKeySpec;
13 import java.security.spec.RSAPrivateCrtKeySpec;
14 import java.security.spec.RSAPrivateKeySpec;
15 import java.security.spec.RSAPublicKeySpec;
16 
17 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
18 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
19 import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
20 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
21 import org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi;
22 import org.bouncycastle.jcajce.provider.asymmetric.util.ExtendedInvalidKeySpecException;
23 
24 public class KeyFactorySpi
25     extends BaseKeyFactorySpi
26 {
KeyFactorySpi()27     public KeyFactorySpi()
28     {
29     }
30 
engineGetKeySpec( Key key, Class spec)31     protected KeySpec engineGetKeySpec(
32         Key key,
33         Class spec)
34         throws InvalidKeySpecException
35     {
36         if (spec.isAssignableFrom(RSAPublicKeySpec.class) && key instanceof RSAPublicKey)
37         {
38             RSAPublicKey k = (RSAPublicKey)key;
39 
40             return new RSAPublicKeySpec(k.getModulus(), k.getPublicExponent());
41         }
42         else if (spec.isAssignableFrom(RSAPrivateKeySpec.class) && key instanceof java.security.interfaces.RSAPrivateKey)
43         {
44             java.security.interfaces.RSAPrivateKey k = (java.security.interfaces.RSAPrivateKey)key;
45 
46             return new RSAPrivateKeySpec(k.getModulus(), k.getPrivateExponent());
47         }
48         else if (spec.isAssignableFrom(RSAPrivateCrtKeySpec.class) && key instanceof RSAPrivateCrtKey)
49         {
50             RSAPrivateCrtKey k = (RSAPrivateCrtKey)key;
51 
52             return new RSAPrivateCrtKeySpec(
53                 k.getModulus(), k.getPublicExponent(),
54                 k.getPrivateExponent(),
55                 k.getPrimeP(), k.getPrimeQ(),
56                 k.getPrimeExponentP(), k.getPrimeExponentQ(),
57                 k.getCrtCoefficient());
58         }
59 
60         return super.engineGetKeySpec(key, spec);
61     }
62 
engineTranslateKey( Key key)63     protected Key engineTranslateKey(
64         Key key)
65         throws InvalidKeyException
66     {
67         if (key instanceof RSAPublicKey)
68         {
69             return new BCRSAPublicKey((RSAPublicKey)key);
70         }
71         else if (key instanceof RSAPrivateCrtKey)
72         {
73             return new BCRSAPrivateCrtKey((RSAPrivateCrtKey)key);
74         }
75         else if (key instanceof java.security.interfaces.RSAPrivateKey)
76         {
77             return new BCRSAPrivateKey((java.security.interfaces.RSAPrivateKey)key);
78         }
79 
80         throw new InvalidKeyException("key type unknown");
81     }
82 
engineGeneratePrivate( KeySpec keySpec)83     protected PrivateKey engineGeneratePrivate(
84         KeySpec keySpec)
85         throws InvalidKeySpecException
86     {
87         if (keySpec instanceof PKCS8EncodedKeySpec)
88         {
89             try
90             {
91                 return generatePrivate(PrivateKeyInfo.getInstance(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
92             }
93             catch (Exception e)
94             {
95                 //
96                 // in case it's just a RSAPrivateKey object... -- openSSL produces these
97                 //
98                 try
99                 {
100                     return new BCRSAPrivateCrtKey(
101                         RSAPrivateKey.getInstance(((PKCS8EncodedKeySpec)keySpec).getEncoded()));
102                 }
103                 catch (Exception ex)
104                 {
105                     throw new ExtendedInvalidKeySpecException("unable to process key spec: " + e.toString(), e);
106                 }
107             }
108         }
109         else if (keySpec instanceof RSAPrivateCrtKeySpec)
110         {
111             return new BCRSAPrivateCrtKey((RSAPrivateCrtKeySpec)keySpec);
112         }
113         else if (keySpec instanceof RSAPrivateKeySpec)
114         {
115             return new BCRSAPrivateKey((RSAPrivateKeySpec)keySpec);
116         }
117 
118         throw new InvalidKeySpecException("Unknown KeySpec type: " + keySpec.getClass().getName());
119     }
120 
engineGeneratePublic( KeySpec keySpec)121     protected PublicKey engineGeneratePublic(
122         KeySpec keySpec)
123         throws InvalidKeySpecException
124     {
125         if (keySpec instanceof RSAPublicKeySpec)
126         {
127             return new BCRSAPublicKey((RSAPublicKeySpec)keySpec);
128         }
129 
130         return super.engineGeneratePublic(keySpec);
131     }
132 
generatePrivate(PrivateKeyInfo keyInfo)133     public PrivateKey generatePrivate(PrivateKeyInfo keyInfo)
134         throws IOException
135     {
136         ASN1ObjectIdentifier algOid = keyInfo.getPrivateKeyAlgorithm().getAlgorithm();
137 
138         if (RSAUtil.isRsaOid(algOid))
139         {
140             RSAPrivateKey rsaPrivKey = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
141 
142             if (rsaPrivKey.getCoefficient().intValue() == 0)
143             {
144                 return new BCRSAPrivateKey(rsaPrivKey);
145             }
146             else
147             {
148                 return new BCRSAPrivateCrtKey(keyInfo);
149             }
150         }
151         else
152         {
153             throw new IOException("algorithm identifier " + algOid + " in key not recognised");
154         }
155     }
156 
generatePublic(SubjectPublicKeyInfo keyInfo)157     public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo)
158         throws IOException
159     {
160         ASN1ObjectIdentifier algOid = keyInfo.getAlgorithm().getAlgorithm();
161 
162         if (RSAUtil.isRsaOid(algOid))
163         {
164             return new BCRSAPublicKey(keyInfo);
165         }
166         else
167         {
168             throw new IOException("algorithm identifier " + algOid + " in key not recognised");
169         }
170     }
171 }
172