History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/crypto/KeyAgreement.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/crypto/KeyAgreement.java+634−0
@@ -0,0 +1,634 @@
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
26package javax.crypto;
27
28import java.util.*;
29
30import java.security.*;
31import java.security.Provider.Service;
32import java.security.spec.*;
33
34import sun.security.util.Debug;
35import sun.security.jca.*;
36import sun.security.jca.GetInstance.Instance;
37
38/**
39 * This class provides the functionality of a key agreement (or key
40 * exchange) protocol.
41 * <p>
42 * The keys involved in establishing a shared secret are created by one of the
43 * key generators (<code>KeyPairGenerator</code> or
44 * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
45 * an intermediate phase of the key agreement protocol.
46 *
47 * <p> For each of the correspondents in the key exchange, <code>doPhase</code>
48 * needs to be called. For example, if this key exchange is with one other
49 * party, <code>doPhase</code> needs to be called once, with the
50 * <code>lastPhase</code> flag set to <code>true</code>.
51 * If this key exchange is
52 * with two other parties, <code>doPhase</code> needs to be called twice,
53 * the first time setting the <code>lastPhase</code> flag to
54 * <code>false</code>, and the second time setting it to <code>true</code>.
55 * There may be any number of parties involved in a key exchange.
56 *
57 * <p> Every implementation of the Java platform is required to support the
58 * following standard <code>KeyAgreement</code> algorithm:
59 * <ul>
60 * <li><tt>DiffieHellman</tt></li>
61 * </ul>
62 * This algorithm is described in the <a href=
63 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
64 * KeyAgreement section</a> of the
65 * Java Cryptography Architecture Standard Algorithm Name Documentation.
66 * Consult the release documentation for your implementation to see if any
67 * other algorithms are supported.
68 *
69 * @author Jan Luehe
70 *
71 * @see KeyGenerator
72 * @see SecretKey
73 * @since 1.4
74 */
75
76public class KeyAgreement {
77
78 private static final Debug debug =
79 Debug.getInstance("jca", "KeyAgreement");
80
81 // The provider
82 private Provider provider;
83
84 // The provider implementation (delegate)
85 private KeyAgreementSpi spi;
86
87 // The name of the key agreement algorithm.
88 private final String algorithm;
89
90 // next service to try in provider selection
91 // null once provider is selected
92 private Service firstService;
93
94 // remaining services to try in provider selection
95 // null once provider is selected
96 private Iterator serviceIterator;
97
98 private final Object lock;
99
100 /**
101 * Creates a KeyAgreement object.
102 *
103 * @param keyAgreeSpi the delegate
104 * @param provider the provider
105 * @param algorithm the algorithm
106 */
107 protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider,
108 String algorithm) {
109 this.spi = keyAgreeSpi;
110 this.provider = provider;
111 this.algorithm = algorithm;
112 lock = null;
113 }
114
115 private KeyAgreement(Service s, Iterator t, String algorithm) {
116 firstService = s;
117 serviceIterator = t;
118 this.algorithm = algorithm;
119 lock = new Object();
120 }
121
122 /**
123 * Returns the algorithm name of this <code>KeyAgreement</code> object.
124 *
125 * <p>This is the same name that was specified in one of the
126 * <code>getInstance</code> calls that created this
127 * <code>KeyAgreement</code> object.
128 *
129 * @return the algorithm name of this <code>KeyAgreement</code> object.
130 */
131 public final String getAlgorithm() {
132 return this.algorithm;
133 }
134
135 /**
136 * Returns a <code>KeyAgreement</code> object that implements the
137 * specified key agreement algorithm.
138 *
139 * <p> This method traverses the list of registered security Providers,
140 * starting with the most preferred Provider.
141 * A new KeyAgreement object encapsulating the
142 * KeyAgreementSpi implementation from the first
143 * Provider that supports the specified algorithm is returned.
144 *
145 * <p> Note that the list of registered providers may be retrieved via
146 * the {@link Security#getProviders() Security.getProviders()} method.
147 *
148 * @param algorithm the standard name of the requested key agreement
149 * algorithm.
150 * See the KeyAgreement section in the <a href=
151 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
152 * Java Cryptography Architecture Standard Algorithm Name Documentation
153 * for information about standard algorithm names.
154 *
155 * @return the new <code>KeyAgreement</code> object.
156 *
157 * @exception NullPointerException if the specified algorithm
158 * is null.
159 *
160 * @exception NoSuchAlgorithmException if no Provider supports a
161 * KeyAgreementSpi implementation for the
162 * specified algorithm.
163 *
164 * @see java.security.Provider
165 */
166 public static final KeyAgreement getInstance(String algorithm)
167 throws NoSuchAlgorithmException {
168 List services = GetInstance.getServices("KeyAgreement", algorithm);
169 // make sure there is at least one service from a signed provider
170 Iterator t = services.iterator();
171 while (t.hasNext()) {
172 Service s = (Service)t.next();
173 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
174 continue;
175 }
176 return new KeyAgreement(s, t, algorithm);
177 }
178 throw new NoSuchAlgorithmException
179 ("Algorithm " + algorithm + " not available");
180 }
181
182 /**
183 * Returns a <code>KeyAgreement</code> object that implements the
184 * specified key agreement algorithm.
185 *
186 * <p> A new KeyAgreement object encapsulating the
187 * KeyAgreementSpi implementation from the specified provider
188 * is returned. The specified provider must be registered
189 * in the security provider list.
190 *
191 * <p> Note that the list of registered providers may be retrieved via
192 * the {@link Security#getProviders() Security.getProviders()} method.
193 *
194 * @param algorithm the standard name of the requested key agreement
195 * algorithm.
196 * See the KeyAgreement section in the <a href=
197 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
198 * Java Cryptography Architecture Standard Algorithm Name Documentation
199 * for information about standard algorithm names.
200 *
201 * @param provider the name of the provider.
202 *
203 * @return the new <code>KeyAgreement</code> object.
204 *
205 * @exception NullPointerException if the specified algorithm
206 * is null.
207 *
208 * @exception NoSuchAlgorithmException if a KeyAgreementSpi
209 * implementation for the specified algorithm is not
210 * available from the specified provider.
211 *
212 * @exception NoSuchProviderException if the specified provider is not
213 * registered in the security provider list.
214 *
215 * @exception IllegalArgumentException if the <code>provider</code>
216 * is null or empty.
217 *
218 * @see java.security.Provider
219 */
220 public static final KeyAgreement getInstance(String algorithm,
221 String provider) throws NoSuchAlgorithmException,
222 NoSuchProviderException {
223 Instance instance = JceSecurity.getInstance
224 ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
225 return new KeyAgreement((KeyAgreementSpi)instance.impl,
226 instance.provider, algorithm);
227 }
228
229 /**
230 * Returns a <code>KeyAgreement</code> object that implements the
231 * specified key agreement algorithm.
232 *
233 * <p> A new KeyAgreement object encapsulating the
234 * KeyAgreementSpi implementation from the specified Provider
235 * object is returned. Note that the specified Provider object
236 * does not have to be registered in the provider list.
237 *
238 * @param algorithm the standard name of the requested key agreement
239 * algorithm.
240 * See the KeyAgreement section in the <a href=
241 * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyAgreement">
242 * Java Cryptography Architecture Standard Algorithm Name Documentation
243 * for information about standard algorithm names.
244 *
245 * @param provider the provider.
246 *
247 * @return the new <code>KeyAgreement</code> object.
248 *
249 * @exception NullPointerException if the specified algorithm
250 * is null.
251 *
252 * @exception NoSuchAlgorithmException if a KeyAgreementSpi
253 * implementation for the specified algorithm is not available
254 * from the specified Provider object.
255 *
256 * @exception IllegalArgumentException if the <code>provider</code>
257 * is null.
258 *
259 * @see java.security.Provider
260 */
261 public static final KeyAgreement getInstance(String algorithm,
262 Provider provider) throws NoSuchAlgorithmException {
263 Instance instance = JceSecurity.getInstance
264 ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
265 return new KeyAgreement((KeyAgreementSpi)instance.impl,
266 instance.provider, algorithm);
267 }
268
269 // max number of debug warnings to print from chooseFirstProvider()
270 private static int warnCount = 10;
271
272 /**
273 * Choose the Spi from the first provider available. Used if
274 * delayed provider selection is not possible because init()
275 * is not the first method called.
276 */
277 void chooseFirstProvider() {
278 if (spi != null) {
279 return;
280 }
281 synchronized (lock) {
282 if (spi != null) {
283 return;
284 }
285 if (debug != null) {
286 int w = --warnCount;
287 if (w >= 0) {
288 debug.println("KeyAgreement.init() not first method "
289 + "called, disabling delayed provider selection");
290 if (w == 0) {
291 debug.println("Further warnings of this type will "
292 + "be suppressed");
293 }
294 new Exception("Call trace").printStackTrace();
295 }
296 }
297 Exception lastException = null;
298 while ((firstService != null) || serviceIterator.hasNext()) {
299 Service s;
300 if (firstService != null) {
301 s = firstService;
302 firstService = null;
303 } else {
304 s = (Service)serviceIterator.next();
305 }
306 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
307 continue;
308 }
309 try {
310 Object obj = s.newInstance(null);
311 if (obj instanceof KeyAgreementSpi == false) {
312 continue;
313 }
314 spi = (KeyAgreementSpi)obj;
315 provider = s.getProvider();
316 // not needed any more
317 firstService = null;
318 serviceIterator = null;
319 return;
320 } catch (Exception e) {
321 lastException = e;
322 }
323 }
324 ProviderException e = new ProviderException
325 ("Could not construct KeyAgreementSpi instance");
326 if (lastException != null) {
327 e.initCause(lastException);
328 }
329 throw e;
330 }
331 }
332
333 private final static int I_NO_PARAMS = 1;
334 private final static int I_PARAMS = 2;
335
336 private void implInit(KeyAgreementSpi spi, int type, Key key,
337 AlgorithmParameterSpec params, SecureRandom random)
338 throws InvalidKeyException, InvalidAlgorithmParameterException {
339 if (type == I_NO_PARAMS) {
340 spi.engineInit(key, random);
341 } else { // I_PARAMS
342 spi.engineInit(key, params, random);
343 }
344 }
345
346 private void chooseProvider(int initType, Key key,
347 AlgorithmParameterSpec params, SecureRandom random)
348 throws InvalidKeyException, InvalidAlgorithmParameterException {
349 synchronized (lock) {
350 if (spi != null) {
351 implInit(spi, initType, key, params, random);
352 return;
353 }
354 Exception lastException = null;
355 while ((firstService != null) || serviceIterator.hasNext()) {
356 Service s;
357 if (firstService != null) {
358 s = firstService;
359 firstService = null;
360 } else {
361 s = (Service)serviceIterator.next();
362 }
363 // if provider says it does not support this key, ignore it
364 if (s.supportsParameter(key) == false) {
365 continue;
366 }
367 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
368 continue;
369 }
370 try {
371 KeyAgreementSpi spi = (KeyAgreementSpi)s.newInstance(null);
372 implInit(spi, initType, key, params, random);
373 provider = s.getProvider();
374 this.spi = spi;
375 firstService = null;
376 serviceIterator = null;
377 return;
378 } catch (Exception e) {
379 // NoSuchAlgorithmException from newInstance()
380 // InvalidKeyException from init()
381 // RuntimeException (ProviderException) from init()
382 if (lastException == null) {
383 lastException = e;
384 }
385 }
386 }
387 // no working provider found, fail
388 if (lastException instanceof InvalidKeyException) {
389 throw (InvalidKeyException)lastException;
390 }
391 if (lastException instanceof InvalidAlgorithmParameterException) {
392 throw (InvalidAlgorithmParameterException)lastException;
393 }
394 if (lastException instanceof RuntimeException) {
395 throw (RuntimeException)lastException;
396 }
397 String kName = (key != null) ? key.getClass().getName() : "(null)";
398 throw new InvalidKeyException
399 ("No installed provider supports this key: "
400 + kName, lastException);
401 }
402 }
403
404 /**
405 * Returns the provider of this <code>KeyAgreement</code> object.
406 *
407 * @return the provider of this <code>KeyAgreement</code> object
408 */
409 public final Provider getProvider() {
410 chooseFirstProvider();
411 return this.provider;
412 }
413
414 /**
415 * Initializes this key agreement with the given key, which is required to
416 * contain all the algorithm parameters required for this key agreement.
417 *
418 * <p> If this key agreement requires any random bytes, it will get
419 * them using the
420 * {@link SecureRandom <code>SecureRandom</code>}
421 * implementation of the highest-priority
422 * installed provider as the source of randomness.
423 * (If none of the installed providers supply an implementation of
424 * SecureRandom, a system-provided source of randomness will be used.)
425 *
426 * @param key the party's private information. For example, in the case
427 * of the Diffie-Hellman key agreement, this would be the party's own
428 * Diffie-Hellman private key.
429 *
430 * @exception InvalidKeyException if the given key is
431 * inappropriate for this key agreement, e.g., is of the wrong type or
432 * has an incompatible algorithm type.
433 */
434 public final void init(Key key) throws InvalidKeyException {
435 init(key, JceSecurity.RANDOM);
436 }
437
438 /**
439 * Initializes this key agreement with the given key and source of
440 * randomness. The given key is required to contain all the algorithm
441 * parameters required for this key agreement.
442 *
443 * <p> If the key agreement algorithm requires random bytes, it gets them
444 * from the given source of randomness, <code>random</code>.
445 * However, if the underlying
446 * algorithm implementation does not require any random bytes,
447 * <code>random</code> is ignored.
448 *
449 * @param key the party's private information. For example, in the case
450 * of the Diffie-Hellman key agreement, this would be the party's own
451 * Diffie-Hellman private key.
452 * @param random the source of randomness
453 *
454 * @exception InvalidKeyException if the given key is
455 * inappropriate for this key agreement, e.g., is of the wrong type or
456 * has an incompatible algorithm type.
457 */
458 public final void init(Key key, SecureRandom random)
459 throws InvalidKeyException {
460 if (spi != null) {
461 spi.engineInit(key, random);
462 } else {
463 try {
464 chooseProvider(I_NO_PARAMS, key, null, random);
465 } catch (InvalidAlgorithmParameterException e) {
466 // should never occur
467 throw new InvalidKeyException(e);
468 }
469 }
470 }
471
472 /**
473 * Initializes this key agreement with the given key and set of
474 * algorithm parameters.
475 *
476 * <p> If this key agreement requires any random bytes, it will get
477 * them using the
478 * {@link SecureRandom <code>SecureRandom</code>}
479 * implementation of the highest-priority
480 * installed provider as the source of randomness.
481 * (If none of the installed providers supply an implementation of
482 * SecureRandom, a system-provided source of randomness will be used.)
483 *
484 * @param key the party's private information. For example, in the case
485 * of the Diffie-Hellman key agreement, this would be the party's own
486 * Diffie-Hellman private key.
487 * @param params the key agreement parameters
488 *
489 * @exception InvalidKeyException if the given key is
490 * inappropriate for this key agreement, e.g., is of the wrong type or
491 * has an incompatible algorithm type.
492 * @exception InvalidAlgorithmParameterException if the given parameters
493 * are inappropriate for this key agreement.
494 */
495 public final void init(Key key, AlgorithmParameterSpec params)
496 throws InvalidKeyException, InvalidAlgorithmParameterException
497 {
498 init(key, params, JceSecurity.RANDOM);
499 }
500
501 /**
502 * Initializes this key agreement with the given key, set of
503 * algorithm parameters, and source of randomness.
504 *
505 * @param key the party's private information. For example, in the case
506 * of the Diffie-Hellman key agreement, this would be the party's own
507 * Diffie-Hellman private key.
508 * @param params the key agreement parameters
509 * @param random the source of randomness
510 *
511 * @exception InvalidKeyException if the given key is
512 * inappropriate for this key agreement, e.g., is of the wrong type or
513 * has an incompatible algorithm type.
514 * @exception InvalidAlgorithmParameterException if the given parameters
515 * are inappropriate for this key agreement.
516 */
517 public final void init(Key key, AlgorithmParameterSpec params,
518 SecureRandom random)
519 throws InvalidKeyException, InvalidAlgorithmParameterException
520 {
521 if (spi != null) {
522 spi.engineInit(key, params, random);
523 } else {
524 chooseProvider(I_PARAMS, key, params, random);
525 }
526 }
527
528 /**
529 * Executes the next phase of this key agreement with the given
530 * key that was received from one of the other parties involved in this key
531 * agreement.
532 *
533 * @param key the key for this phase. For example, in the case of
534 * Diffie-Hellman between 2 parties, this would be the other party's
535 * Diffie-Hellman public key.
536 * @param lastPhase flag which indicates whether or not this is the last
537 * phase of this key agreement.
538 *
539 * @return the (intermediate) key resulting from this phase, or null
540 * if this phase does not yield a key
541 *
542 * @exception InvalidKeyException if the given key is inappropriate for
543 * this phase.
544 * @exception IllegalStateException if this key agreement has not been
545 * initialized.
546 */
547 public final Key doPhase(Key key, boolean lastPhase)
548 throws InvalidKeyException, IllegalStateException
549 {
550 chooseFirstProvider();
551 return spi.engineDoPhase(key, lastPhase);
552 }
553
554 /**
555 * Generates the shared secret and returns it in a new buffer.
556 *
557 * <p>This method resets this <code>KeyAgreement</code> object, so that it
558 * can be reused for further key agreements. Unless this key agreement is
559 * reinitialized with one of the <code>init</code> methods, the same
560 * private information and algorithm parameters will be used for
561 * subsequent key agreements.
562 *
563 * @return the new buffer with the shared secret
564 *
565 * @exception IllegalStateException if this key agreement has not been
566 * completed yet
567 */
568 public final byte[] generateSecret() throws IllegalStateException {
569 chooseFirstProvider();
570 return spi.engineGenerateSecret();
571 }
572
573 /**
574 * Generates the shared secret, and places it into the buffer
575 * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
576 *
577 * <p>If the <code>sharedSecret</code> buffer is too small to hold the
578 * result, a <code>ShortBufferException</code> is thrown.
579 * In this case, this call should be repeated with a larger output buffer.
580 *
581 * <p>This method resets this <code>KeyAgreement</code> object, so that it
582 * can be reused for further key agreements. Unless this key agreement is
583 * reinitialized with one of the <code>init</code> methods, the same
584 * private information and algorithm parameters will be used for
585 * subsequent key agreements.
586 *
587 * @param sharedSecret the buffer for the shared secret
588 * @param offset the offset in <code>sharedSecret</code> where the
589 * shared secret will be stored
590 *
591 * @return the number of bytes placed into <code>sharedSecret</code>
592 *
593 * @exception IllegalStateException if this key agreement has not been
594 * completed yet
595 * @exception ShortBufferException if the given output buffer is too small
596 * to hold the secret
597 */
598 public final int generateSecret(byte[] sharedSecret, int offset)
599 throws IllegalStateException, ShortBufferException
600 {
601 chooseFirstProvider();
602 return spi.engineGenerateSecret(sharedSecret, offset);
603 }
604
605 /**
606 * Creates the shared secret and returns it as a <code>SecretKey</code>
607 * object of the specified algorithm.
608 *
609 * <p>This method resets this <code>KeyAgreement</code> object, so that it
610 * can be reused for further key agreements. Unless this key agreement is
611 * reinitialized with one of the <code>init</code> methods, the same
612 * private information and algorithm parameters will be used for
613 * subsequent key agreements.
614 *
615 * @param algorithm the requested secret-key algorithm
616 *
617 * @return the shared secret key
618 *
619 * @exception IllegalStateException if this key agreement has not been
620 * completed yet
621 * @exception NoSuchAlgorithmException if the specified secret-key
622 * algorithm is not available
623 * @exception InvalidKeyException if the shared secret-key material cannot
624 * be used to generate a secret key of the specified algorithm (e.g.,
625 * the key material is too short)
626 */
627 public final SecretKey generateSecret(String algorithm)
628 throws IllegalStateException, NoSuchAlgorithmException,
629 InvalidKeyException
630 {
631 chooseFirstProvider();
632 return spi.engineGenerateSecret(algorithm);
633 }
634}