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