Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java
67773 views
1
/*
2
* Copyright (c) 1996, 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.pkcs;
27
28
import java.io.OutputStream;
29
import java.io.IOException;
30
import java.math.BigInteger;
31
import java.security.cert.CertPathValidatorException;
32
import java.security.cert.CertificateException;
33
import java.security.cert.CertificateFactory;
34
import java.security.cert.CertPath;
35
import java.security.cert.X509Certificate;
36
import java.security.*;
37
import java.security.spec.PSSParameterSpec;
38
import java.util.ArrayList;
39
import java.util.Collections;
40
import java.util.Date;
41
import java.util.HashMap;
42
import java.util.HashSet;
43
import java.util.Map;
44
import java.util.Set;
45
46
import sun.security.provider.SHAKE256;
47
import sun.security.timestamp.TimestampToken;
48
import sun.security.util.*;
49
import sun.security.x509.AlgorithmId;
50
import sun.security.x509.X500Name;
51
import sun.security.x509.KeyUsageExtension;
52
53
/**
54
* A SignerInfo, as defined in PKCS#7's signedData type.
55
*
56
* @author Benjamin Renaud
57
*/
58
public class SignerInfo implements DerEncoder {
59
60
private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
61
DisabledAlgorithmConstraints.jarConstraints();
62
63
BigInteger version;
64
X500Name issuerName;
65
BigInteger certificateSerialNumber;
66
AlgorithmId digestAlgorithmId;
67
AlgorithmId digestEncryptionAlgorithmId;
68
byte[] encryptedDigest;
69
Timestamp timestamp;
70
private boolean hasTimestamp = true;
71
private static final Debug debug = Debug.getInstance("jar");
72
73
PKCS9Attributes authenticatedAttributes;
74
PKCS9Attributes unauthenticatedAttributes;
75
76
/**
77
* A map containing the algorithms in this SignerInfo. This is used to
78
* avoid checking algorithms to see if they are disabled more than once.
79
* The key is the AlgorithmId of the algorithm, and the value is the name of
80
* the field or attribute.
81
*/
82
private Map<AlgorithmId, String> algorithms = new HashMap<>();
83
84
public SignerInfo(X500Name issuerName,
85
BigInteger serial,
86
AlgorithmId digestAlgorithmId,
87
AlgorithmId digestEncryptionAlgorithmId,
88
byte[] encryptedDigest) {
89
this(issuerName, serial, digestAlgorithmId, null,
90
digestEncryptionAlgorithmId, encryptedDigest, null);
91
}
92
93
public SignerInfo(X500Name issuerName,
94
BigInteger serial,
95
AlgorithmId digestAlgorithmId,
96
PKCS9Attributes authenticatedAttributes,
97
AlgorithmId digestEncryptionAlgorithmId,
98
byte[] encryptedDigest,
99
PKCS9Attributes unauthenticatedAttributes) {
100
this.version = BigInteger.ONE;
101
this.issuerName = issuerName;
102
this.certificateSerialNumber = serial;
103
this.digestAlgorithmId = digestAlgorithmId;
104
this.authenticatedAttributes = authenticatedAttributes;
105
this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId;
106
this.encryptedDigest = encryptedDigest;
107
this.unauthenticatedAttributes = unauthenticatedAttributes;
108
}
109
110
/**
111
* Parses a PKCS#7 signer info.
112
*/
113
public SignerInfo(DerInputStream derin)
114
throws IOException, ParsingException
115
{
116
this(derin, false);
117
}
118
119
/**
120
* Parses a PKCS#7 signer info.
121
*
122
* <p>This constructor is used only for backwards compatibility with
123
* PKCS#7 blocks that were generated using JDK1.1.x.
124
*
125
* @param derin the ASN.1 encoding of the signer info.
126
* @param oldStyle flag indicating whether or not the given signer info
127
* is encoded according to JDK1.1.x.
128
*/
129
public SignerInfo(DerInputStream derin, boolean oldStyle)
130
throws IOException, ParsingException
131
{
132
// version
133
version = derin.getBigInteger();
134
135
// issuerAndSerialNumber
136
DerValue[] issuerAndSerialNumber = derin.getSequence(2);
137
if (issuerAndSerialNumber.length != 2) {
138
throw new ParsingException("Invalid length for IssuerAndSerialNumber");
139
}
140
byte[] issuerBytes = issuerAndSerialNumber[0].toByteArray();
141
issuerName = new X500Name(new DerValue(DerValue.tag_Sequence,
142
issuerBytes));
143
certificateSerialNumber = issuerAndSerialNumber[1].getBigInteger();
144
145
// digestAlgorithmId
146
DerValue tmp = derin.getDerValue();
147
148
digestAlgorithmId = AlgorithmId.parse(tmp);
149
150
// authenticatedAttributes
151
if (oldStyle) {
152
// In JDK1.1.x, the authenticatedAttributes are always present,
153
// encoded as an empty Set (Set of length zero)
154
derin.getSet(0);
155
} else {
156
// check if set of auth attributes (implicit tag) is provided
157
// (auth attributes are OPTIONAL)
158
if ((byte)(derin.peekByte()) == (byte)0xA0) {
159
authenticatedAttributes = new PKCS9Attributes(derin);
160
}
161
}
162
163
// digestEncryptionAlgorithmId - little RSA naming scheme -
164
// signature == encryption...
165
tmp = derin.getDerValue();
166
167
digestEncryptionAlgorithmId = AlgorithmId.parse(tmp);
168
169
// encryptedDigest
170
encryptedDigest = derin.getOctetString();
171
172
// unauthenticatedAttributes
173
if (oldStyle) {
174
// In JDK1.1.x, the unauthenticatedAttributes are always present,
175
// encoded as an empty Set (Set of length zero)
176
derin.getSet(0);
177
} else {
178
// check if set of unauth attributes (implicit tag) is provided
179
// (unauth attributes are OPTIONAL)
180
if (derin.available() != 0
181
&& (byte)(derin.peekByte()) == (byte)0xA1) {
182
unauthenticatedAttributes =
183
new PKCS9Attributes(derin, true);// ignore unsupported attrs
184
}
185
}
186
187
// all done
188
if (derin.available() != 0) {
189
throw new ParsingException("extra data at the end");
190
}
191
192
// verify CMSAlgorithmProtection
193
checkCMSAlgorithmProtection();
194
}
195
196
// CMSAlgorithmProtection verification as described in RFC 6211
197
private void checkCMSAlgorithmProtection() throws IOException {
198
if (authenticatedAttributes == null) {
199
return;
200
}
201
PKCS9Attribute ap = authenticatedAttributes.getAttribute(
202
PKCS9Attribute.CMS_ALGORITHM_PROTECTION_OID);
203
if (ap == null) {
204
return;
205
}
206
DerValue dv = new DerValue((byte[])ap.getValue());
207
DerInputStream data = dv.data();
208
AlgorithmId d = AlgorithmId.parse(data.getDerValue());
209
DerValue ds = data.getDerValue();
210
if (data.available() > 0) {
211
throw new IOException("Unknown field in CMSAlgorithmProtection");
212
}
213
if (!ds.isContextSpecific((byte)1)) {
214
throw new IOException("No signature algorithm in CMSAlgorithmProtection");
215
}
216
AlgorithmId s = AlgorithmId.parse(ds.withTag(DerValue.tag_Sequence));
217
if (!s.equals(digestEncryptionAlgorithmId)
218
|| !d.equals(digestAlgorithmId)) {
219
throw new IOException("CMSAlgorithmProtection check failed");
220
}
221
}
222
223
public void encode(DerOutputStream out) throws IOException {
224
225
derEncode(out);
226
}
227
228
/**
229
* DER encode this object onto an output stream.
230
* Implements the {@code DerEncoder} interface.
231
*
232
* @param out
233
* the output stream on which to write the DER encoding.
234
*
235
* @exception IOException on encoding error.
236
*/
237
public void derEncode(OutputStream out) throws IOException {
238
DerOutputStream seq = new DerOutputStream();
239
seq.putInteger(version);
240
DerOutputStream issuerAndSerialNumber = new DerOutputStream();
241
issuerName.encode(issuerAndSerialNumber);
242
issuerAndSerialNumber.putInteger(certificateSerialNumber);
243
seq.write(DerValue.tag_Sequence, issuerAndSerialNumber);
244
245
digestAlgorithmId.encode(seq);
246
247
// encode authenticated attributes if there are any
248
if (authenticatedAttributes != null)
249
authenticatedAttributes.encode((byte)0xA0, seq);
250
251
digestEncryptionAlgorithmId.encode(seq);
252
253
seq.putOctetString(encryptedDigest);
254
255
// encode unauthenticated attributes if there are any
256
if (unauthenticatedAttributes != null)
257
unauthenticatedAttributes.encode((byte)0xA1, seq);
258
259
DerOutputStream tmp = new DerOutputStream();
260
tmp.write(DerValue.tag_Sequence, seq);
261
262
out.write(tmp.toByteArray());
263
}
264
265
/*
266
* Returns the (user) certificate pertaining to this SignerInfo.
267
*/
268
public X509Certificate getCertificate(PKCS7 block)
269
throws IOException
270
{
271
return block.getCertificate(certificateSerialNumber, issuerName);
272
}
273
274
/*
275
* Returns the certificate chain pertaining to this SignerInfo.
276
*/
277
public ArrayList<X509Certificate> getCertificateChain(PKCS7 block)
278
throws IOException
279
{
280
X509Certificate userCert;
281
userCert = block.getCertificate(certificateSerialNumber, issuerName);
282
if (userCert == null)
283
return null;
284
285
ArrayList<X509Certificate> certList = new ArrayList<>();
286
certList.add(userCert);
287
288
X509Certificate[] pkcsCerts = block.getCertificates();
289
if (pkcsCerts == null
290
|| userCert.getSubjectX500Principal().equals(userCert.getIssuerX500Principal())) {
291
return certList;
292
}
293
294
Principal issuer = userCert.getIssuerX500Principal();
295
int start = 0;
296
while (true) {
297
boolean match = false;
298
int i = start;
299
while (i < pkcsCerts.length) {
300
if (issuer.equals(pkcsCerts[i].getSubjectX500Principal())) {
301
// next cert in chain found
302
certList.add(pkcsCerts[i]);
303
// if selected cert is self-signed, we're done
304
// constructing the chain
305
if (pkcsCerts[i].getSubjectX500Principal().equals(
306
pkcsCerts[i].getIssuerX500Principal())) {
307
start = pkcsCerts.length;
308
} else {
309
issuer = pkcsCerts[i].getIssuerX500Principal();
310
X509Certificate tmpCert = pkcsCerts[start];
311
pkcsCerts[start] = pkcsCerts[i];
312
pkcsCerts[i] = tmpCert;
313
start++;
314
}
315
match = true;
316
break;
317
} else {
318
i++;
319
}
320
}
321
if (!match)
322
break;
323
}
324
325
return certList;
326
}
327
328
/* Returns null if verify fails, this signerInfo if
329
verify succeeds. */
330
SignerInfo verify(PKCS7 block, byte[] data)
331
throws NoSuchAlgorithmException, SignatureException {
332
333
try {
334
Timestamp timestamp = null;
335
try {
336
timestamp = getTimestamp();
337
} catch (Exception e) {
338
// Log exception and continue. This allows for the case
339
// where, if there are no other errors, the code is
340
// signed but w/o a timestamp.
341
if (debug != null) {
342
debug.println("Unexpected exception while getting" +
343
" timestamp: " + e);
344
}
345
}
346
347
ContentInfo content = block.getContentInfo();
348
if (data == null) {
349
data = content.getContentBytes();
350
}
351
352
String digestAlgName = digestAlgorithmId.getName();
353
algorithms.put(digestAlgorithmId, "SignerInfo digestAlgorithm field");
354
355
byte[] dataSigned;
356
357
// if there are authenticate attributes, get the message
358
// digest and compare it with the digest of data
359
if (authenticatedAttributes == null) {
360
dataSigned = data;
361
} else {
362
363
// first, check content type
364
ObjectIdentifier contentType = (ObjectIdentifier)
365
authenticatedAttributes.getAttributeValue(
366
PKCS9Attribute.CONTENT_TYPE_OID);
367
if (contentType == null ||
368
!contentType.equals(content.contentType))
369
return null; // contentType does not match, bad SignerInfo
370
371
// now, check message digest
372
byte[] messageDigest = (byte[])
373
authenticatedAttributes.getAttributeValue(
374
PKCS9Attribute.MESSAGE_DIGEST_OID);
375
376
if (messageDigest == null) // fail if there is no message digest
377
return null;
378
379
byte[] computedMessageDigest;
380
if (digestAlgName.equals("SHAKE256")
381
|| digestAlgName.equals("SHAKE256-LEN")) {
382
if (digestAlgName.equals("SHAKE256-LEN")) {
383
// RFC8419: for EdDSA in CMS, the id-shake256-len
384
// algorithm id must contain parameter value 512
385
// encoded as a positive integer value
386
byte[] params = digestAlgorithmId.getEncodedParams();
387
if (params == null) {
388
throw new SignatureException(
389
"id-shake256-len oid missing length");
390
}
391
int v = new DerValue(params).getInteger();
392
if (v != 512) {
393
throw new SignatureException(
394
"Unsupported id-shake256-" + v);
395
}
396
}
397
var md = new SHAKE256(64);
398
md.update(data, 0, data.length);
399
computedMessageDigest = md.digest();
400
} else {
401
MessageDigest md = MessageDigest.getInstance(digestAlgName);
402
computedMessageDigest = md.digest(data);
403
}
404
405
if (!MessageDigest.isEqual(messageDigest, computedMessageDigest)) {
406
return null;
407
}
408
409
// message digest attribute matched
410
// digest of original data
411
412
// the data actually signed is the DER encoding of
413
// the authenticated attributes (tagged with
414
// the "SET OF" tag, not 0xA0).
415
dataSigned = authenticatedAttributes.getDerEncoding();
416
}
417
418
// put together digest algorithm and encryption algorithm
419
// to form signing algorithm. See makeSigAlg for details.
420
String sigAlgName = makeSigAlg(
421
digestAlgorithmId,
422
digestEncryptionAlgorithmId,
423
authenticatedAttributes == null);
424
425
KnownOIDs oid = KnownOIDs.findMatch(sigAlgName);
426
if (oid != null) {
427
AlgorithmId sigAlgId =
428
new AlgorithmId(ObjectIdentifier.of(oid),
429
digestEncryptionAlgorithmId.getParameters());
430
algorithms.put(sigAlgId,
431
"SignerInfo digestEncryptionAlgorithm field");
432
}
433
434
X509Certificate cert = getCertificate(block);
435
if (cert == null) {
436
return null;
437
}
438
PublicKey key = cert.getPublicKey();
439
440
if (cert.hasUnsupportedCriticalExtension()) {
441
throw new SignatureException("Certificate has unsupported "
442
+ "critical extension(s)");
443
}
444
445
// Make sure that if the usage of the key in the certificate is
446
// restricted, it can be used for digital signatures.
447
// XXX We may want to check for additional extensions in the
448
// future.
449
boolean[] keyUsageBits = cert.getKeyUsage();
450
if (keyUsageBits != null) {
451
KeyUsageExtension keyUsage;
452
try {
453
// We don't care whether or not this extension was marked
454
// critical in the certificate.
455
// We're interested only in its value (i.e., the bits set)
456
// and treat the extension as critical.
457
keyUsage = new KeyUsageExtension(keyUsageBits);
458
} catch (IOException ioe) {
459
throw new SignatureException("Failed to parse keyUsage "
460
+ "extension");
461
}
462
463
boolean digSigAllowed
464
= keyUsage.get(KeyUsageExtension.DIGITAL_SIGNATURE);
465
466
boolean nonRepuAllowed
467
= keyUsage.get(KeyUsageExtension.NON_REPUDIATION);
468
469
if (!digSigAllowed && !nonRepuAllowed) {
470
throw new SignatureException("Key usage restricted: "
471
+ "cannot be used for "
472
+ "digital signatures");
473
}
474
}
475
476
Signature sig = Signature.getInstance(sigAlgName);
477
478
AlgorithmParameters ap =
479
digestEncryptionAlgorithmId.getParameters();
480
try {
481
SignatureUtil.initVerifyWithParam(sig, key,
482
SignatureUtil.getParamSpec(sigAlgName, ap));
483
} catch (ProviderException | InvalidAlgorithmParameterException |
484
InvalidKeyException e) {
485
throw new SignatureException(e.getMessage(), e);
486
}
487
488
sig.update(dataSigned);
489
if (sig.verify(encryptedDigest)) {
490
return this;
491
}
492
} catch (IOException e) {
493
throw new SignatureException("Error verifying signature", e);
494
}
495
return null;
496
}
497
498
/**
499
* Derives the signature algorithm name from the digest algorithm
500
* and the encryption algorithm inside a PKCS7 SignerInfo.
501
*
502
* The digest algorithm is in the form "DIG", and the encryption
503
* algorithm can be in any of the 3 forms:
504
*
505
* 1. Old style key algorithm like RSA, DSA, EC, this method returns
506
* DIGwithKEY.
507
* 2. New style signature algorithm in the form of HASHwithKEY, this
508
* method returns DIGwithKEY. Please note this is not HASHwithKEY.
509
* 3. Modern signature algorithm like RSASSA-PSS and EdDSA, this method
510
* returns the signature algorithm itself but ensures digAlgId is
511
* compatible with the algorithm as described in RFC 4056 and 8419.
512
*
513
* @param digAlgId the digest algorithm
514
* @param encAlgId the encryption algorithm
515
* @param directSign whether the signature is calculated on the content
516
* directly. This makes difference for Ed448.
517
*/
518
public static String makeSigAlg(AlgorithmId digAlgId, AlgorithmId encAlgId,
519
boolean directSign) throws NoSuchAlgorithmException {
520
String encAlg = encAlgId.getName();
521
switch (encAlg) {
522
case "RSASSA-PSS":
523
PSSParameterSpec spec = (PSSParameterSpec)
524
SignatureUtil.getParamSpec(encAlg, encAlgId.getParameters());
525
/*
526
* RFC 4056 section 3 for Signed-data:
527
* signatureAlgorithm MUST contain id-RSASSA-PSS. The algorithm
528
* parameters field MUST contain RSASSA-PSS-params.
529
*/
530
if (spec == null) {
531
throw new NoSuchAlgorithmException("Missing PSSParameterSpec for RSASSA-PSS algorithm");
532
}
533
534
if (!AlgorithmId.get(spec.getDigestAlgorithm()).equals(digAlgId)) {
535
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
536
}
537
return encAlg;
538
case "Ed25519":
539
if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.sha512)) {
540
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
541
}
542
return encAlg;
543
case "Ed448":
544
if (directSign) {
545
if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.shake256)) {
546
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
547
}
548
} else {
549
if (!digAlgId.equals(SignatureUtil.EdDSADigestAlgHolder.shake256$512)) {
550
throw new NoSuchAlgorithmException("Incompatible digest algorithm");
551
}
552
}
553
return encAlg;
554
default:
555
String digAlg = digAlgId.getName();
556
String keyAlg = SignatureUtil.extractKeyAlgFromDwithE(encAlg);
557
if (keyAlg == null) {
558
// The encAlg used to be only the key alg
559
keyAlg = encAlg;
560
}
561
if (digAlg.startsWith("SHA-")) {
562
digAlg = "SHA" + digAlg.substring(4);
563
}
564
if (keyAlg.equals("EC")) keyAlg = "ECDSA";
565
return digAlg + "with" + keyAlg;
566
}
567
}
568
569
/* Verify the content of the pkcs7 block. */
570
SignerInfo verify(PKCS7 block)
571
throws NoSuchAlgorithmException, SignatureException {
572
return verify(block, null);
573
}
574
575
public BigInteger getVersion() {
576
return version;
577
}
578
579
public X500Name getIssuerName() {
580
return issuerName;
581
}
582
583
public BigInteger getCertificateSerialNumber() {
584
return certificateSerialNumber;
585
}
586
587
public AlgorithmId getDigestAlgorithmId() {
588
return digestAlgorithmId;
589
}
590
591
public PKCS9Attributes getAuthenticatedAttributes() {
592
return authenticatedAttributes;
593
}
594
595
public AlgorithmId getDigestEncryptionAlgorithmId() {
596
return digestEncryptionAlgorithmId;
597
}
598
599
public byte[] getEncryptedDigest() {
600
return encryptedDigest;
601
}
602
603
public PKCS9Attributes getUnauthenticatedAttributes() {
604
return unauthenticatedAttributes;
605
}
606
607
/**
608
* Returns the timestamp PKCS7 data unverified.
609
* @return a PKCS7 object
610
*/
611
public PKCS7 getTsToken() throws IOException {
612
if (unauthenticatedAttributes == null) {
613
return null;
614
}
615
PKCS9Attribute tsTokenAttr =
616
unauthenticatedAttributes.getAttribute(
617
PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
618
if (tsTokenAttr == null) {
619
return null;
620
}
621
return new PKCS7((byte[])tsTokenAttr.getValue());
622
}
623
624
/*
625
* Extracts a timestamp from a PKCS7 SignerInfo.
626
*
627
* Examines the signer's unsigned attributes for a
628
* {@code signatureTimestampToken} attribute. If present,
629
* then it is parsed to extract the date and time at which the
630
* timestamp was generated.
631
*
632
* @param info A signer information element of a PKCS 7 block.
633
*
634
* @return A timestamp token or null if none is present.
635
* @throws IOException if an error is encountered while parsing the
636
* PKCS7 data.
637
* @throws NoSuchAlgorithmException if an error is encountered while
638
* verifying the PKCS7 object.
639
* @throws SignatureException if an error is encountered while
640
* verifying the PKCS7 object.
641
* @throws CertificateException if an error is encountered while generating
642
* the TSA's certpath.
643
*/
644
public Timestamp getTimestamp()
645
throws IOException, NoSuchAlgorithmException, SignatureException,
646
CertificateException
647
{
648
if (timestamp != null || !hasTimestamp)
649
return timestamp;
650
651
PKCS7 tsToken = getTsToken();
652
if (tsToken == null) {
653
hasTimestamp = false;
654
return null;
655
}
656
657
// Extract the content (an encoded timestamp token info)
658
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
659
// Extract the signer (the Timestamping Authority)
660
// while verifying the content
661
SignerInfo[] tsa = tsToken.verify(encTsTokenInfo);
662
if (tsa == null || tsa.length == 0) {
663
throw new SignatureException("Unable to verify timestamp");
664
}
665
// Expect only one signer
666
ArrayList<X509Certificate> chain = tsa[0].getCertificateChain(tsToken);
667
CertificateFactory cf = CertificateFactory.getInstance("X.509");
668
CertPath tsaChain = cf.generateCertPath(chain);
669
// Create a timestamp token info object
670
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
671
// Check that the signature timestamp applies to this signature
672
verifyTimestamp(tsTokenInfo);
673
algorithms.putAll(tsa[0].algorithms);
674
// Create a timestamp object
675
timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain);
676
return timestamp;
677
}
678
679
/*
680
* Check that the signature timestamp applies to this signature.
681
* Match the hash present in the signature timestamp token against the hash
682
* of this signature.
683
*/
684
private void verifyTimestamp(TimestampToken token)
685
throws NoSuchAlgorithmException, SignatureException {
686
687
AlgorithmId digestAlgId = token.getHashAlgorithm();
688
algorithms.put(digestAlgId, "TimestampToken digestAlgorithm field");
689
690
MessageDigest md = MessageDigest.getInstance(digestAlgId.getName());
691
692
if (!MessageDigest.isEqual(token.getHashedMessage(),
693
md.digest(encryptedDigest))) {
694
695
throw new SignatureException("Signature timestamp (#" +
696
token.getSerialNumber() + ") generated on " + token.getDate() +
697
" is inapplicable");
698
}
699
700
if (debug != null) {
701
debug.println();
702
debug.println("Detected signature timestamp (#" +
703
token.getSerialNumber() + ") generated on " + token.getDate());
704
debug.println();
705
}
706
}
707
708
public String toString() {
709
HexDumpEncoder hexDump = new HexDumpEncoder();
710
711
String out = "";
712
713
out += "Signer Info for (issuer): " + issuerName + "\n";
714
out += "\tversion: " + Debug.toHexString(version) + "\n";
715
out += "\tcertificateSerialNumber: " +
716
Debug.toHexString(certificateSerialNumber) + "\n";
717
out += "\tdigestAlgorithmId: " + digestAlgorithmId + "\n";
718
if (authenticatedAttributes != null) {
719
out += "\tauthenticatedAttributes: " + authenticatedAttributes +
720
"\n";
721
}
722
out += "\tdigestEncryptionAlgorithmId: " + digestEncryptionAlgorithmId +
723
"\n";
724
725
out += "\tencryptedDigest: " + "\n" +
726
hexDump.encodeBuffer(encryptedDigest) + "\n";
727
if (unauthenticatedAttributes != null) {
728
out += "\tunauthenticatedAttributes: " +
729
unauthenticatedAttributes + "\n";
730
}
731
return out;
732
}
733
734
/**
735
* Verify all of the algorithms in the array of SignerInfos against the
736
* constraints in the jdk.jar.disabledAlgorithms security property.
737
*
738
* @param infos array of SignerInfos
739
* @param params constraint parameters
740
* @param name the name of the signer's PKCS7 file
741
* @return a set of algorithms that passed the checks and are not disabled
742
*/
743
public static Set<String> verifyAlgorithms(SignerInfo[] infos,
744
JarConstraintsParameters params, String name) throws SignatureException {
745
Map<AlgorithmId, String> algorithms = new HashMap<>();
746
for (SignerInfo info : infos) {
747
algorithms.putAll(info.algorithms);
748
}
749
750
Set<String> enabledAlgorithms = new HashSet<>();
751
try {
752
for (Map.Entry<AlgorithmId, String> algorithm : algorithms.entrySet()) {
753
params.setExtendedExceptionMsg(name, algorithm.getValue());
754
AlgorithmId algId = algorithm.getKey();
755
JAR_DISABLED_CHECK.permits(algId.getName(),
756
algId.getParameters(), params);
757
enabledAlgorithms.add(algId.getName());
758
}
759
} catch (CertPathValidatorException e) {
760
throw new SignatureException(e);
761
}
762
return enabledAlgorithms;
763
}
764
}
765
766