1 /* EncodedKeyFactory.java -- encoded key factory.
2    Copyright (C) 2004  Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
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)
9 any later version.
10 
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.
15 
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
19 02110-1301 USA.
20 
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
24 combination.
25 
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. */
37 
38 
39 package gnu.java.security.provider;
40 
41 import gnu.java.security.OID;
42 import gnu.java.security.der.BitString;
43 import gnu.java.security.der.DERReader;
44 import gnu.java.security.der.DERValue;
45 
46 import java.io.IOException;
47 import java.math.BigInteger;
48 import java.security.AlgorithmParameters;
49 import java.security.InvalidKeyException;
50 import java.security.Key;
51 import java.security.KeyFactorySpi;
52 import java.security.NoSuchAlgorithmException;
53 import java.security.PrivateKey;
54 import java.security.PublicKey;
55 import java.security.spec.DSAParameterSpec;
56 import java.security.spec.InvalidKeySpecException;
57 import java.security.spec.InvalidParameterSpecException;
58 import java.security.spec.KeySpec;
59 import java.security.spec.PKCS8EncodedKeySpec;
60 import java.security.spec.RSAPrivateCrtKeySpec;
61 import java.security.spec.RSAPublicKeySpec;
62 import java.security.spec.X509EncodedKeySpec;
63 
64 import javax.crypto.spec.DHParameterSpec;
65 
66 /**
67  * A factory for keys encoded in either the X.509 format (for public
68  * keys) or the PKCS#8 format (for private keys).
69  *
70  * @author Casey Marshall (rsdio@metastatic.org)
71  */
72 public class EncodedKeyFactory extends KeyFactorySpi
73 {
74 
75   // Constants.
76   // ------------------------------------------------------------------------
77 
78   private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
79   private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
80   private static final OID ID_DH  = new OID("1.2.840.10046.2.1");
81 
82   // Instance methods.
83   // ------------------------------------------------------------------------
84 
engineGeneratePublic(KeySpec spec)85   public PublicKey engineGeneratePublic(KeySpec spec)
86     throws InvalidKeySpecException
87   {
88     if (!(spec instanceof X509EncodedKeySpec))
89       throw new InvalidKeySpecException("only supports X.509 key specs");
90     DERReader der = new DERReader(((X509EncodedKeySpec) spec).getEncoded());
91     try
92       {
93         DERValue spki = der.read();
94         if (!spki.isConstructed())
95           {
96             throw new InvalidKeySpecException("malformed encoded key");
97           }
98         DERValue alg = der.read();
99         if (!alg.isConstructed())
100           {
101             throw new InvalidKeySpecException("malformed encoded key");
102           }
103         DERValue val = der.read();
104         if (!(val.getValue() instanceof OID))
105           {
106             throw new InvalidKeySpecException("malformed encoded key");
107           }
108         OID algId = (OID) val.getValue();
109         byte[] algParams = null;
110         if (alg.getLength() > val.getEncodedLength())
111           {
112             val = der.read();
113             algParams = val.getEncoded();
114             if (val.isConstructed())
115               der.skip(val.getLength());
116           }
117         val = der.read();
118         if (!(val.getValue() instanceof BitString))
119           {
120             throw new InvalidKeySpecException("malformed encoded key");
121           }
122         byte[] publicKey = ((BitString) val.getValue()).toByteArray();
123         if (algId.equals(ID_DSA))
124           {
125             BigInteger p = null, g = null, q = null, Y;
126             if (algParams != null)
127               {
128                 DERReader dsaParams = new DERReader(algParams);
129                 val = dsaParams.read();
130                 if (!val.isConstructed())
131                   throw new InvalidKeySpecException("malformed DSA parameters");
132                 val = dsaParams.read();
133                 if (!(val.getValue() instanceof BigInteger))
134                   throw new InvalidKeySpecException("malformed DSA parameters");
135                 p = (BigInteger) val.getValue();
136                 val = dsaParams.read();
137                 if (!(val.getValue() instanceof BigInteger))
138                   throw new InvalidKeySpecException("malformed DSA parameters");
139                 q = (BigInteger) val.getValue();
140                 val = dsaParams.read();
141                 if (!(val.getValue() instanceof BigInteger))
142                   throw new InvalidKeySpecException("malformed DSA parameters");
143                 g = (BigInteger) val.getValue();
144               }
145             DERReader dsaPub = new DERReader(publicKey);
146             val = dsaPub.read();
147             if (!(val.getValue() instanceof BigInteger))
148               throw new InvalidKeySpecException("malformed DSA parameters");
149             Y = (BigInteger) val.getValue();
150             return new GnuDSAPublicKey(Y, p, q, g);
151           }
152         else if (algId.equals(ID_RSA))
153           {
154             DERReader rsaParams = new DERReader(publicKey);
155             if (!rsaParams.read().isConstructed())
156               {
157                 throw new InvalidKeySpecException("malformed encoded key");
158               }
159             return new GnuRSAPublicKey(new RSAPublicKeySpec(
160               (BigInteger) rsaParams.read().getValue(),
161               (BigInteger) rsaParams.read().getValue()));
162           }
163         else if (algId.equals(ID_DH))
164           {
165             if (algParams == null)
166               throw new InvalidKeySpecException("missing DH parameters");
167             DERReader dhParams = new DERReader(algParams);
168             val = dhParams.read();
169             BigInteger p, g, q, Y;
170             if (!val.isConstructed())
171               throw new InvalidKeySpecException("malformed DH parameters");
172             val = dhParams.read();
173             if (!(val.getValue() instanceof BigInteger))
174               throw new InvalidKeySpecException("malformed DH parameters");
175             p = (BigInteger) val.getValue();
176             val = dhParams.read();
177             if (!(val.getValue() instanceof BigInteger))
178               throw new InvalidKeySpecException("malformed DH parameters");
179             g = (BigInteger) val.getValue();
180             val = dhParams.read();
181             if (!(val.getValue() instanceof BigInteger))
182               throw new InvalidKeySpecException("malformed DH parameters");
183             q = (BigInteger) val.getValue();
184             DERReader dhPub = new DERReader(publicKey);
185             val = dhPub.read();
186             if (!(val.getValue() instanceof BigInteger))
187               throw new InvalidKeySpecException("malformed DH parameters");
188             Y = (BigInteger) val.getValue();
189             return (PublicKey) new GnuDHPublicKey(new DHParameterSpec(p, g), Y, q);
190           }
191         else
192           throw new InvalidKeySpecException("unknown algorithm: " + algId);
193       }
194     catch (IOException ioe)
195       {
196         throw new InvalidKeySpecException(ioe.getMessage());
197       }
198   }
199 
engineGeneratePrivate(KeySpec spec)200   public PrivateKey engineGeneratePrivate(KeySpec spec)
201     throws InvalidKeySpecException
202   {
203     if (!(spec instanceof PKCS8EncodedKeySpec))
204       {
205         throw new InvalidKeySpecException("only supports PKCS8 key specs");
206       }
207     DERReader der = new DERReader(((PKCS8EncodedKeySpec) spec).getEncoded());
208     try
209       {
210         DERValue pki = der.read();
211         if (!pki.isConstructed())
212           {
213             throw new InvalidKeySpecException("malformed encoded key");
214           }
215         DERValue val = der.read();
216         if (!(val.getValue() instanceof BigInteger))
217           {
218             throw new InvalidKeySpecException("malformed encoded key");
219           }
220         DERValue alg = der.read();
221         if (!alg.isConstructed())
222           {
223             throw new InvalidKeySpecException("malformed encoded key");
224           }
225         val = der.read();
226         if (!(val.getValue() instanceof OID))
227           {
228             throw new InvalidKeySpecException("malformed encoded key");
229           }
230         OID algId = (OID) val.getValue();
231         byte[] algParams = null;
232         if (alg.getLength() > val.getEncodedLength())
233           {
234             val = der.read();
235             algParams = val.getEncoded();
236             if (val.isConstructed())
237               der.skip(val.getLength());
238           }
239         byte[] privateKey = (byte[]) der.read().getValue();
240         if (algId.equals(ID_DSA))
241           {
242             if (algParams == null)
243               {
244                 throw new InvalidKeySpecException("missing DSA parameters");
245               }
246             AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");
247             params.init(algParams);
248             DSAParameterSpec dsaSpec = (DSAParameterSpec)
249               params.getParameterSpec(DSAParameterSpec.class);
250             DERReader dsaPriv = new DERReader(privateKey);
251             return new GnuDSAPrivateKey((BigInteger) dsaPriv.read().getValue(),
252               dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG());
253           }
254         else if (algId.equals(ID_RSA))
255           {
256             DERReader rsaParams = new DERReader(privateKey);
257             if (!rsaParams.read().isConstructed())
258               throw new InvalidKeySpecException("malformed encoded key");
259             return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
260               (BigInteger) rsaParams.read().getValue(), // n
261               (BigInteger) rsaParams.read().getValue(), // e
262               (BigInteger) rsaParams.read().getValue(), // d
263               (BigInteger) rsaParams.read().getValue(), // p
264               (BigInteger) rsaParams.read().getValue(), // q
265               (BigInteger) rsaParams.read().getValue(), // d mod (p - 1)
266               (BigInteger) rsaParams.read().getValue(), // d mod (q - 1)
267               (BigInteger) rsaParams.read().getValue())); // (inv q) mod p
268           }
269         else
270           throw new InvalidKeySpecException("unknown algorithm: " + algId);
271       }
272     catch (InvalidParameterSpecException iapse)
273       {
274         throw new InvalidKeySpecException(iapse.getMessage());
275       }
276     catch (NoSuchAlgorithmException nsae)
277       {
278         throw new InvalidKeySpecException(nsae.getMessage());
279       }
280     catch (IOException ioe)
281       {
282         throw new InvalidKeySpecException(ioe.getMessage());
283       }
284   }
285 
engineGetKeySpec(Key key, Class speClass)286   public KeySpec engineGetKeySpec(Key key, Class speClass)
287     throws InvalidKeySpecException
288   {
289     if ((key instanceof PrivateKey) && key.getFormat().equals("PKCS#8")
290         && speClass.isAssignableFrom(PKCS8EncodedKeySpec.class))
291       return new PKCS8EncodedKeySpec(key.getEncoded());
292     else if ((key instanceof PublicKey) && key.getFormat().equals("X.509")
293         && speClass.isAssignableFrom(X509EncodedKeySpec.class))
294       return new X509EncodedKeySpec(key.getEncoded());
295     else
296       throw new InvalidKeySpecException();
297   }
298 
engineTranslateKey(Key key)299   public Key engineTranslateKey(Key key) throws InvalidKeyException
300   {
301     throw new InvalidKeyException("translating keys not supported");
302   }
303 }
304