001    /* KeyStore.java --- Key Store Class
002       Copyright (C) 1999, 2002, 2003, 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.security;
040    
041    import gnu.java.security.Engine;
042    
043    import java.io.IOException;
044    import java.io.InputStream;
045    import java.io.OutputStream;
046    import java.lang.reflect.InvocationTargetException;
047    import java.security.cert.CertificateException;
048    import java.util.Date;
049    import java.util.Enumeration;
050    
051    /**
052     * Keystore represents an in-memory collection of keys and
053     * certificates. There are two types of entries:
054     *
055     * <dl>
056     * <dt>Key Entry</dt>
057     *
058     * <dd><p>This type of keystore entry store sensitive crytographic key
059     * information in a protected format.Typically this is a secret
060     * key or a private key with a certificate chain.</p></dd>
061     *
062     * <dt>Trusted Ceritificate Entry</dt>
063     *
064     * <dd><p>This type of keystore entry contains a single public key
065     * certificate belonging to annother entity. It is called trusted
066     * because the keystore owner trusts that the certificates
067     * belongs to the subject (owner) of the certificate.</p></dd>
068     * </dl>
069     *
070     * <p>Entries in a key store are referred to by their "alias": a simple
071     * unique string.
072     *
073     * <p>The structure and persistentence of the key store is not
074     * specified. Any method could be used to protect sensitive
075     * (private or secret) keys. Smart cards or integrated
076     * cryptographic engines could be used or the keystore could
077     * be simply stored in a file.</p>
078     *
079     * @see java.security.cert.Certificate
080     * @see Key
081     */
082    public class KeyStore
083    {
084    
085      // Constants and fields.
086      // ------------------------------------------------------------------------
087    
088      /** Service name for key stores. */
089      private static final String KEY_STORE = "KeyStore";
090    
091      private KeyStoreSpi keyStoreSpi;
092      private Provider provider;
093      private String type;
094    
095      // Constructors.
096      // ------------------------------------------------------------------------
097    
098      /**
099         Creates an instance of KeyStore
100    
101         @param keyStoreSpi A KeyStore engine to use
102         @param provider A provider to use
103         @param type The type of KeyStore
104       */
105      protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
106      {
107        this.keyStoreSpi = keyStoreSpi;
108        this.provider = provider;
109        this.type = type;
110      }
111    
112      /**
113       * Returns an instance of a <code>KeyStore</code> representing the specified
114       * type, from the first provider that implements it.
115       *
116       * @param type the type of keystore to create.
117       * @return a <code>KeyStore</code> repesenting the desired type.
118       * @throws KeyStoreException if the designated type of is not implemented by
119       *           any provider, or the implementation could not be instantiated.
120       * @throws IllegalArgumentException if <code>type</code> is
121       *           <code>null</code> or is an empty string.
122       */
123      public static KeyStore getInstance(String type) throws KeyStoreException
124      {
125        Provider[] p = Security.getProviders();
126        KeyStoreException lastException = null;
127        for (int i = 0; i < p.length; i++)
128          try
129            {
130              return getInstance(type, p[i]);
131            }
132          catch (KeyStoreException x)
133            {
134              lastException = x;
135            }
136        if (lastException != null)
137          throw lastException;
138        throw new KeyStoreException(type);
139      }
140    
141      /**
142       * Returns an instance of a <code>KeyStore</code> representing the specified
143       * type, from the named provider.
144       *
145       * @param type the type of keystore to create.
146       * @param provider the name of the provider to use.
147       * @return a <code>KeyStore</code> repesenting the desired type.
148       * @throws KeyStoreException if the designated type is not implemented by the
149       *           given provider.
150       * @throws NoSuchProviderException if the provider is not found.
151       * @throws IllegalArgumentException if either <code>type</code> or
152       *           <code>provider</code> is <code>null</code> or empty.
153       */
154      public static KeyStore getInstance(String type, String provider)
155        throws KeyStoreException, NoSuchProviderException
156      {
157        if (provider == null)
158          throw new IllegalArgumentException("provider MUST NOT be null");
159        provider = provider.trim();
160        if (provider.length() == 0)
161          throw new IllegalArgumentException("provider MUST NOT be empty");
162        Provider p = Security.getProvider(provider);
163        if (p == null)
164          throw new NoSuchProviderException(provider);
165        return getInstance(type, p);
166      }
167    
168      /**
169       * Returns an instance of a <code>KeyStore</code> representing the specified
170       * type, from the specified provider.
171       *
172       * @param type the type of keystore to create.
173       * @param provider the provider to use.
174       * @return a <code>KeyStore</code> repesenting the desired type.
175       * @throws KeyStoreException if the designated type is not implemented by the
176       *           given provider.
177       * @throws IllegalArgumentException if either <code>type</code> or
178       *           <code>provider</code> is <code>null</code>, or if
179       *           <code>type</code> is an empty string.
180       * @since 1.4
181       */
182      public static KeyStore getInstance(String type, Provider provider)
183          throws KeyStoreException
184      {
185        Throwable cause;
186        try
187          {
188            Object spi = Engine.getInstance(KEY_STORE, type, provider);
189            return new KeyStore((KeyStoreSpi) spi, provider, type);
190          }
191        catch (NoSuchAlgorithmException x)
192          {
193            cause = x;
194          }
195        catch (InvocationTargetException x)
196          {
197            cause = x.getCause() != null ? x.getCause() : x;
198          }
199        catch (ClassCastException x)
200          {
201            cause = x;
202          }
203        KeyStoreException x = new KeyStoreException(type);
204        x.initCause(cause);
205        throw x;
206      }
207    
208      /**
209       * Returns the default KeyStore type. This method looks up the
210       * type in &lt;JAVA_HOME&gt;/lib/security/java.security with the
211       * property "keystore.type" or if that fails then "gkr" .
212       */
213      public static final String getDefaultType()
214      {
215        // Security reads every property in java.security so it
216        // will return this property if it exists.
217        String tmp = Security.getProperty("keystore.type");
218    
219        if (tmp == null)
220          tmp = "gkr";
221    
222        return tmp;
223      }
224    
225      // Instance methods.
226      // ------------------------------------------------------------------------
227    
228      /**
229         Gets the provider that the class is from.
230    
231         @return the provider of this class
232       */
233      public final Provider getProvider()
234      {
235        return provider;
236      }
237    
238      /**
239         Returns the type of the KeyStore supported
240    
241         @return A string with the type of KeyStore
242       */
243      public final String getType()
244      {
245        return type;
246      }
247    
248      /**
249         Returns the key associated with given alias using the
250         supplied password.
251    
252         @param alias an alias for the key to get
253         @param password password to access key with
254    
255         @return the requested key, or null otherwise
256    
257         @throws NoSuchAlgorithmException if there is no algorithm
258         for recovering the key
259         @throws UnrecoverableKeyException key cannot be reocovered
260         (wrong password).
261       */
262      public final Key getKey(String alias, char[]password)
263        throws KeyStoreException, NoSuchAlgorithmException,
264        UnrecoverableKeyException
265      {
266        return keyStoreSpi.engineGetKey(alias, password);
267      }
268    
269      /**
270         Gets a Certificate chain for the specified alias.
271    
272         @param alias the alias name
273    
274         @return a chain of Certificates ( ordered from the user's
275         certificate to the Certificate Authority's ) or
276         null if the alias does not exist or there is no
277         certificate chain for the alias ( the alias refers
278         to a trusted certificate entry or there is no entry).
279       */
280      public final java.security.cert.
281        Certificate[] getCertificateChain(String alias) throws KeyStoreException
282      {
283        return keyStoreSpi.engineGetCertificateChain(alias);
284      }
285    
286      /**
287         Gets a Certificate for the specified alias.
288    
289         If there is a trusted certificate entry then that is returned.
290         it there is a key entry with a certificate chain then the
291         first certificate is return or else null.
292    
293         @param alias the alias name
294    
295         @return a Certificate or null if the alias does not exist
296         or there is no certificate for the alias
297       */
298      public final java.security.cert.Certificate getCertificate(String alias)
299        throws KeyStoreException
300      {
301        return keyStoreSpi.engineGetCertificate(alias);
302      }
303    
304      /**
305         Gets entry creation date for the specified alias.
306    
307         @param alias the alias name
308    
309         @returns the entry creation date or null
310       */
311      public final Date getCreationDate(String alias) throws KeyStoreException
312      {
313        return keyStoreSpi.engineGetCreationDate(alias);
314      }
315    
316      /**
317         Assign the key to the alias in the keystore, protecting it
318         with the given password. It will overwrite an existing
319         entry and if the key is a PrivateKey, also add the
320         certificate chain representing the corresponding public key.
321    
322         @param alias the alias name
323         @param key the key to add
324         @password the password to protect with
325         @param chain the certificate chain for the corresponding
326         public key
327    
328         @throws KeyStoreException if it fails
329       */
330      public final void setKeyEntry(String alias, Key key, char[]password,
331                                    java.security.cert.
332                                    Certificate[]chain) throws KeyStoreException
333      {
334        keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
335      }
336    
337      /**
338         Assign the key to the alias in the keystore. It will overwrite
339         an existing entry and if the key is a PrivateKey, also
340         add the certificate chain representing the corresponding
341         public key.
342    
343         @param alias the alias name
344         @param key the key to add
345         @param chain the certificate chain for the corresponding
346         public key
347    
348         @throws KeyStoreException if it fails
349       */
350      public final void setKeyEntry(String alias, byte[]key,
351                                    java.security.cert.
352                                    Certificate[]chain) throws KeyStoreException
353      {
354        keyStoreSpi.engineSetKeyEntry(alias, key, chain);
355      }
356    
357      /**
358         Assign the certificate to the alias in the keystore. It
359         will overwrite an existing entry.
360    
361         @param alias the alias name
362         @param cert the certificate to add
363    
364         @throws KeyStoreException if it fails
365       */
366      public final void setCertificateEntry(String alias,
367                                            java.security.cert.
368                                            Certificate cert) throws
369        KeyStoreException
370      {
371        keyStoreSpi.engineSetCertificateEntry(alias, cert);
372      }
373    
374      /**
375         Deletes the entry for the specified entry.
376    
377         @param alias the alias name
378    
379         @throws KeyStoreException if it fails
380       */
381      public final void deleteEntry(String alias) throws KeyStoreException
382      {
383        keyStoreSpi.engineDeleteEntry(alias);
384      }
385    
386      /**
387         Generates a list of all the aliases in the keystore.
388    
389         @return an Enumeration of the aliases
390       */
391      public final Enumeration<String> aliases() throws KeyStoreException
392      {
393        return keyStoreSpi.engineAliases();
394      }
395    
396      /**
397         Determines if the keystore contains the specified alias.
398    
399         @param alias the alias name
400    
401         @return true if it contains the alias, false otherwise
402       */
403      public final boolean containsAlias(String alias) throws KeyStoreException
404      {
405        return keyStoreSpi.engineContainsAlias(alias);
406      }
407    
408      /**
409         Returns the number of entries in the keystore.
410    
411         @returns the number of keystore entries.
412       */
413      public final int size() throws KeyStoreException
414      {
415        return keyStoreSpi.engineSize();
416      }
417    
418      /**
419         Determines if the keystore contains a key entry for
420         the specified alias.
421    
422         @param alias the alias name
423    
424         @return true if it is a key entry, false otherwise
425       */
426      public final boolean isKeyEntry(String alias) throws KeyStoreException
427      {
428        return keyStoreSpi.engineIsKeyEntry(alias);
429      }
430    
431    
432      /**
433         Determines if the keystore contains a certificate entry for
434         the specified alias.
435    
436         @param alias the alias name
437    
438         @return true if it is a certificate entry, false otherwise
439       */
440      public final boolean isCertificateEntry(String alias)
441        throws KeyStoreException
442      {
443        return keyStoreSpi.engineIsCertificateEntry(alias);
444      }
445    
446      /**
447         Determines if the keystore contains the specified certificate
448         entry and returns the alias.
449    
450         It checks every entry and for a key entry checks only the
451         first certificate in the chain.
452    
453         @param cert Certificate to look for
454    
455         @return alias of first matching certificate, null if it
456         does not exist.
457       */
458      public final String getCertificateAlias(java.security.cert.Certificate cert)
459        throws KeyStoreException
460      {
461        return keyStoreSpi.engineGetCertificateAlias(cert);
462      }
463    
464      /**
465         Stores the keystore in the specified output stream and it
466         uses the specified key it keep it secure.
467    
468         @param stream the output stream to save the keystore to
469         @param password the password to protect the keystore integrity with
470    
471         @throws IOException if an I/O error occurs.
472         @throws NoSuchAlgorithmException the data integrity algorithm
473         used cannot be found.
474         @throws CertificateException if any certificates could not be
475         stored in the output stream.
476       */
477      public final void store(OutputStream stream, char[]password)
478        throws KeyStoreException, IOException, NoSuchAlgorithmException,
479        CertificateException
480      {
481        keyStoreSpi.engineStore(stream, password);
482      }
483    
484      /**
485         Loads the keystore from the specified input stream and it
486         uses the specified password to check for integrity if supplied.
487    
488         @param stream the input stream to load the keystore from
489         @param password the password to check the keystore integrity with
490    
491         @throws IOException if an I/O error occurs.
492         @throws NoSuchAlgorithmException the data integrity algorithm
493         used cannot be found.
494         @throws CertificateException if any certificates could not be
495         stored in the output stream.
496       */
497      public final void load(InputStream stream, char[]password)
498        throws IOException, NoSuchAlgorithmException, CertificateException
499      {
500        keyStoreSpi.engineLoad(stream, password);
501      }
502    
503    }