1 package javax.crypto;
2 
3 import java.security.Key;
4 import java.security.Provider;
5 import java.security.SecureRandom;
6 import java.security.InvalidKeyException;
7 import java.security.NoSuchProviderException;
8 import java.security.NoSuchAlgorithmException;
9 import java.security.InvalidAlgorithmParameterException;
10 import java.security.spec.AlgorithmParameterSpec;
11 
12 /**
13  * This class provides the functionality of a key agreement (or key
14  * exchange) protocol.
15  * The keys involved in establishing a shared secret are created by one of the
16  * key generators (<code>KeyPairGenerator</code> or
17  * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
18  * an intermediate phase of the key agreement protocol
19  * (see <a href = "#doPhase(java.security.Key, boolean)">doPhase</a>).
20  *
21  * For each of the correspondents in the key exchange, <code>doPhase</code>
22  * needs to be called. For example, if this key exchange is with one other
23  * party, <code>doPhase</code> needs to be called once, with the
24  * <code>lastPhase</code> flag set to <code>true</code>.
25  * If this key exchange is
26  * with two other parties, <code>doPhase</code> needs to be called twice,
27  * the first time setting the <code>lastPhase</code> flag to
28  * <code>false</code>, and the second time setting it to <code>true</code>.
29  * There may be any number of parties involved in a key exchange.
30  *
31  * @see KeyGenerator
32  * @see SecretKey
33  */
34 public class KeyAgreement
35 {
36     KeyAgreementSpi keyAgreeSpi;
37     Provider        provider;
38     String          algorithm;
39 
40     /**
41      * Creates a KeyAgreement object.
42      *
43      * @param keyAgreeSpi the delegate
44      * @param provider the provider
45      * @param algorithm the algorithm
46      */
KeyAgreement( KeyAgreementSpi keyAgreeSpi, Provider provider, String algorithm)47     protected KeyAgreement(
48         KeyAgreementSpi keyAgreeSpi,
49         Provider        provider,
50         String          algorithm)
51     {
52         this.keyAgreeSpi = keyAgreeSpi;
53         this.provider = provider;
54         this.algorithm = algorithm;
55     }
56 
57     /**
58      * Returns the algorithm name of this <code>KeyAgreement</code> object.
59      * <p>
60      * This is the same name that was specified in one of the
61      * <code>getInstance</code> calls that created this
62      * <code>KeyAgreement</code> object.
63      *
64      * @return the algorithm name of this <code>KeyAgreement</code> object.
65      */
getAlgorithm()66     public final String getAlgorithm()
67     {
68         return algorithm;
69     }
70 
71     /**
72      * Generates a <code>KeyAgreement</code> object that implements the
73      * specified key agreement algorithm.
74      * If the default provider package provides an implementation of the
75      * requested key agreement algorithm, an instance of
76      * <code>KeyAgreement</code> containing that implementation is returned.
77      * If the algorithm is not available in the default provider package,
78      * other provider packages are searched.
79      *
80      * @param algorithm the standard name of the requested key agreement algorithm.
81      * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
82      * for information about standard algorithm names.
83      * @return the new <code>KeyAgreement</code> object
84      * @exception NoSuchAlgorithmException if the specified algorithm is not
85      * available in the default provider package or any of the other provider
86      * packages that were searched.
87      */
getInstance( String algorithm)88     public static final KeyAgreement getInstance(
89         String      algorithm)
90     throws NoSuchAlgorithmException
91     {
92         try
93         {
94             JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, (String) null);
95 
96             if (imp == null)
97             {
98                 throw new NoSuchAlgorithmException(algorithm + " not found");
99             }
100 
101             KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
102 
103             return keyAgree;
104         }
105         catch (NoSuchProviderException e)
106         {
107             throw new NoSuchAlgorithmException(algorithm + " not found");
108         }
109     }
110 
111     /**
112      * Generates a <code>KeyAgreement</code> object for the specified key
113      * agreement algorithm from the specified provider.
114      *
115      * @param algorithm the standard name of the requested key agreement algorithm.
116      * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
117      * for information about standard algorithm names.
118      * @param provider the provider
119      * @return the new <code>KeyAgreement</code> object
120      * @exception NoSuchAlgorithmException if the specified algorithm is not
121      * available from the specified provider.
122      */
getInstance( String algorithm, Provider provider)123     public static final KeyAgreement getInstance(
124             String      algorithm,
125             Provider      provider)
126         throws NoSuchAlgorithmException
127     {
128         if (provider == null)
129         {
130             throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()");
131         }
132 
133         JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider);
134 
135         if (imp == null)
136         {
137             throw new NoSuchAlgorithmException(algorithm + " not found");
138         }
139 
140         KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
141 
142         return keyAgree;
143     }
144 
145     /**
146      * Generates a <code>KeyAgreement</code> object for the specified key
147      * agreement algorithm from the specified provider.
148      *
149      * @param algorithm the standard name of the requested key agreement algorithm.
150      * See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
151      * for information about standard algorithm names.
152      * @param provider the name of the provider
153      * @return the new <code>KeyAgreement</code> object
154      * @exception NoSuchAlgorithmException if the specified algorithm is not
155      * available from the specified provider.
156      * @exception NoSuchProviderException if the specified provider has not
157      * been configured.
158      */
getInstance( String algorithm, String provider)159     public static final KeyAgreement getInstance(
160         String      algorithm,
161         String      provider)
162     throws NoSuchAlgorithmException, NoSuchProviderException
163     {
164         if (provider == null)
165         {
166             throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()");
167         }
168 
169         JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider);
170 
171         if (imp == null)
172         {
173             throw new NoSuchAlgorithmException(algorithm + " not found");
174         }
175 
176         KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
177 
178         return keyAgree;
179     }
180 
181     /**
182      * Returns the provider of this <code>KeyAgreement</code> object.
183      *
184      * @return the provider of this <code>KeyAgreement</code> object
185      */
getProvider()186     public final Provider getProvider()
187     {
188         return provider;
189     }
190 
191     /**
192      * Initializes this key agreement with the given key, which is required to
193      * contain all the algorithm parameters required for this key agreement.
194      * <p>
195      * If this key agreement requires any random bytes, it will get
196      * them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
197      * <code>SecureRandom</code></a> implementation of the highest-priority
198      * installed provider as the source of randomness.
199      * (If none of the installed providers supply an implementation of
200      * SecureRandom, a system-provided source of randomness will be used.)
201      *
202      * @param key the party's private information. For example, in the case
203      * of the Diffie-Hellman key agreement, this would be the party's own
204      * Diffie-Hellman private key.
205      * @exception InvalidKeyException if the given key is
206      * inappropriate for this key agreement, e.g., is of the wrong type or
207      * has an incompatible algorithm type.
208      */
init( Key key)209     public final void init(
210         Key     key)
211     throws InvalidKeyException
212     {
213         keyAgreeSpi.engineInit(key, null);
214     }
215 
216     /**
217      * Initializes this key agreement with the given key and source of
218      * randomness. The given key is required to contain all the algorithm
219      * parameters required for this key agreement.
220      * <p>
221      * If the key agreement algorithm requires random bytes, it gets them
222      * from the given source of randomness, <code>random</code>.
223      * However, if the underlying
224      * algorithm implementation does not require any random bytes,
225      * <code>random</code> is ignored.
226      *
227      * @param key the party's private information. For example, in the case
228      * of the Diffie-Hellman key agreement, this would be the party's own
229      * Diffie-Hellman private key.
230      * @param random the source of randomness
231      * @exception InvalidKeyException if the given key is
232      * inappropriate for this key agreement, e.g., is of the wrong type or
233      * has an incompatible algorithm type.
234      */
init( Key key, SecureRandom random)235     public final void init(
236         Key             key,
237         SecureRandom    random)
238     throws InvalidKeyException
239     {
240         keyAgreeSpi.engineInit(key, random);
241     }
242 
243     /**
244      * Initializes this key agreement with the given key and set of
245      * algorithm parameters.
246      * <p>
247      * If this key agreement requires any random bytes, it will get
248      * them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
249      * <code>SecureRandom</code></a> implementation of the highest-priority
250      * installed provider as the source of randomness.
251      * (If none of the installed providers supply an implementation of
252      * SecureRandom, a system-provided source of randomness will be used.)
253      *
254      * @param key the party's private information. For example, in the case
255      * of the Diffie-Hellman key agreement, this would be the party's own
256      * Diffie-Hellman private key.
257      * @param params the key agreement parameters
258      * @exception InvalidKeyException if the given key is inappropriate for this
259      * key agreement, e.g., is of the wrong type or has an incompatible algorithm type.
260      * @exception InvalidAlgorithmParameterException if the given parameters
261      * are inappropriate for this key agreement.
262      */
init( Key key, AlgorithmParameterSpec params)263     public final void init(
264         Key                     key,
265         AlgorithmParameterSpec  params)
266     throws InvalidKeyException, InvalidAlgorithmParameterException
267     {
268         keyAgreeSpi.engineInit(key, params, null);
269     }
270 
271     /**
272      * Initializes this key agreement with the given key, set of
273      * algorithm parameters, and source of randomness.
274      *
275      * @param key the party's private information. For example, in the case
276      * of the Diffie-Hellman key agreement, this would be the party's own
277      * Diffie-Hellman private key.
278      * @param params the key agreement parameters
279      * @param random the source of randomness
280      * @exception InvalidKeyException if the given key is
281      * inappropriate for this key agreement, e.g., is of the wrong type or
282      * has an incompatible algorithm type.
283      * @exception InvalidAlgorithmParameterException if the given parameters
284      * are inappropriate for this key agreement.
285      */
init( Key key, AlgorithmParameterSpec params, SecureRandom random)286     public final void init(
287         Key                     key,
288         AlgorithmParameterSpec  params,
289         SecureRandom            random)
290     throws InvalidKeyException, InvalidAlgorithmParameterException
291     {
292         keyAgreeSpi.engineInit(key, params, random);
293     }
294 
295     /**
296      * Executes the next phase of this key agreement with the given
297      * key that was received from one of the other parties involved in this key
298      * agreement.
299      *
300      * @param key the key for this phase. For example, in the case of
301      * Diffie-Hellman between 2 parties, this would be the other party's
302      * Diffie-Hellman public key.
303      * @param lastPhase flag which indicates whether or not this is the last
304      * phase of this key agreement.
305      * @return the (intermediate) key resulting from this phase, or null
306      * if this phase does not yield a key
307      * @exception InvalidKeyException if the given key is inappropriate for this phase.
308      * @exception IllegalStateException if this key agreement has not been
309      * initialized.
310      */
doPhase( Key key, boolean lastPhase)311     public final Key doPhase(
312         Key         key,
313         boolean     lastPhase)
314     throws InvalidKeyException, IllegalStateException
315     {
316         return keyAgreeSpi.engineDoPhase(key, lastPhase);
317     }
318 
319     /**
320      * Generates the shared secret and returns it in a new buffer.
321      * <p>
322      * This method resets this <code>KeyAgreement</code> object, so that it
323      * can be reused for further key agreements. Unless this key agreement is
324      * reinitialized with one of the <code>init</code> methods, the same
325      * private information and algorithm parameters will be used for
326      * subsequent key agreements.
327      *
328      * @return the new buffer with the shared secret
329      * @exception IllegalStateException if this key agreement has not been completed yet
330      */
generateSecret()331     public final byte[] generateSecret()
332     throws IllegalStateException
333     {
334         return keyAgreeSpi.engineGenerateSecret();
335     }
336 
337     /**
338      * Generates the shared secret, and places it into the buffer
339      * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
340      * <p>
341      * If the <code>sharedSecret</code> buffer is too small to hold the
342      * result, a <code>ShortBufferException</code> is thrown.
343      * In this case, this call should be repeated with a larger output buffer.
344      * <p>
345      * This method resets this <code>KeyAgreement</code> object, so that it
346      * can be reused for further key agreements. Unless this key agreement is
347      * reinitialized with one of the <code>init</code> methods, the same
348      * private information and algorithm parameters will be used for
349      * subsequent key agreements.
350      *
351      * @param sharedSecret the buffer for the shared secret
352      * @param offset the offset in <code>sharedSecret</code> where the
353      * shared secret will be stored
354      * @return the number of bytes placed into <code>sharedSecret</code>
355      * @exception IllegalStateException if this key agreement has not been
356      * completed yet
357      * @exception ShortBufferException if the given output buffer is too small
358      * to hold the secret
359      */
generateSecret( byte[] sharedSecret, int offset)360     public final int generateSecret(
361         byte[]  sharedSecret,
362         int     offset)
363     throws IllegalStateException, ShortBufferException
364     {
365         return keyAgreeSpi.engineGenerateSecret(sharedSecret, offset);
366     }
367 
368     /**
369      * Creates the shared secret and returns it as a <code>SecretKey</code>
370      * object of the specified algorithm.
371      * <p>
372      * This method resets this <code>KeyAgreement</code> object, so that it
373      * can be reused for further key agreements. Unless this key agreement is
374      * reinitialized with one of the <code>init</code> methods, the same
375      * private information and algorithm parameters will be used for
376      * subsequent key agreements.
377      *
378      * @param algorithm the requested secret-key algorithm
379      * @return the shared secret key
380      * @exception IllegalStateException if this key agreement has not been
381      * completed yet
382      * @exception NoSuchAlgorithmException if the specified secret-key
383      * algorithm is not available
384      * @exception InvalidKeyException if the shared secret-key material cannot
385      * be used to generate a secret key of the specified algorithm (e.g.,
386      * the key material is too short)
387      */
generateSecret( String algorithm)388     public final SecretKey generateSecret(
389         String      algorithm)
390     throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException
391     {
392         return keyAgreeSpi.engineGenerateSecret(algorithm);
393     }
394 }
395