Home | History | Annotate | Download | only in crypto
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package javax.crypto;
     19 
     20 import java.security.InvalidAlgorithmParameterException;
     21 import java.security.InvalidKeyException;
     22 import java.security.Key;
     23 import java.security.NoSuchAlgorithmException;
     24 import java.security.NoSuchProviderException;
     25 import java.security.Provider;
     26 import java.security.SecureRandom;
     27 import java.security.Security;
     28 import java.security.spec.AlgorithmParameterSpec;
     29 import org.apache.harmony.security.fortress.Engine;
     30 
     31 /**
     32  * This class provides the functionality for a key exchange protocol. This
     33  * enables two or more parties to agree on a secret key for symmetric
     34  * cryptography.
     35  */
     36 public class KeyAgreement {
     37 
     38     // Used to access common engine functionality
     39     private static final Engine ENGINE = new Engine("KeyAgreement");
     40 
     41     // Store SecureRandom
     42     private static final SecureRandom RANDOM = new SecureRandom();
     43 
     44     // Store used provider
     45     private final Provider provider;
     46 
     47     // Store used spi implementation
     48     private final KeyAgreementSpi spiImpl;
     49 
     50     // Store used algorithm name
     51     private final String algorithm;
     52 
     53     /**
     54      * Creates a new {@code KeyAgreement} instance.
     55      *
     56      * @param keyAgreeSpi
     57      *            the <b>SPI</b> delegate.
     58      * @param provider
     59      *            the provider providing this KeyAgreement.
     60      * @param algorithm
     61      *            the name of the key agreement algorithm.
     62      */
     63     protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider,
     64             String algorithm) {
     65         this.provider = provider;
     66         this.algorithm = algorithm;
     67         this.spiImpl = keyAgreeSpi;
     68     }
     69 
     70     /**
     71      * Returns the name of the key agreement algorithm.
     72      *
     73      * @return the name of the key agreement algorithm.
     74      */
     75     public final String getAlgorithm() {
     76         return algorithm;
     77     }
     78 
     79     /**
     80      * Returns the provider for this {@code KeyAgreement} instance.
     81      *
     82      * @return the provider for this {@code KeyAgreement} instance.
     83      */
     84     public final Provider getProvider() {
     85         return provider;
     86     }
     87 
     88     /**
     89      * Creates a new {@code KeyAgreement} for the specified algorithm.
     90      *
     91      * @param algorithm
     92      *            the name of the key agreement algorithm to create.
     93      * @return a key agreement for the specified algorithm.
     94      * @throws NoSuchAlgorithmException
     95      *             if no installed provider can provide the requested algorithm.
     96      * @throws NullPointerException
     97      *             if the specified algorithm is {@code null}.
     98      */
     99     public static final KeyAgreement getInstance(String algorithm)
    100             throws NoSuchAlgorithmException {
    101         if (algorithm == null) {
    102             throw new NullPointerException("algorithm == null");
    103         }
    104         Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null);
    105         return new KeyAgreement((KeyAgreementSpi) sap.spi, sap.provider, algorithm);
    106     }
    107 
    108     /**
    109      * Creates a new {@code KeyAgreement} for the specified algorithm from the
    110      * specified provider.
    111      *
    112      * @param algorithm
    113      *            the name of the key agreement algorithm to create.
    114      * @param provider
    115      *            the name of the provider that provides the requested
    116      *            algorithm.
    117      * @return a key agreement for the specified algorithm from the specified
    118      *         provider.
    119      * @throws NoSuchAlgorithmException
    120      *             if the specified provider cannot provide the requested
    121      *             algorithm.
    122      * @throws NoSuchProviderException
    123      *             if the specified provider does not exist.
    124      * @throws IllegalArgumentException
    125      *             if the specified provider name is {@code null} or empty.
    126      */
    127     public static final KeyAgreement getInstance(String algorithm,
    128             String provider) throws NoSuchAlgorithmException,
    129             NoSuchProviderException {
    130         if (provider == null || provider.isEmpty()) {
    131             throw new IllegalArgumentException("Provider is null or empty");
    132         }
    133         Provider impProvider = Security.getProvider(provider);
    134         if (impProvider == null) {
    135             throw new NoSuchProviderException(provider);
    136         }
    137         return getInstance(algorithm, impProvider);
    138     }
    139 
    140     /**
    141      * Create a new {@code KeyAgreement} for the specified algorithm from the
    142      * specified provider.
    143      *
    144      * @param algorithm
    145      *            the name of the key agreement algorithm to create.
    146      * @param provider
    147      *            the provider that provides the requested algorithm.
    148      * @return a key agreement for the specified algorithm from the specified
    149      *         provider.
    150      * @throws NoSuchAlgorithmException
    151      *             if the specified provider cannot provide the requested
    152      *             algorithm.
    153      * @throws IllegalArgumentException
    154      *             if the specified provider is {@code null}.
    155      * @throws NullPointerException
    156      *             if the specified algorithm name is {@code null}.
    157      */
    158     public static final KeyAgreement getInstance(String algorithm,
    159             Provider provider) throws NoSuchAlgorithmException {
    160         if (provider == null) {
    161             throw new IllegalArgumentException("provider == null");
    162         }
    163         if (algorithm == null) {
    164             throw new NullPointerException("algorithm == null");
    165         }
    166         Object spi = ENGINE.getInstance(algorithm, provider, null);
    167         return new KeyAgreement((KeyAgreementSpi) spi, provider, algorithm);
    168     }
    169 
    170     /**
    171      * Initializes this {@code KeyAgreement} with the specified key.
    172      *
    173      * @param key
    174      *            the key to initialize this key agreement.
    175      * @throws InvalidKeyException
    176      *             if the specified key cannot be used to initialize this key
    177      *             agreement.
    178      */
    179     public final void init(Key key) throws InvalidKeyException {
    180         spiImpl.engineInit(key, RANDOM);//new SecureRandom());
    181     }
    182 
    183     /**
    184      * Initializes this {@code KeyAgreement} with the specified key and the
    185      * specified randomness source.
    186      *
    187      * @param key
    188      *            the key to initialize this key agreement.
    189      * @param random
    190      *            the source for any randomness needed.
    191      * @throws InvalidKeyException
    192      *             if the specified key cannot be used to initialize this key
    193      *             agreement.
    194      */
    195     public final void init(Key key, SecureRandom random)
    196             throws InvalidKeyException {
    197         spiImpl.engineInit(key, random);
    198     }
    199 
    200     /**
    201      * Initializes this {@code KeyAgreement} with the specified key and the
    202      * algorithm parameters.
    203      *
    204      * @param key
    205      *            the key to initialize this key agreement.
    206      * @param params
    207      *            the parameters for this key agreement algorithm.
    208      * @throws InvalidKeyException
    209      *             if the specified key cannot be used to initialize this key
    210      *             agreement.
    211      * @throws InvalidAlgorithmParameterException
    212      *             if the specified parameters are invalid for this key
    213      *             agreement algorithm.
    214      */
    215     public final void init(Key key, AlgorithmParameterSpec params)
    216             throws InvalidKeyException, InvalidAlgorithmParameterException {
    217         spiImpl.engineInit(key, params, RANDOM);//new SecureRandom());
    218     }
    219 
    220     /**
    221      * Initializes this {@code KeyAgreement} with the specified key, algorithm
    222      * parameters and randomness source.
    223      *
    224      * @param key
    225      *            the key to initialize this key agreement.
    226      * @param params
    227      *            the parameters for this key agreement algorithm.
    228      * @param random
    229      *            the source for any randomness needed.
    230      * @throws InvalidKeyException
    231      *             if the specified key cannot be used to initialize this key
    232      *             agreement.
    233      * @throws InvalidAlgorithmParameterException
    234      *             if the specified parameters are invalid for this key
    235      *             agreement algorithm.
    236      */
    237     public final void init(Key key, AlgorithmParameterSpec params,
    238             SecureRandom random) throws InvalidKeyException,
    239             InvalidAlgorithmParameterException {
    240         spiImpl.engineInit(key, params, random);
    241     }
    242 
    243     /**
    244      * Does the next (or the last) phase of the key agreement, using the
    245      * specified key.
    246      *
    247      * @param key
    248      *            the key received from the other party for this phase.
    249      * @param lastPhase
    250      *            set to {@code true} if this is the last phase of this key
    251      *            agreement.
    252      * @return the intermediate key from this phase or {@code null} if there is
    253      *         no intermediate key for this phase.
    254      * @throws InvalidKeyException
    255      *             if the specified key cannot be used in this key agreement or
    256      *             this phase,
    257      * @throws IllegalStateException
    258      *             if this instance has not been initialized.
    259      */
    260     public final Key doPhase(Key key, boolean lastPhase)
    261             throws InvalidKeyException, IllegalStateException {
    262         return spiImpl.engineDoPhase(key, lastPhase);
    263     }
    264 
    265     /**
    266      * Generates the shared secret.
    267      *
    268      * @return the generated shared secret.
    269      * @throws IllegalStateException
    270      *             if this key agreement is not complete.
    271      */
    272     public final byte[] generateSecret() throws IllegalStateException {
    273         return spiImpl.engineGenerateSecret();
    274     }
    275 
    276     /**
    277      * Generates the shared secret and stores it into the buffer {@code
    278      * sharedSecred} at {@code offset}.
    279      *
    280      * @param sharedSecret
    281      *            the buffer to store the shared secret.
    282      * @param offset
    283      *            the offset in the buffer.
    284      * @return the number of bytes stored in the buffer.
    285      * @throws IllegalStateException
    286      *             if this key agreement is not complete.
    287      * @throws ShortBufferException
    288      *             if the specified buffer is too small for the shared secret.
    289      */
    290     public final int generateSecret(byte[] sharedSecret, int offset)
    291             throws IllegalStateException, ShortBufferException {
    292         return spiImpl.engineGenerateSecret(sharedSecret, offset);
    293     }
    294 
    295     /**
    296      * Generates the shared secret.
    297      *
    298      * @param algorithm
    299      *            the algorithm to for the {@code SecretKey}
    300      * @return the shared secret as a {@code SecretKey} of the specified
    301      *         algorithm.
    302      * @throws IllegalStateException
    303      *             if this key agreement is not complete.
    304      * @throws NoSuchAlgorithmException
    305      *             if the specified algorithm for the secret key does not
    306      *             exists.
    307      * @throws InvalidKeyException
    308      *             if a {@code SecretKey} with the specified algorithm cannot be
    309      *             created using the generated shared secret.
    310      */
    311     public final SecretKey generateSecret(String algorithm)
    312             throws IllegalStateException, NoSuchAlgorithmException,
    313             InvalidKeyException {
    314         return spiImpl.engineGenerateSecret(algorithm);
    315     }
    316 
    317 }
    318