Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/sun/security/rsa/RSAPSSSignature.java
67760 views
1
/*
2
* Copyright (c) 2018, 2021, 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.rsa;
27
28
import java.io.IOException;
29
import java.nio.ByteBuffer;
30
31
import java.security.*;
32
import java.security.spec.AlgorithmParameterSpec;
33
import java.security.spec.PSSParameterSpec;
34
import java.security.spec.MGF1ParameterSpec;
35
import java.security.interfaces.*;
36
37
import java.util.Arrays;
38
import java.util.Hashtable;
39
40
import sun.security.util.*;
41
import sun.security.jca.JCAUtil;
42
43
44
/**
45
* PKCS#1 v2.2 RSASSA-PSS signatures with various message digest algorithms.
46
* RSASSA-PSS implementation takes the message digest algorithm, MGF algorithm,
47
* and salt length values through the required signature PSS parameters.
48
* We support SHA-1, SHA-2 family and SHA3 family of message digest algorithms,
49
* and MGF1 mask generation function.
50
*
51
* @since 11
52
*/
53
public class RSAPSSSignature extends SignatureSpi {
54
55
private static final boolean DEBUG = false;
56
57
// utility method for comparing digest algorithms
58
// NOTE that first argument is assumed to be standard digest name
59
private boolean isDigestEqual(String stdAlg, String givenAlg) {
60
if (stdAlg == null || givenAlg == null) return false;
61
62
if (givenAlg.indexOf("-") != -1) {
63
return stdAlg.equalsIgnoreCase(givenAlg);
64
} else {
65
if (stdAlg.equals("SHA-1")) {
66
return (givenAlg.equalsIgnoreCase("SHA")
67
|| givenAlg.equalsIgnoreCase("SHA1"));
68
} else {
69
StringBuilder sb = new StringBuilder(givenAlg);
70
// case-insensitive check
71
if (givenAlg.regionMatches(true, 0, "SHA", 0, 3)) {
72
givenAlg = sb.insert(3, "-").toString();
73
return stdAlg.equalsIgnoreCase(givenAlg);
74
} else {
75
throw new ProviderException("Unsupported digest algorithm "
76
+ givenAlg);
77
}
78
}
79
}
80
}
81
82
private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];
83
84
private static final Hashtable<KnownOIDs, Integer> DIGEST_LENGTHS =
85
new Hashtable<KnownOIDs, Integer>();
86
static {
87
DIGEST_LENGTHS.put(KnownOIDs.SHA_1, 20);
88
DIGEST_LENGTHS.put(KnownOIDs.SHA_224, 28);
89
DIGEST_LENGTHS.put(KnownOIDs.SHA_256, 32);
90
DIGEST_LENGTHS.put(KnownOIDs.SHA_384, 48);
91
DIGEST_LENGTHS.put(KnownOIDs.SHA_512, 64);
92
DIGEST_LENGTHS.put(KnownOIDs.SHA_512$224, 28);
93
DIGEST_LENGTHS.put(KnownOIDs.SHA_512$256, 32);
94
DIGEST_LENGTHS.put(KnownOIDs.SHA3_224, 28);
95
DIGEST_LENGTHS.put(KnownOIDs.SHA3_256, 32);
96
DIGEST_LENGTHS.put(KnownOIDs.SHA3_384, 48);
97
DIGEST_LENGTHS.put(KnownOIDs.SHA3_512, 64);
98
}
99
100
// message digest implementation we use for hashing the data
101
private MessageDigest md;
102
// flag indicating whether the digest is reset
103
private boolean digestReset = true;
104
105
// private key, if initialized for signing
106
private RSAPrivateKey privKey = null;
107
// public key, if initialized for verifying
108
private RSAPublicKey pubKey = null;
109
// PSS parameters from signatures and keys respectively
110
private PSSParameterSpec sigParams = null; // required for PSS signatures
111
112
// PRNG used to generate salt bytes if none given
113
private SecureRandom random;
114
115
/**
116
* Construct a new RSAPSSSignatur with arbitrary digest algorithm
117
*/
118
public RSAPSSSignature() {
119
this.md = null;
120
}
121
122
// initialize for verification. See JCA doc
123
@Override
124
protected void engineInitVerify(PublicKey publicKey)
125
throws InvalidKeyException {
126
if (publicKey instanceof RSAPublicKey rsaPubKey) {
127
isPublicKeyValid(rsaPubKey);
128
this.pubKey = rsaPubKey;
129
this.privKey = null;
130
resetDigest();
131
} else {
132
throw new InvalidKeyException("key must be RSAPublicKey");
133
}
134
}
135
136
// initialize for signing. See JCA doc
137
@Override
138
protected void engineInitSign(PrivateKey privateKey)
139
throws InvalidKeyException {
140
engineInitSign(privateKey, null);
141
}
142
143
// initialize for signing. See JCA doc
144
@Override
145
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
146
throws InvalidKeyException {
147
if (privateKey instanceof RSAPrivateKey rsaPrivateKey) {
148
isPrivateKeyValid(rsaPrivateKey);
149
this.privKey = rsaPrivateKey;
150
this.pubKey = null;
151
this.random =
152
(random == null ? JCAUtil.getSecureRandom() : random);
153
resetDigest();
154
} else {
155
throw new InvalidKeyException("key must be RSAPrivateKey");
156
}
157
}
158
159
/**
160
* Utility method for checking the key PSS parameters against signature
161
* PSS parameters.
162
* Returns false if any of the digest/MGF algorithms and trailerField
163
* values does not match or if the salt length in key parameters is
164
* larger than the value in signature parameters.
165
*/
166
private static boolean isCompatible(AlgorithmParameterSpec keyParams,
167
PSSParameterSpec sigParams) {
168
if (keyParams == null) {
169
// key with null PSS parameters means no restriction
170
return true;
171
}
172
if (!(keyParams instanceof PSSParameterSpec)) {
173
return false;
174
}
175
// nothing to compare yet, defer the check to when sigParams is set
176
if (sigParams == null) {
177
return true;
178
}
179
PSSParameterSpec pssKeyParams = (PSSParameterSpec) keyParams;
180
// first check the salt length requirement
181
if (pssKeyParams.getSaltLength() > sigParams.getSaltLength()) {
182
return false;
183
}
184
185
// compare equality of the rest of fields based on DER encoding
186
PSSParameterSpec keyParams2 =
187
new PSSParameterSpec(pssKeyParams.getDigestAlgorithm(),
188
pssKeyParams.getMGFAlgorithm(),
189
pssKeyParams.getMGFParameters(),
190
sigParams.getSaltLength(),
191
pssKeyParams.getTrailerField());
192
PSSParameters ap = new PSSParameters();
193
// skip the JCA overhead
194
try {
195
ap.engineInit(keyParams2);
196
byte[] encoded = ap.engineGetEncoded();
197
ap.engineInit(sigParams);
198
byte[] encoded2 = ap.engineGetEncoded();
199
return Arrays.equals(encoded, encoded2);
200
} catch (Exception e) {
201
if (DEBUG) {
202
e.printStackTrace();
203
}
204
return false;
205
}
206
}
207
208
/**
209
* Validate the specified RSAPrivateKey
210
*/
211
private void isPrivateKeyValid(RSAPrivateKey prKey) throws InvalidKeyException {
212
try {
213
if (prKey instanceof RSAPrivateCrtKey crtKey) {
214
if (RSAPrivateCrtKeyImpl.checkComponents(crtKey)) {
215
RSAKeyFactory.checkRSAProviderKeyLengths(
216
crtKey.getModulus().bitLength(),
217
crtKey.getPublicExponent());
218
} else {
219
throw new InvalidKeyException(
220
"Some of the CRT-specific components are not available");
221
}
222
} else {
223
RSAKeyFactory.checkRSAProviderKeyLengths(
224
prKey.getModulus().bitLength(),
225
null);
226
}
227
} catch (InvalidKeyException ikEx) {
228
throw ikEx;
229
} catch (Exception e) {
230
throw new InvalidKeyException(
231
"Can not access private key components", e);
232
}
233
isValid(prKey);
234
}
235
236
/**
237
* Validate the specified RSAPublicKey
238
*/
239
private void isPublicKeyValid(RSAPublicKey pKey) throws InvalidKeyException {
240
try {
241
RSAKeyFactory.checkRSAProviderKeyLengths(
242
pKey.getModulus().bitLength(),
243
pKey.getPublicExponent());
244
} catch (InvalidKeyException ikEx) {
245
throw ikEx;
246
} catch (Exception e) {
247
throw new InvalidKeyException(
248
"Can not access public key components", e);
249
}
250
isValid(pKey);
251
}
252
253
/**
254
* Validate the specified RSAKey and its associated parameters against
255
* internal signature parameters.
256
*/
257
private void isValid(RSAKey rsaKey) throws InvalidKeyException {
258
AlgorithmParameterSpec keyParams = rsaKey.getParams();
259
// validate key parameters
260
if (!isCompatible(rsaKey.getParams(), this.sigParams)) {
261
throw new InvalidKeyException
262
("Key contains incompatible PSS parameter values");
263
}
264
// validate key length
265
if (this.sigParams != null) {
266
String digestAlgo = this.sigParams.getDigestAlgorithm();
267
KnownOIDs ko = KnownOIDs.findMatch(digestAlgo);
268
if (ko != null) {
269
Integer hLen = DIGEST_LENGTHS.get(ko);
270
if (hLen != null) {
271
checkKeyLength(rsaKey, hLen,
272
this.sigParams.getSaltLength());
273
} else {
274
// should never happen; checked in validateSigParams()
275
throw new ProviderException
276
("Unsupported digest algo: " + digestAlgo);
277
}
278
} else {
279
// should never happen; checked in validateSigParams()
280
throw new ProviderException
281
("Unrecognized digest algo: " + digestAlgo);
282
}
283
}
284
}
285
286
/**
287
* Validate the specified Signature PSS parameters.
288
*/
289
private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p)
290
throws InvalidAlgorithmParameterException {
291
if (p == null) {
292
throw new InvalidAlgorithmParameterException
293
("Parameters cannot be null");
294
}
295
if (!(p instanceof PSSParameterSpec)) {
296
throw new InvalidAlgorithmParameterException
297
("parameters must be type PSSParameterSpec");
298
}
299
// no need to validate again if same as current signature parameters
300
PSSParameterSpec params = (PSSParameterSpec) p;
301
if (params == this.sigParams) return params;
302
303
RSAKey key = (this.privKey == null? this.pubKey : this.privKey);
304
// check against keyParams if set
305
if (key != null) {
306
if (!isCompatible(key.getParams(), params)) {
307
throw new InvalidAlgorithmParameterException
308
("Signature parameters does not match key parameters");
309
}
310
}
311
// now sanity check the parameter values
312
if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) {
313
throw new InvalidAlgorithmParameterException("Only supports MGF1");
314
315
}
316
if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) {
317
throw new InvalidAlgorithmParameterException
318
("Only supports TrailerFieldBC(1)");
319
320
}
321
322
// check key length again
323
if (key != null) {
324
String digestAlgo = params.getDigestAlgorithm();
325
KnownOIDs ko = KnownOIDs.findMatch(digestAlgo);
326
if (ko != null) {
327
Integer hLen = DIGEST_LENGTHS.get(ko);
328
if (hLen != null) {
329
try {
330
checkKeyLength(key, hLen, params.getSaltLength());
331
} catch (InvalidKeyException e) {
332
throw new InvalidAlgorithmParameterException(e);
333
}
334
} else {
335
throw new InvalidAlgorithmParameterException
336
("Unsupported digest algo: " + digestAlgo);
337
}
338
} else {
339
throw new InvalidAlgorithmParameterException
340
("Unrecognized digest algo: " + digestAlgo);
341
}
342
}
343
return params;
344
}
345
346
/**
347
* Ensure the object is initialized with key and parameters and
348
* reset digest
349
*/
350
private void ensureInit() throws SignatureException {
351
RSAKey key = (this.privKey == null? this.pubKey : this.privKey);
352
if (key == null) {
353
throw new SignatureException("Missing key");
354
}
355
if (this.sigParams == null) {
356
// Parameters are required for signature verification
357
throw new SignatureException
358
("Parameters required for RSASSA-PSS signatures");
359
}
360
}
361
362
/**
363
* Utility method for checking key length against digest length and
364
* salt length
365
*/
366
private static void checkKeyLength(RSAKey key, int digestLen,
367
int saltLen) throws InvalidKeyException {
368
if (key != null) {
369
int keyLength = (getKeyLengthInBits(key) + 7) >> 3;
370
int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2);
371
if (keyLength < minLength) {
372
throw new InvalidKeyException
373
("Key is too short, need min " + minLength + " bytes");
374
}
375
}
376
}
377
378
/**
379
* Reset the message digest if it is not already reset.
380
*/
381
private void resetDigest() {
382
if (digestReset == false) {
383
this.md.reset();
384
digestReset = true;
385
}
386
}
387
388
/**
389
* Return the message digest value.
390
*/
391
private byte[] getDigestValue() {
392
digestReset = true;
393
return this.md.digest();
394
}
395
396
// update the signature with the plaintext data. See JCA doc
397
@Override
398
protected void engineUpdate(byte b) throws SignatureException {
399
ensureInit();
400
this.md.update(b);
401
digestReset = false;
402
}
403
404
// update the signature with the plaintext data. See JCA doc
405
@Override
406
protected void engineUpdate(byte[] b, int off, int len)
407
throws SignatureException {
408
ensureInit();
409
this.md.update(b, off, len);
410
digestReset = false;
411
}
412
413
// update the signature with the plaintext data. See JCA doc
414
@Override
415
protected void engineUpdate(ByteBuffer b) {
416
try {
417
ensureInit();
418
} catch (SignatureException se) {
419
// workaround for API bug
420
throw new RuntimeException(se.getMessage());
421
}
422
this.md.update(b);
423
digestReset = false;
424
}
425
426
// sign the data and return the signature. See JCA doc
427
@Override
428
protected byte[] engineSign() throws SignatureException {
429
ensureInit();
430
byte[] mHash = getDigestValue();
431
try {
432
byte[] encoded = encodeSignature(mHash);
433
byte[] encrypted = RSACore.rsa(encoded, privKey, true);
434
return encrypted;
435
} catch (GeneralSecurityException e) {
436
throw new SignatureException("Could not sign data", e);
437
} catch (IOException e) {
438
throw new SignatureException("Could not encode data", e);
439
}
440
}
441
442
// verify the data and return the result. See JCA doc
443
// should be reset to the state after engineInitVerify call.
444
@Override
445
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
446
ensureInit();
447
try {
448
if (sigBytes.length != RSACore.getByteLength(this.pubKey)) {
449
throw new SignatureException
450
("Signature length not correct: got "
451
+ sigBytes.length + " but was expecting "
452
+ RSACore.getByteLength(this.pubKey));
453
}
454
byte[] mHash = getDigestValue();
455
byte[] decrypted = RSACore.rsa(sigBytes, this.pubKey);
456
return decodeSignature(mHash, decrypted);
457
} catch (javax.crypto.BadPaddingException e) {
458
// occurs if the app has used the wrong RSA public key
459
// or if sigBytes is invalid
460
// return false rather than propagating the exception for
461
// compatibility/ease of use
462
return false;
463
} catch (IOException e) {
464
throw new SignatureException("Signature encoding error", e);
465
} finally {
466
resetDigest();
467
}
468
}
469
470
// return the modulus length in bits
471
private static int getKeyLengthInBits(RSAKey k) {
472
if (k != null) {
473
return k.getModulus().bitLength();
474
}
475
return -1;
476
}
477
478
/**
479
* Encode the digest 'mHash', return the to-be-signed data.
480
* Also used by the PKCS#11 provider.
481
*/
482
private byte[] encodeSignature(byte[] mHash)
483
throws IOException, DigestException {
484
AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
485
String mgfDigestAlgo;
486
if (mgfParams != null) {
487
mgfDigestAlgo =
488
((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
489
} else {
490
mgfDigestAlgo = this.md.getAlgorithm();
491
}
492
try {
493
int emBits = getKeyLengthInBits(this.privKey) - 1;
494
int emLen = (emBits + 7) >> 3;
495
int hLen = this.md.getDigestLength();
496
int dbLen = emLen - hLen - 1;
497
int sLen = this.sigParams.getSaltLength();
498
499
// maps DB into the corresponding region of EM and
500
// stores its bytes directly into EM
501
byte[] em = new byte[emLen];
502
503
// step7 and some of step8
504
em[dbLen - sLen - 1] = (byte) 1; // set DB's padding2 into EM
505
em[em.length - 1] = (byte) 0xBC; // set trailer field of EM
506
507
if (!digestReset) {
508
throw new ProviderException("Digest should be reset");
509
}
510
// step5: generates M' using padding1, mHash, and salt
511
this.md.update(EIGHT_BYTES_OF_ZEROS);
512
digestReset = false; // mark digest as it now has data
513
this.md.update(mHash);
514
if (sLen != 0) {
515
// step4: generate random salt
516
byte[] salt = new byte[sLen];
517
this.random.nextBytes(salt);
518
this.md.update(salt);
519
520
// step8: set DB's salt into EM
521
System.arraycopy(salt, 0, em, dbLen - sLen, sLen);
522
}
523
// step6: generate H using M'
524
this.md.digest(em, dbLen, hLen); // set H field of EM
525
digestReset = true;
526
527
// step7 and 8 are already covered by the code which setting up
528
// EM as above
529
530
// step9 and 10: feed H into MGF and xor with DB in EM
531
MGF1 mgf1 = new MGF1(mgfDigestAlgo);
532
mgf1.generateAndXor(em, dbLen, hLen, dbLen, em, 0);
533
534
// step11: set the leftmost (8emLen - emBits) bits of the leftmost
535
// octet to 0
536
int numZeroBits = (emLen << 3) - emBits;
537
538
if (numZeroBits != 0) {
539
byte MASK = (byte) (0xff >>> numZeroBits);
540
em[0] = (byte) (em[0] & MASK);
541
}
542
543
// step12: em should now holds maskedDB || hash h || 0xBC
544
return em;
545
} catch (NoSuchAlgorithmException e) {
546
throw new IOException(e.toString());
547
}
548
}
549
550
/**
551
* Decode the signature data as under RFC8017 sec9.1.2 EMSA-PSS-VERIFY
552
*/
553
private boolean decodeSignature(byte[] mHash, byte[] em)
554
throws IOException {
555
int hLen = mHash.length;
556
int sLen = this.sigParams.getSaltLength();
557
int emBits = getKeyLengthInBits(this.pubKey) - 1;
558
int emLen = (emBits + 7) >> 3;
559
560
// When key length is 8N+1 bits (N+1 bytes), emBits = 8N,
561
// emLen = N which is one byte shorter than em.length.
562
// Otherwise, emLen should be same as em.length
563
int emOfs = em.length - emLen;
564
if ((emOfs == 1) && (em[0] != 0)) {
565
return false;
566
}
567
568
// step3
569
if (emLen < (hLen + sLen + 2)) {
570
return false;
571
}
572
573
// step4
574
if (em[emOfs + emLen - 1] != (byte) 0xBC) {
575
return false;
576
}
577
578
// step6: check if the leftmost (8emLen - emBits) bits of the leftmost
579
// octet are 0
580
int numZeroBits = (emLen << 3) - emBits;
581
582
if (numZeroBits != 0) {
583
byte MASK = (byte) (0xff << (8 - numZeroBits));
584
if ((em[emOfs] & MASK) != 0) {
585
return false;
586
}
587
}
588
String mgfDigestAlgo;
589
AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();
590
if (mgfParams != null) {
591
mgfDigestAlgo =
592
((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
593
} else {
594
mgfDigestAlgo = this.md.getAlgorithm();
595
}
596
// step 7 and 8
597
int dbLen = emLen - hLen - 1;
598
try {
599
MGF1 mgf1 = new MGF1(mgfDigestAlgo);
600
mgf1.generateAndXor(em, emOfs + dbLen, hLen, dbLen,
601
em, emOfs);
602
} catch (NoSuchAlgorithmException nsae) {
603
throw new IOException(nsae.toString());
604
}
605
606
// step9: set the leftmost (8emLen - emBits) bits of the leftmost
607
// octet to 0
608
if (numZeroBits != 0) {
609
byte MASK = (byte) (0xff >>> numZeroBits);
610
em[emOfs] = (byte) (em[emOfs] & MASK);
611
}
612
613
// step10
614
int i = emOfs;
615
for (; i < emOfs + (dbLen - sLen - 1); i++) {
616
if (em[i] != 0) {
617
return false;
618
}
619
}
620
if (em[i] != 0x01) {
621
return false;
622
}
623
// step12 and 13
624
this.md.update(EIGHT_BYTES_OF_ZEROS);
625
digestReset = false;
626
this.md.update(mHash);
627
if (sLen > 0) {
628
this.md.update(em, emOfs + (dbLen - sLen), sLen);
629
}
630
byte[] digest2 = this.md.digest();
631
digestReset = true;
632
633
// step14
634
byte[] digestInEM = Arrays.copyOfRange(em, emOfs + dbLen,
635
emOfs + emLen - 1);
636
return MessageDigest.isEqual(digest2, digestInEM);
637
}
638
639
// set parameter, not supported. See JCA doc
640
@Deprecated
641
@Override
642
protected void engineSetParameter(String param, Object value)
643
throws InvalidParameterException {
644
throw new UnsupportedOperationException("setParameter() not supported");
645
}
646
647
@Override
648
protected void engineSetParameter(AlgorithmParameterSpec params)
649
throws InvalidAlgorithmParameterException {
650
this.sigParams = validateSigParams(params);
651
// disallow changing parameters when digest has been used
652
if (!digestReset) {
653
throw new ProviderException
654
("Cannot set parameters during operations");
655
}
656
String newHashAlg = this.sigParams.getDigestAlgorithm();
657
// re-allocate md if not yet assigned or algorithm changed
658
if ((this.md == null) ||
659
!(this.md.getAlgorithm().equalsIgnoreCase(newHashAlg))) {
660
try {
661
this.md = MessageDigest.getInstance(newHashAlg);
662
} catch (NoSuchAlgorithmException nsae) {
663
// should not happen as we pick default digest algorithm
664
throw new InvalidAlgorithmParameterException
665
("Unsupported digest algorithm " +
666
newHashAlg, nsae);
667
}
668
}
669
}
670
671
// get parameter, not supported. See JCA doc
672
@Deprecated
673
@Override
674
protected Object engineGetParameter(String param)
675
throws InvalidParameterException {
676
throw new UnsupportedOperationException("getParameter() not supported");
677
}
678
679
@Override
680
protected AlgorithmParameters engineGetParameters() {
681
AlgorithmParameters ap = null;
682
if (this.sigParams != null) {
683
try {
684
ap = AlgorithmParameters.getInstance("RSASSA-PSS");
685
ap.init(this.sigParams);
686
} catch (GeneralSecurityException gse) {
687
throw new ProviderException(gse.getMessage());
688
}
689
}
690
return ap;
691
}
692
}
693
694