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