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+
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.util.Debug;
35+import sun.security.jca.*;
36+import 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+
76+public 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+}