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/sun/security/pkcs11/P11RSACipher.java
38919 views
1
/*
2
* Copyright (c) 2003, 2020, 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 sun.security.pkcs11;
27
28
import java.security.*;
29
import java.security.spec.AlgorithmParameterSpec;
30
import java.security.spec.*;
31
32
import java.util.Locale;
33
34
import javax.crypto.*;
35
import javax.crypto.spec.*;
36
37
import static sun.security.pkcs11.TemplateManager.*;
38
import sun.security.pkcs11.wrapper.*;
39
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
40
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
41
import sun.security.util.KeyUtil;
42
43
/**
44
* RSA Cipher implementation class. We currently only support
45
* PKCS#1 v1.5 padding on top of CKM_RSA_PKCS.
46
*
47
* @author Andreas Sterbenz
48
* @since 1.5
49
*/
50
final class P11RSACipher extends CipherSpi {
51
52
// minimum length of PKCS#1 v1.5 padding
53
private final static int PKCS1_MIN_PADDING_LENGTH = 11;
54
55
// constant byte[] of length 0
56
private final static byte[] B0 = new byte[0];
57
58
// mode constant for public key encryption
59
private final static int MODE_ENCRYPT = 1;
60
// mode constant for private key decryption
61
private final static int MODE_DECRYPT = 2;
62
// mode constant for private key encryption (signing)
63
private final static int MODE_SIGN = 3;
64
// mode constant for public key decryption (verifying)
65
private final static int MODE_VERIFY = 4;
66
67
// padding type constant for NoPadding
68
private final static int PAD_NONE = 1;
69
// padding type constant for PKCS1Padding
70
private final static int PAD_PKCS1 = 2;
71
72
// token instance
73
private final Token token;
74
75
// algorithm name (always "RSA")
76
private final String algorithm;
77
78
// mechanism id
79
private final long mechanism;
80
81
// associated session, if any
82
private Session session;
83
84
// mode, one of MODE_* above
85
private int mode;
86
87
// padding, one of PAD_* above
88
private int padType;
89
90
private byte[] buffer;
91
private int bufOfs;
92
93
// key, if init() was called
94
private P11Key p11Key;
95
96
// flag indicating whether an operation is initialized
97
private boolean initialized;
98
99
// maximum input data size allowed
100
// for decryption, this is the length of the key
101
// for encryption, length of the key minus minimum padding length
102
private int maxInputSize;
103
104
// maximum output size. this is the length of the key
105
private int outputSize;
106
107
// cipher parameter for TLS RSA premaster secret
108
private AlgorithmParameterSpec spec = null;
109
110
// the source of randomness
111
private SecureRandom random;
112
113
P11RSACipher(Token token, String algorithm, long mechanism)
114
throws PKCS11Exception {
115
super();
116
this.token = token;
117
this.algorithm = "RSA";
118
this.mechanism = mechanism;
119
}
120
121
// modes do not make sense for RSA, but allow ECB
122
// see JCE spec
123
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
124
if (mode.equalsIgnoreCase("ECB") == false) {
125
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
126
}
127
}
128
129
protected void engineSetPadding(String padding)
130
throws NoSuchPaddingException {
131
String lowerPadding = padding.toLowerCase(Locale.ENGLISH);
132
if (lowerPadding.equals("pkcs1padding")) {
133
padType = PAD_PKCS1;
134
} else if (lowerPadding.equals("nopadding")) {
135
padType = PAD_NONE;
136
} else {
137
throw new NoSuchPaddingException("Unsupported padding " + padding);
138
}
139
}
140
141
// return 0 as block size, we are not a block cipher
142
// see JCE spec
143
protected int engineGetBlockSize() {
144
return 0;
145
}
146
147
// return the output size
148
// see JCE spec
149
protected int engineGetOutputSize(int inputLen) {
150
return outputSize;
151
}
152
153
// no IV, return null
154
// see JCE spec
155
protected byte[] engineGetIV() {
156
return null;
157
}
158
159
// no parameters, return null
160
// see JCE spec
161
protected AlgorithmParameters engineGetParameters() {
162
return null;
163
}
164
165
// see JCE spec
166
protected void engineInit(int opmode, Key key, SecureRandom random)
167
throws InvalidKeyException {
168
implInit(opmode, key);
169
}
170
171
// see JCE spec
172
protected void engineInit(int opmode, Key key,
173
AlgorithmParameterSpec params, SecureRandom random)
174
throws InvalidKeyException, InvalidAlgorithmParameterException {
175
if (params != null) {
176
if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
177
throw new InvalidAlgorithmParameterException(
178
"Parameters not supported");
179
}
180
spec = params;
181
this.random = random; // for TLS RSA premaster secret
182
}
183
implInit(opmode, key);
184
}
185
186
// see JCE spec
187
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
188
SecureRandom random)
189
throws InvalidKeyException, InvalidAlgorithmParameterException {
190
if (params != null) {
191
throw new InvalidAlgorithmParameterException(
192
"Parameters not supported");
193
}
194
implInit(opmode, key);
195
}
196
197
private void implInit(int opmode, Key key) throws InvalidKeyException {
198
reset(true);
199
p11Key = P11KeyFactory.convertKey(token, key, algorithm);
200
boolean encrypt;
201
if (opmode == Cipher.ENCRYPT_MODE) {
202
encrypt = true;
203
} else if (opmode == Cipher.DECRYPT_MODE) {
204
encrypt = false;
205
} else if (opmode == Cipher.WRAP_MODE) {
206
if (p11Key.isPublic() == false) {
207
throw new InvalidKeyException
208
("Wrap has to be used with public keys");
209
}
210
// No further setup needed for C_Wrap(). We'll initialize later if
211
// we can't use C_Wrap().
212
return;
213
} else if (opmode == Cipher.UNWRAP_MODE) {
214
if (p11Key.isPrivate() == false) {
215
throw new InvalidKeyException
216
("Unwrap has to be used with private keys");
217
}
218
// No further setup needed for C_Unwrap(). We'll initialize later
219
// if we can't use C_Unwrap().
220
return;
221
} else {
222
throw new InvalidKeyException("Unsupported mode: " + opmode);
223
}
224
if (p11Key.isPublic()) {
225
mode = encrypt ? MODE_ENCRYPT : MODE_VERIFY;
226
} else if (p11Key.isPrivate()) {
227
mode = encrypt ? MODE_SIGN : MODE_DECRYPT;
228
} else {
229
throw new InvalidKeyException("Unknown key type: " + p11Key);
230
}
231
int n = (p11Key.length() + 7) >> 3;
232
outputSize = n;
233
buffer = new byte[n];
234
maxInputSize = ((padType == PAD_PKCS1 && encrypt) ?
235
(n - PKCS1_MIN_PADDING_LENGTH) : n);
236
try {
237
initialize();
238
} catch (PKCS11Exception e) {
239
throw new InvalidKeyException("init() failed", e);
240
}
241
}
242
243
// reset the states to the pre-initialized values
244
private void reset(boolean doCancel) {
245
if (!initialized) {
246
return;
247
}
248
initialized = false;
249
250
try {
251
if (session == null) {
252
return;
253
}
254
255
if (doCancel && token.explicitCancel) {
256
cancelOperation();
257
}
258
} finally {
259
p11Key.releaseKeyID();
260
session = token.releaseSession(session);
261
}
262
}
263
264
// should only called by reset as this method does not update other
265
// state variables such as "initialized"
266
private void cancelOperation() {
267
token.ensureValid();
268
// cancel operation by finishing it; avoid killSession as some
269
// hardware vendors may require re-login
270
try {
271
PKCS11 p11 = token.p11;
272
int inLen = maxInputSize;
273
int outLen = buffer.length;
274
long sessId = session.id();
275
switch (mode) {
276
case MODE_ENCRYPT:
277
p11.C_Encrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen);
278
break;
279
case MODE_DECRYPT:
280
p11.C_Decrypt(sessId, 0, buffer, 0, inLen, 0, buffer, 0, outLen);
281
break;
282
case MODE_SIGN:
283
byte[] tmpBuffer = new byte[maxInputSize];
284
p11.C_Sign(sessId, tmpBuffer);
285
break;
286
case MODE_VERIFY:
287
p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer,
288
0, outLen);
289
break;
290
default:
291
throw new ProviderException("internal error");
292
}
293
} catch (PKCS11Exception e) {
294
// XXX ensure this always works, ignore error
295
}
296
}
297
298
private void ensureInitialized() throws PKCS11Exception {
299
token.ensureValid();
300
if (!initialized) {
301
initialize();
302
}
303
}
304
305
private void initialize() throws PKCS11Exception {
306
if (p11Key == null) {
307
throw new ProviderException(
308
"Operation cannot be performed without " +
309
"calling engineInit first");
310
}
311
long keyID = p11Key.getKeyID();
312
try {
313
if (session == null) {
314
session = token.getOpSession();
315
}
316
PKCS11 p11 = token.p11;
317
CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
318
switch (mode) {
319
case MODE_ENCRYPT:
320
p11.C_EncryptInit(session.id(), ckMechanism, keyID);
321
break;
322
case MODE_DECRYPT:
323
p11.C_DecryptInit(session.id(), ckMechanism, keyID);
324
break;
325
case MODE_SIGN:
326
p11.C_SignInit(session.id(), ckMechanism, keyID);
327
break;
328
case MODE_VERIFY:
329
p11.C_VerifyRecoverInit(session.id(), ckMechanism, keyID);
330
break;
331
default:
332
throw new AssertionError("internal error");
333
}
334
bufOfs = 0;
335
initialized = true;
336
} catch (PKCS11Exception e) {
337
p11Key.releaseKeyID();
338
session = token.releaseSession(session);
339
throw e;
340
}
341
}
342
343
private void implUpdate(byte[] in, int inOfs, int inLen) {
344
try {
345
ensureInitialized();
346
} catch (PKCS11Exception e) {
347
throw new ProviderException("update() failed", e);
348
}
349
if ((inLen == 0) || (in == null)) {
350
return;
351
}
352
if (bufOfs + inLen > maxInputSize) {
353
bufOfs = maxInputSize + 1;
354
return;
355
}
356
System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
357
bufOfs += inLen;
358
}
359
360
private int implDoFinal(byte[] out, int outOfs, int outLen)
361
throws BadPaddingException, IllegalBlockSizeException {
362
if (bufOfs > maxInputSize) {
363
reset(true);
364
throw new IllegalBlockSizeException("Data must not be longer "
365
+ "than " + maxInputSize + " bytes");
366
}
367
try {
368
ensureInitialized();
369
PKCS11 p11 = token.p11;
370
int n;
371
switch (mode) {
372
case MODE_ENCRYPT:
373
n = p11.C_Encrypt
374
(session.id(), 0, buffer, 0, bufOfs, 0, out, outOfs, outLen);
375
break;
376
case MODE_DECRYPT:
377
n = p11.C_Decrypt
378
(session.id(), 0, buffer, 0, bufOfs, 0, out, outOfs, outLen);
379
break;
380
case MODE_SIGN:
381
byte[] tmpBuffer = new byte[bufOfs];
382
System.arraycopy(buffer, 0, tmpBuffer, 0, bufOfs);
383
tmpBuffer = p11.C_Sign(session.id(), tmpBuffer);
384
if (tmpBuffer.length > outLen) {
385
throw new BadPaddingException(
386
"Output buffer (" + outLen + ") is too small to " +
387
"hold the produced data (" + tmpBuffer.length + ")");
388
}
389
System.arraycopy(tmpBuffer, 0, out, outOfs, tmpBuffer.length);
390
n = tmpBuffer.length;
391
break;
392
case MODE_VERIFY:
393
n = p11.C_VerifyRecover
394
(session.id(), buffer, 0, bufOfs, out, outOfs, outLen);
395
break;
396
default:
397
throw new ProviderException("internal error");
398
}
399
return n;
400
} catch (PKCS11Exception e) {
401
throw (BadPaddingException)new BadPaddingException
402
("doFinal() failed").initCause(e);
403
} finally {
404
reset(false);
405
}
406
}
407
408
// see JCE spec
409
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
410
implUpdate(in, inOfs, inLen);
411
return B0;
412
}
413
414
// see JCE spec
415
protected int engineUpdate(byte[] in, int inOfs, int inLen,
416
byte[] out, int outOfs) throws ShortBufferException {
417
implUpdate(in, inOfs, inLen);
418
return 0;
419
}
420
421
// see JCE spec
422
protected byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
423
throws IllegalBlockSizeException, BadPaddingException {
424
implUpdate(in, inOfs, inLen);
425
int n = implDoFinal(buffer, 0, buffer.length);
426
byte[] out = new byte[n];
427
System.arraycopy(buffer, 0, out, 0, n);
428
return out;
429
}
430
431
// see JCE spec
432
protected int engineDoFinal(byte[] in, int inOfs, int inLen,
433
byte[] out, int outOfs) throws ShortBufferException,
434
IllegalBlockSizeException, BadPaddingException {
435
implUpdate(in, inOfs, inLen);
436
return implDoFinal(out, outOfs, out.length - outOfs);
437
}
438
439
private byte[] doFinal() throws BadPaddingException,
440
IllegalBlockSizeException {
441
byte[] t = new byte[2048];
442
int n = implDoFinal(t, 0, t.length);
443
byte[] out = new byte[n];
444
System.arraycopy(t, 0, out, 0, n);
445
return out;
446
}
447
448
// see JCE spec
449
protected byte[] engineWrap(Key key) throws InvalidKeyException,
450
IllegalBlockSizeException {
451
String keyAlg = key.getAlgorithm();
452
P11Key sKey = null;
453
try {
454
// The conversion may fail, e.g. trying to wrap an AES key on
455
// a token that does not support AES, or when the key size is
456
// not within the range supported by the token.
457
sKey = P11SecretKeyFactory.convertKey(token, key, keyAlg);
458
} catch (InvalidKeyException ike) {
459
byte[] toBeWrappedKey = key.getEncoded();
460
if (toBeWrappedKey == null) {
461
throw new InvalidKeyException
462
("wrap() failed, no encoding available", ike);
463
}
464
// Directly encrypt the key encoding when key conversion failed
465
implInit(Cipher.ENCRYPT_MODE, p11Key);
466
implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length);
467
try {
468
return doFinal();
469
} catch (BadPaddingException bpe) {
470
// should not occur
471
throw new InvalidKeyException("wrap() failed", bpe);
472
} finally {
473
// Restore original mode
474
implInit(Cipher.WRAP_MODE, p11Key);
475
}
476
}
477
Session s = null;
478
long p11KeyID = p11Key.getKeyID();
479
long sKeyID = sKey.getKeyID();
480
try {
481
s = token.getOpSession();
482
return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
483
p11KeyID, sKeyID);
484
} catch (PKCS11Exception e) {
485
throw new InvalidKeyException("wrap() failed", e);
486
} finally {
487
p11Key.releaseKeyID();
488
sKey.releaseKeyID();
489
token.releaseSession(s);
490
}
491
}
492
493
// see JCE spec
494
protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
495
int type) throws InvalidKeyException, NoSuchAlgorithmException {
496
497
boolean isTlsRsaPremasterSecret =
498
algorithm.equals("TlsRsaPremasterSecret");
499
Exception failover = null;
500
501
// Should C_Unwrap be preferred for non-TLS RSA premaster secret?
502
if (token.supportsRawSecretKeyImport()) {
503
// XXX implement unwrap using C_Unwrap() for all keys
504
implInit(Cipher.DECRYPT_MODE, p11Key);
505
try {
506
if (wrappedKey.length > maxInputSize) {
507
throw new InvalidKeyException("Key is too long for unwrapping");
508
}
509
510
byte[] encoded = null;
511
implUpdate(wrappedKey, 0, wrappedKey.length);
512
try {
513
encoded = doFinal();
514
} catch (BadPaddingException e) {
515
if (isTlsRsaPremasterSecret) {
516
failover = e;
517
} else {
518
throw new InvalidKeyException("Unwrapping failed", e);
519
}
520
} catch (IllegalBlockSizeException e) {
521
// should not occur, handled with length check above
522
throw new InvalidKeyException("Unwrapping failed", e);
523
}
524
525
if (isTlsRsaPremasterSecret) {
526
if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
527
throw new IllegalStateException(
528
"No TlsRsaPremasterSecretParameterSpec specified");
529
}
530
531
// polish the TLS premaster secret
532
TlsRsaPremasterSecretParameterSpec psps =
533
(TlsRsaPremasterSecretParameterSpec)spec;
534
encoded = KeyUtil.checkTlsPreMasterSecretKey(
535
psps.getClientVersion(), psps.getServerVersion(),
536
random, encoded, (failover != null));
537
}
538
539
return ConstructKeys.constructKey(encoded, algorithm, type);
540
} finally {
541
// Restore original mode
542
implInit(Cipher.UNWRAP_MODE, p11Key);
543
}
544
} else {
545
Session s = null;
546
SecretKey secretKey = null;
547
long p11KeyID = p11Key.getKeyID();
548
try {
549
try {
550
s = token.getObjSession();
551
long keyType = CKK_GENERIC_SECRET;
552
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
553
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
554
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
555
};
556
attributes = token.getAttributes(
557
O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
558
559
long keyID = token.p11.C_UnwrapKey(s.id(),
560
new CK_MECHANISM(mechanism), p11KeyID,
561
wrappedKey, attributes);
562
secretKey = P11Key.secretKey(s, keyID,
563
algorithm, 48 << 3, attributes);
564
} catch (PKCS11Exception e) {
565
if (isTlsRsaPremasterSecret) {
566
failover = e;
567
} else {
568
throw new InvalidKeyException("unwrap() failed", e);
569
}
570
}
571
572
if (isTlsRsaPremasterSecret) {
573
TlsRsaPremasterSecretParameterSpec psps =
574
(TlsRsaPremasterSecretParameterSpec)spec;
575
576
// Please use the tricky failover as the parameter so that
577
// smart compiler won't dispose the unused variable.
578
secretKey = polishPreMasterSecretKey(token, s,
579
failover, secretKey,
580
psps.getClientVersion(), psps.getServerVersion());
581
}
582
583
return secretKey;
584
} finally {
585
p11Key.releaseKeyID();
586
token.releaseSession(s);
587
}
588
}
589
}
590
591
// see JCE spec
592
protected int engineGetKeySize(Key key) throws InvalidKeyException {
593
int n = P11KeyFactory.convertKey(token, key, algorithm).length();
594
return n;
595
}
596
597
private static SecretKey polishPreMasterSecretKey(
598
Token token, Session session,
599
Exception failover, SecretKey unwrappedKey,
600
int clientVersion, int serverVersion) {
601
602
SecretKey newKey;
603
CK_VERSION version = new CK_VERSION(
604
(clientVersion >>> 8) & 0xFF, clientVersion & 0xFF);
605
try {
606
CK_ATTRIBUTE[] attributes = token.getAttributes(
607
O_GENERATE, CKO_SECRET_KEY,
608
CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
609
long keyID = token.p11.C_GenerateKey(session.id(),
610
new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version),
611
attributes);
612
newKey = P11Key.secretKey(session,
613
keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
614
} catch (PKCS11Exception e) {
615
throw new ProviderException(
616
"Could not generate premaster secret", e);
617
}
618
619
return (failover == null) ? unwrappedKey : newKey;
620
}
621
622
}
623
624
final class ConstructKeys {
625
/**
626
* Construct a public key from its encoding.
627
*
628
* @param encodedKey the encoding of a public key.
629
*
630
* @param encodedKeyAlgorithm the algorithm the encodedKey is for.
631
*
632
* @return a public key constructed from the encodedKey.
633
*/
634
private static final PublicKey constructPublicKey(byte[] encodedKey,
635
String encodedKeyAlgorithm)
636
throws InvalidKeyException, NoSuchAlgorithmException {
637
try {
638
KeyFactory keyFactory =
639
KeyFactory.getInstance(encodedKeyAlgorithm);
640
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
641
return keyFactory.generatePublic(keySpec);
642
} catch (NoSuchAlgorithmException nsae) {
643
throw new NoSuchAlgorithmException("No installed providers " +
644
"can create keys for the " +
645
encodedKeyAlgorithm +
646
"algorithm", nsae);
647
} catch (InvalidKeySpecException ike) {
648
throw new InvalidKeyException("Cannot construct public key", ike);
649
}
650
}
651
652
/**
653
* Construct a private key from its encoding.
654
*
655
* @param encodedKey the encoding of a private key.
656
*
657
* @param encodedKeyAlgorithm the algorithm the wrapped key is for.
658
*
659
* @return a private key constructed from the encodedKey.
660
*/
661
private static final PrivateKey constructPrivateKey(byte[] encodedKey,
662
String encodedKeyAlgorithm) throws InvalidKeyException,
663
NoSuchAlgorithmException {
664
try {
665
KeyFactory keyFactory =
666
KeyFactory.getInstance(encodedKeyAlgorithm);
667
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
668
return keyFactory.generatePrivate(keySpec);
669
} catch (NoSuchAlgorithmException nsae) {
670
throw new NoSuchAlgorithmException("No installed providers " +
671
"can create keys for the " +
672
encodedKeyAlgorithm +
673
"algorithm", nsae);
674
} catch (InvalidKeySpecException ike) {
675
throw new InvalidKeyException("Cannot construct private key", ike);
676
}
677
}
678
679
/**
680
* Construct a secret key from its encoding.
681
*
682
* @param encodedKey the encoding of a secret key.
683
*
684
* @param encodedKeyAlgorithm the algorithm the secret key is for.
685
*
686
* @return a secret key constructed from the encodedKey.
687
*/
688
private static final SecretKey constructSecretKey(byte[] encodedKey,
689
String encodedKeyAlgorithm) {
690
return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
691
}
692
693
static final Key constructKey(byte[] encoding, String keyAlgorithm,
694
int keyType) throws InvalidKeyException, NoSuchAlgorithmException {
695
switch (keyType) {
696
case Cipher.SECRET_KEY:
697
return constructSecretKey(encoding, keyAlgorithm);
698
case Cipher.PRIVATE_KEY:
699
return constructPrivateKey(encoding, keyAlgorithm);
700
case Cipher.PUBLIC_KEY:
701
return constructPublicKey(encoding, keyAlgorithm);
702
default:
703
throw new InvalidKeyException("Unknown keytype " + keyType);
704
}
705
}
706
}
707
708