Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package javax.crypto;
     27 
     28 import java.util.*;
     29 
     30 import java.security.*;
     31 import java.security.Provider.Service;
     32 import java.security.spec.*;
     33 
     34 import sun.security.jca.*;
     35 import sun.security.jca.GetInstance.Instance;
     36 
     37 /**
     38  * This class represents a factory for secret keys.
     39  *
     40  * <P> Key factories are used to convert <I>keys</I> (opaque
     41  * cryptographic keys of type <code>Key</code>) into <I>key specifications</I>
     42  * (transparent representations of the underlying key material), and vice
     43  * versa.
     44  * Secret key factories operate only on secret (symmetric) keys.
     45  *
     46  * <P> Key factories are bi-directional, i.e., they allow to build an opaque
     47  * key object from a given key specification (key material), or to retrieve
     48  * the underlying key material of a key object in a suitable format.
     49  *
     50  * <P> Application developers should refer to their provider's documentation
     51  * to find out which key specifications are supported by the
     52  * {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and
     53  * {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec}
     54  * methods.
     55  * For example, the DES secret-key factory supplied by the "SunJCE" provider
     56  * supports <code>DESKeySpec</code> as a transparent representation of DES
     57  * keys, and that provider's secret-key factory for Triple DES keys supports
     58  * <code>DESedeKeySpec</code> as a transparent representation of Triple DES
     59  * keys.
     60  *
     61  * <p> Android provides the following <code>SecretKeyFactory</code> algorithms:
     62  * <table>
     63  *   <thead>
     64  *     <tr>
     65  *       <th>Algorithm</th>
     66  *       <th>Supported API Levels</th>
     67  *     </tr>
     68  *   </thead>
     69  *   <tbody>
     70  *     <tr>
     71  *       <td>AES</td>
     72  *       <td>23+</td>
     73  *     </tr>
     74  *     <tr>
     75  *       <td>DES</td>
     76  *       <td>1+</td>
     77  *     </tr>
     78  *     <tr>
     79  *       <td>DESede</td>
     80  *       <td>1+</td>
     81  *     </tr>
     82  *     <tr>
     83  *       <td>HmacSHA1</td>
     84  *       <td>23+</td>
     85  *     </tr>
     86  *     <tr>
     87  *       <td>HmacSHA224</td>
     88  *       <td>23+</td>
     89  *     </tr>
     90  *     <tr>
     91  *       <td>HmacSHA256</td>
     92  *       <td>23+</td>
     93  *     </tr>
     94  *     <tr>
     95  *       <td>HmacSHA384</td>
     96  *       <td>23+</td>
     97  *     </tr>
     98  *     <tr>
     99  *       <td>HmacSHA512</td>
    100  *       <td>23+</td>
    101  *     </tr>
    102  *     <tr>
    103  *       <td>PBEwithHmacSHA1</td>
    104  *       <td>1+</td>
    105  *     </tr>
    106  *     <tr>
    107  *       <td>PBEwithHmacSHA1AndAES_128</td>
    108  *       <td>26+</td>
    109  *     </tr>
    110  *     <tr>
    111  *       <td>PBEwithHmacSHA1AndAES_256</td>
    112  *       <td>26+</td>
    113  *     </tr>
    114  *     <tr>
    115  *       <td>PBEwithHmacSHA224AndAES_128</td>
    116  *       <td>26+</td>
    117  *     </tr>
    118  *     <tr>
    119  *       <td>PBEwithHmacSHA224AndAES_256</td>
    120  *       <td>26+</td>
    121  *     </tr>
    122  *     <tr>
    123  *       <td>PBEwithHmacSHA256AndAES_128</td>
    124  *       <td>26+</td>
    125  *     </tr>
    126  *     <tr>
    127  *       <td>PBEwithHmacSHA256AndAES_256</td>
    128  *       <td>26+</td>
    129  *     </tr>
    130  *     <tr>
    131  *       <td>PBEwithHmacSHA384AndAES_128</td>
    132  *       <td>26+</td>
    133  *     </tr>
    134  *     <tr>
    135  *       <td>PBEwithHmacSHA384AndAES_256</td>
    136  *       <td>26+</td>
    137  *     </tr>
    138  *     <tr>
    139  *       <td>PBEwithHmacSHA512AndAES_128</td>
    140  *       <td>26+</td>
    141  *     </tr>
    142  *     <tr>
    143  *       <td>PBEwithHmacSHA512AndAES_256</td>
    144  *       <td>26+</td>
    145  *     </tr>
    146  *     <tr>
    147  *       <td>PBEwithMD5AND128BITAES-CBC-OPENSSL</td>
    148  *       <td>1+</td>
    149  *     </tr>
    150  *     <tr>
    151  *       <td>PBEwithMD5AND192BITAES-CBC-OPENSSL</td>
    152  *       <td>1+</td>
    153  *     </tr>
    154  *     <tr>
    155  *       <td>PBEwithMD5AND256BITAES-CBC-OPENSSL</td>
    156  *       <td>1+</td>
    157  *     </tr>
    158  *     <tr>
    159  *       <td>PBEwithMD5ANDDES</td>
    160  *       <td>1+</td>
    161  *     </tr>
    162  *     <tr>
    163  *       <td>PBEwithMD5ANDRC2</td>
    164  *       <td>1+</td>
    165  *     </tr>
    166  *     <tr>
    167  *       <td>PBEwithSHA1ANDDES</td>
    168  *       <td>1+</td>
    169  *     </tr>
    170  *     <tr>
    171  *       <td>PBEwithSHA1ANDRC2</td>
    172  *       <td>1+</td>
    173  *     </tr>
    174  *     <tr>
    175  *       <td>PBEwithSHA256AND128BITAES-CBC-BC</td>
    176  *       <td>1+</td>
    177  *     </tr>
    178  *     <tr>
    179  *       <td>PBEwithSHA256AND192BITAES-CBC-BC</td>
    180  *       <td>1+</td>
    181  *     </tr>
    182  *     <tr>
    183  *       <td>PBEwithSHA256AND256BITAES-CBC-BC</td>
    184  *       <td>1+</td>
    185  *     </tr>
    186  *     <tr>
    187  *       <td>PBEwithSHAAND128BITAES-CBC-BC</td>
    188  *       <td>1+</td>
    189  *     </tr>
    190  *     <tr>
    191  *       <td>PBEwithSHAAND128BITRC2-CBC</td>
    192  *       <td>10+</td>
    193  *     </tr>
    194  *     <tr>
    195  *       <td>PBEwithSHAAND128BITRC4</td>
    196  *       <td>10+</td>
    197  *     </tr>
    198  *     <tr>
    199  *       <td>PBEwithSHAAND192BITAES-CBC-BC</td>
    200  *       <td>1+</td>
    201  *     </tr>
    202  *     <tr>
    203  *       <td>PBEwithSHAAND2-KEYTRIPLEDES-CBC</td>
    204  *       <td>1+</td>
    205  *     </tr>
    206  *     <tr>
    207  *       <td>PBEwithSHAAND256BITAES-CBC-BC</td>
    208  *       <td>1+</td>
    209  *     </tr>
    210  *     <tr>
    211  *       <td>PBEwithSHAAND3-KEYTRIPLEDES-CBC</td>
    212  *       <td>1+</td>
    213  *     </tr>
    214  *     <tr>
    215  *       <td>PBEwithSHAAND40BITRC2-CBC</td>
    216  *       <td>1+</td>
    217  *     </tr>
    218  *     <tr>
    219  *       <td>PBEwithSHAAND40BITRC4</td>
    220  *       <td>10+</td>
    221  *     </tr>
    222  *     <tr>
    223  *       <td>PBEwithSHAANDTWOFISH-CBC</td>
    224  *       <td>10+</td>
    225  *     </tr>
    226  *     <tr>
    227  *       <td>PBKDF2withHmacSHA1</td>
    228  *       <td>10+</td>
    229  *     </tr>
    230  *     <tr>
    231  *       <td>PBKDF2withHmacSHA1And8BIT</td>
    232  *       <td>19+</td>
    233  *     </tr>
    234  *     <tr>
    235  *       <td>PBKDF2withHmacSHA224</td>
    236  *       <td>26+</td>
    237  *     </tr>
    238  *     <tr>
    239  *       <td>PBKDF2withHmacSHA256</td>
    240  *       <td>26+</td>
    241  *     </tr>
    242  *     <tr>
    243  *       <td>PBKDF2withHmacSHA384</td>
    244  *       <td>26+</td>
    245  *     </tr>
    246  *     <tr>
    247  *       <td>PBKDF2withHmacSHA512</td>
    248  *       <td>26+</td>
    249  *     </tr>
    250  *   </tbody>
    251  * </table>
    252  *
    253  * These algorithms are described in the <a href=
    254  * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
    255  * SecretKeyFactory section</a> of the
    256  * Java Cryptography Architecture Standard Algorithm Name Documentation.
    257  *
    258  * @author Jan Luehe
    259  *
    260  * @see SecretKey
    261  * @see javax.crypto.spec.DESKeySpec
    262  * @see javax.crypto.spec.DESedeKeySpec
    263  * @see javax.crypto.spec.PBEKeySpec
    264  * @since 1.4
    265  */
    266 
    267 public class SecretKeyFactory {
    268 
    269     // The provider
    270     private Provider provider;
    271 
    272     // The algorithm associated with this factory
    273     private final String algorithm;
    274 
    275     // The provider implementation (delegate)
    276     private volatile SecretKeyFactorySpi spi;
    277 
    278     // lock for mutex during provider selection
    279     private final Object lock = new Object();
    280 
    281     // remaining services to try in provider selection
    282     // null once provider is selected
    283     private Iterator<Service> serviceIterator;
    284 
    285     /**
    286      * Creates a SecretKeyFactory object.
    287      *
    288      * @param keyFacSpi the delegate
    289      * @param provider the provider
    290      * @param algorithm the secret-key algorithm
    291      */
    292     protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi,
    293                                Provider provider, String algorithm) {
    294         this.spi = keyFacSpi;
    295         this.provider = provider;
    296         this.algorithm = algorithm;
    297     }
    298 
    299     private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
    300         this.algorithm = algorithm;
    301         List<Service> list =
    302                 GetInstance.getServices("SecretKeyFactory", algorithm);
    303         serviceIterator = list.iterator();
    304         // fetch and instantiate initial spi
    305         if (nextSpi(null) == null) {
    306             throw new NoSuchAlgorithmException
    307                 (algorithm + " SecretKeyFactory not available");
    308         }
    309     }
    310 
    311     /**
    312      * Returns a <code>SecretKeyFactory</code> object that converts
    313      * secret keys of the specified algorithm.
    314      *
    315      * <p> This method traverses the list of registered security Providers,
    316      * starting with the most preferred Provider.
    317      * A new SecretKeyFactory object encapsulating the
    318      * SecretKeyFactorySpi implementation from the first
    319      * Provider that supports the specified algorithm is returned.
    320      *
    321      * <p> Note that the list of registered providers may be retrieved via
    322      * the {@link Security#getProviders() Security.getProviders()} method.
    323      *
    324      * @param algorithm the standard name of the requested secret-key
    325      * algorithm.
    326      * See the SecretKeyFactory section in the <a href=
    327      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
    328      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
    329      * for information about standard algorithm names.
    330      *
    331      * @return the new <code>SecretKeyFactory</code> object.
    332      *
    333      * @exception NullPointerException if the specified algorithm
    334      *          is null.
    335      *
    336      * @exception NoSuchAlgorithmException if no Provider supports a
    337      *          SecretKeyFactorySpi implementation for the
    338      *          specified algorithm.
    339      *
    340      * @see java.security.Provider
    341      */
    342     public static final SecretKeyFactory getInstance(String algorithm)
    343             throws NoSuchAlgorithmException {
    344         return new SecretKeyFactory(algorithm);
    345     }
    346 
    347     /**
    348      * Returns a <code>SecretKeyFactory</code> object that converts
    349      * secret keys of the specified algorithm.
    350      *
    351      * <p> A new SecretKeyFactory object encapsulating the
    352      * SecretKeyFactorySpi implementation from the specified provider
    353      * is returned.  The specified provider must be registered
    354      * in the security provider list.
    355      *
    356      * <p> Note that the list of registered providers may be retrieved via
    357      * the {@link Security#getProviders() Security.getProviders()} method.
    358      *
    359      * @param algorithm the standard name of the requested secret-key
    360      * algorithm.
    361      * See the SecretKeyFactory section in the <a href=
    362      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
    363      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
    364      * for information about standard algorithm names.
    365      *
    366      * @param provider the name of the provider.
    367      *
    368      * @return the new <code>SecretKeyFactory</code> object.
    369      *
    370      * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
    371      *          implementation for the specified algorithm is not
    372      *          available from the specified provider.
    373      *
    374      * @exception NullPointerException if the specified algorithm
    375      *          is null.
    376      *
    377      * @throws NoSuchProviderException if the specified provider is not
    378      *          registered in the security provider list.
    379      *
    380      * @exception IllegalArgumentException if the <code>provider</code>
    381      *          is null or empty.
    382      *
    383      * @see java.security.Provider
    384      */
    385     public static final SecretKeyFactory getInstance(String algorithm,
    386             String provider) throws NoSuchAlgorithmException,
    387             NoSuchProviderException {
    388         Instance instance = JceSecurity.getInstance("SecretKeyFactory",
    389                 SecretKeyFactorySpi.class, algorithm, provider);
    390         return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
    391                 instance.provider, algorithm);
    392     }
    393 
    394     /**
    395      * Returns a <code>SecretKeyFactory</code> object that converts
    396      * secret keys of the specified algorithm.
    397      *
    398      * <p> A new SecretKeyFactory object encapsulating the
    399      * SecretKeyFactorySpi implementation from the specified Provider
    400      * object is returned.  Note that the specified Provider object
    401      * does not have to be registered in the provider list.
    402      *
    403      * @param algorithm the standard name of the requested secret-key
    404      * algorithm.
    405      * See the SecretKeyFactory section in the <a href=
    406      * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecretKeyFactory">
    407      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
    408      * for information about standard algorithm names.
    409      *
    410      * @param provider the provider.
    411      *
    412      * @return the new <code>SecretKeyFactory</code> object.
    413      *
    414      * @exception NullPointerException if the specified algorithm
    415      * is null.
    416      *
    417      * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
    418      *          implementation for the specified algorithm is not available
    419      *          from the specified Provider object.
    420      *
    421      * @exception IllegalArgumentException if the <code>provider</code>
    422      *          is null.
    423      *
    424      * @see java.security.Provider
    425      */
    426     public static final SecretKeyFactory getInstance(String algorithm,
    427             Provider provider) throws NoSuchAlgorithmException {
    428         Instance instance = JceSecurity.getInstance("SecretKeyFactory",
    429                 SecretKeyFactorySpi.class, algorithm, provider);
    430         return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
    431                 instance.provider, algorithm);
    432     }
    433 
    434     /**
    435      * Returns the provider of this <code>SecretKeyFactory</code> object.
    436      *
    437      * @return the provider of this <code>SecretKeyFactory</code> object
    438      */
    439     public final Provider getProvider() {
    440         synchronized (lock) {
    441             // disable further failover after this call
    442             serviceIterator = null;
    443             return provider;
    444         }
    445     }
    446 
    447     /**
    448      * Returns the algorithm name of this <code>SecretKeyFactory</code> object.
    449      *
    450      * <p>This is the same name that was specified in one of the
    451      * <code>getInstance</code> calls that created this
    452      * <code>SecretKeyFactory</code> object.
    453      *
    454      * @return the algorithm name of this <code>SecretKeyFactory</code>
    455      * object.
    456      */
    457     public final String getAlgorithm() {
    458         return this.algorithm;
    459     }
    460 
    461     /**
    462      * Update the active spi of this class and return the next
    463      * implementation for failover. If no more implemenations are
    464      * available, this method returns null. However, the active spi of
    465      * this class is never set to null.
    466      */
    467     private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) {
    468         synchronized (lock) {
    469             // somebody else did a failover concurrently
    470             // try that spi now
    471             if ((oldSpi != null) && (oldSpi != spi)) {
    472                 return spi;
    473             }
    474             if (serviceIterator == null) {
    475                 return null;
    476             }
    477             while (serviceIterator.hasNext()) {
    478                 Service s = serviceIterator.next();
    479                 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
    480                     continue;
    481                 }
    482                 try {
    483                     Object obj = s.newInstance(null);
    484                     if (obj instanceof SecretKeyFactorySpi == false) {
    485                         continue;
    486                     }
    487                     SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj;
    488                     provider = s.getProvider();
    489                     this.spi = spi;
    490                     return spi;
    491                 } catch (NoSuchAlgorithmException e) {
    492                     // ignore
    493                 }
    494             }
    495             serviceIterator = null;
    496             return null;
    497         }
    498     }
    499 
    500     /**
    501      * Generates a <code>SecretKey</code> object from the provided key
    502      * specification (key material).
    503      *
    504      * @param keySpec the specification (key material) of the secret key
    505      *
    506      * @return the secret key
    507      *
    508      * @exception InvalidKeySpecException if the given key specification
    509      * is inappropriate for this secret-key factory to produce a secret key.
    510      */
    511     public final SecretKey generateSecret(KeySpec keySpec)
    512             throws InvalidKeySpecException {
    513         if (serviceIterator == null) {
    514             return spi.engineGenerateSecret(keySpec);
    515         }
    516         Exception failure = null;
    517         SecretKeyFactorySpi mySpi = spi;
    518         do {
    519             try {
    520                 return mySpi.engineGenerateSecret(keySpec);
    521             } catch (Exception e) {
    522                 if (failure == null) {
    523                     failure = e;
    524                 }
    525                 mySpi = nextSpi(mySpi);
    526             }
    527         } while (mySpi != null);
    528         if (failure instanceof InvalidKeySpecException) {
    529             throw (InvalidKeySpecException)failure;
    530         }
    531         throw new InvalidKeySpecException
    532                 ("Could not generate secret key", failure);
    533     }
    534 
    535     /**
    536      * Returns a specification (key material) of the given key object
    537      * in the requested format.
    538      *
    539      * @param key the key
    540      * @param keySpec the requested format in which the key material shall be
    541      * returned
    542      *
    543      * @return the underlying key specification (key material) in the
    544      * requested format
    545      *
    546      * @exception InvalidKeySpecException if the requested key specification is
    547      * inappropriate for the given key (e.g., the algorithms associated with
    548      * <code>key</code> and <code>keySpec</code> do not match, or
    549      * <code>key</code> references a key on a cryptographic hardware device
    550      * whereas <code>keySpec</code> is the specification of a software-based
    551      * key), or the given key cannot be dealt with
    552      * (e.g., the given key has an algorithm or format not supported by this
    553      * secret-key factory).
    554      */
    555     public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)
    556             throws InvalidKeySpecException {
    557         if (serviceIterator == null) {
    558             return spi.engineGetKeySpec(key, keySpec);
    559         }
    560         Exception failure = null;
    561         SecretKeyFactorySpi mySpi = spi;
    562         do {
    563             try {
    564                 return mySpi.engineGetKeySpec(key, keySpec);
    565             } catch (Exception e) {
    566                 if (failure == null) {
    567                     failure = e;
    568                 }
    569                 mySpi = nextSpi(mySpi);
    570             }
    571         } while (mySpi != null);
    572         if (failure instanceof InvalidKeySpecException) {
    573             throw (InvalidKeySpecException)failure;
    574         }
    575         throw new InvalidKeySpecException
    576                 ("Could not get key spec", failure);
    577     }
    578 
    579     /**
    580      * Translates a key object, whose provider may be unknown or potentially
    581      * untrusted, into a corresponding key object of this secret-key factory.
    582      *
    583      * @param key the key whose provider is unknown or untrusted
    584      *
    585      * @return the translated key
    586      *
    587      * @exception InvalidKeyException if the given key cannot be processed
    588      * by this secret-key factory.
    589      */
    590     public final SecretKey translateKey(SecretKey key)
    591             throws InvalidKeyException {
    592         if (serviceIterator == null) {
    593             return spi.engineTranslateKey(key);
    594         }
    595         Exception failure = null;
    596         SecretKeyFactorySpi mySpi = spi;
    597         do {
    598             try {
    599                 return mySpi.engineTranslateKey(key);
    600             } catch (Exception e) {
    601                 if (failure == null) {
    602                     failure = e;
    603                 }
    604                 mySpi = nextSpi(mySpi);
    605             }
    606         } while (mySpi != null);
    607         if (failure instanceof InvalidKeyException) {
    608             throw (InvalidKeyException)failure;
    609         }
    610         throw new InvalidKeyException
    611                 ("Could not translate key", failure);
    612     }
    613 }
    614