Skip to content

Commit 57ab020

Browse files
committed
merge of 1982 CMS branch, relates to github #1982
1 parent 98d81fc commit 57ab020

File tree

5 files changed

+183
-11
lines changed

5 files changed

+183
-11
lines changed

pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public CMSSignedData generate(
138138
ASN1EncodableVector signerInfos = new ASN1EncodableVector();
139139

140140
digests.clear(); // clear the current preserved digest state
141-
141+
digestAlgs.addAll(extraDigestAlgorithms);
142142
//
143143
// add the precalculated SignerInfo objects.
144144
//

pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataParser.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.bouncycastle.asn1.BERTags;
2929
import org.bouncycastle.asn1.DERSet;
3030
import org.bouncycastle.asn1.DERTaggedObject;
31+
import org.bouncycastle.asn1.DLSet;
3132
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
3233
import org.bouncycastle.asn1.cms.ContentInfoParser;
3334
import org.bouncycastle.asn1.cms.SignedDataParser;
@@ -438,15 +439,15 @@ public static OutputStream replaceSigners(
438439
// digests
439440
signedData.getDigestAlgorithms().toASN1Primitive(); // skip old ones
440441

441-
ASN1EncodableVector digestAlgs = new ASN1EncodableVector();
442-
443-
for (Iterator it = signerInformationStore.getSigners().iterator(); it.hasNext();)
442+
Set<AlgorithmIdentifier> digestAlgs = new HashSet<AlgorithmIdentifier>();
443+
for (Iterator it = signerInformationStore.getSigners().iterator(); it.hasNext(); )
444444
{
445445
SignerInformation signer = (SignerInformation)it.next();
446+
CMSUtils.addDigestAlgs(digestAlgs, signer, dgstAlgFinder);
446447
digestAlgs.add(HELPER.fixDigestAlgID(signer.getDigestAlgorithmID(), dgstAlgFinder));
447448
}
448-
449-
sigGen.getRawOutputStream().write(new DERSet(digestAlgs).getEncoded());
449+
AlgorithmIdentifier[] newDigestAlgIds = (AlgorithmIdentifier[])digestAlgs.toArray(new AlgorithmIdentifier[digestAlgs.size()]);
450+
sigGen.getRawOutputStream().write(new DLSet(newDigestAlgIds).getEncoded());
450451

451452
// encap content info
452453
ContentInfoParser encapContentInfo = signedData.getEncapContentInfo();

pkix/src/main/java/org/bouncycastle/cms/CMSSignedDataStreamGenerator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ public OutputStream open(
201201
sigGen.addObject(calculateVersion(eContentType));
202202

203203
Set<AlgorithmIdentifier> digestAlgs = new HashSet<AlgorithmIdentifier>();
204+
digestAlgs.addAll(extraDigestAlgorithms);
204205

205206
//
206207
// add the precalculated SignerInfo digest algorithms.
@@ -219,10 +220,10 @@ public OutputStream open(
219220
for (Iterator it = signerGens.iterator(); it.hasNext();)
220221
{
221222
SignerInfoGenerator signerGen = (SignerInfoGenerator)it.next();
222-
223-
digestAlgs.add(signerGen.getDigestAlgorithm());
223+
digestAlgs.add(CMSSignedHelper.INSTANCE.fixDigestAlgID(signerGen.getDigestAlgorithm(), digestAlgIdFinder));
224224
}
225225

226+
226227
sigGen.getRawOutputStream().write(CMSUtils.convertToDlSet(digestAlgs).getEncoded());
227228

228229
BERSequenceGenerator eiGen = new BERSequenceGenerator(sigGen.getRawOutputStream());

pkix/src/main/java/org/bouncycastle/cms/CMSSignedGenerator.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.HashMap;
55
import java.util.HashSet;
66
import java.util.Iterator;
7+
import java.util.LinkedHashSet;
78
import java.util.List;
89
import java.util.Map;
910
import java.util.Set;
@@ -90,6 +91,8 @@ public class CMSSignedGenerator
9091

9192
protected DigestAlgorithmIdentifierFinder digestAlgIdFinder;
9293

94+
protected Set<AlgorithmIdentifier> extraDigestAlgorithms = new LinkedHashSet<AlgorithmIdentifier>();
95+
9396
/**
9497
* base constructor
9598
*/
@@ -251,4 +254,13 @@ public Map getGeneratedDigests()
251254
{
252255
return new HashMap(digests);
253256
}
257+
258+
/**
259+
* Add extra digest algorithm identifiers to the digest algorithm set in resulting SignedData object.
260+
* @param digestAlgorithmIDs a set of extra digest algorithms
261+
* */
262+
public void addDigestAlgorithms(Set<AlgorithmIdentifier> digestAlgorithmIDs)
263+
{
264+
extraDigestAlgorithms.addAll(digestAlgorithmIDs);
265+
}
254266
}

pkix/src/test/java/org/bouncycastle/cms/test/NewSignedDataStreamTest.java

Lines changed: 161 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.bouncycastle.asn1.cms.CMSAttributes;
3333
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
3434
import org.bouncycastle.asn1.ocsp.OCSPResponse;
35+
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
36+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
3537
import org.bouncycastle.cert.X509AttributeCertificateHolder;
3638
import org.bouncycastle.cert.X509CertificateHolder;
3739
import org.bouncycastle.cert.jcajce.JcaCRLStore;
@@ -209,8 +211,45 @@ private void verifySignatures(CMSSignedDataParser sp, byte[] contentDigest)
209211
assertEquals(certStore.getMatches(null).size(), sp.getCertificates().getMatches(null).size());
210212
assertEquals(crlStore.getMatches(null).size(), sp.getCRLs().getMatches(null).size());
211213
}
212-
213-
private void verifySignatures(CMSSignedDataParser sp)
214+
215+
private void verifySignatures(CMSSignedDataParser sp, byte[] contentDigest, boolean ignoreCounterSig)
216+
throws Exception
217+
{
218+
Store certStore = sp.getCertificates();
219+
Store crlStore = sp.getCRLs();
220+
SignerInformationStore signers = sp.getSignerInfos();
221+
222+
Set digestIDs = new HashSet(sp.getDigestAlgorithmIDs());
223+
224+
assertTrue(digestIDs.size() > 0);
225+
226+
Collection c = signers.getSigners();
227+
Iterator it = c.iterator();
228+
229+
while (it.hasNext())
230+
{
231+
SignerInformation signer = (SignerInformation)it.next();
232+
Collection certCollection = certStore.getMatches(signer.getSID());
233+
234+
Iterator certIt = certCollection.iterator();
235+
X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
236+
237+
assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert)));
238+
239+
digestIDs.remove(signer.getDigestAlgorithmID());
240+
241+
if (contentDigest != null)
242+
{
243+
assertTrue(MessageDigest.isEqual(contentDigest, signer.getContentDigest()));
244+
}
245+
}
246+
247+
assertTrue(digestIDs.size() > 0);
248+
assertEquals(certStore.getMatches(null).size(), sp.getCertificates().getMatches(null).size());
249+
assertEquals(crlStore.getMatches(null).size(), sp.getCRLs().getMatches(null).size());
250+
}
251+
252+
private void verifySignatures(CMSSignedDataParser sp)
214253
throws Exception
215254
{
216255
verifySignatures(sp, null);
@@ -364,7 +403,126 @@ public void testDSANoAttributes()
364403

365404
verifySignatures(sp, md.digest(TEST_MESSAGE.getBytes()));
366405
}
367-
406+
407+
public void testAddDigestAlgorithm()
408+
throws Exception
409+
{
410+
List certList = new ArrayList();
411+
List crlList = new ArrayList();
412+
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
413+
414+
certList.add(_origCert);
415+
certList.add(_signCert);
416+
417+
crlList.add(_signCrl);
418+
crlList.add(_origCrl);
419+
420+
Store certs = new JcaCertStore(certList);
421+
Store crls = new JcaCRLStore(crlList);
422+
423+
CMSSignedDataStreamGenerator gen = new CMSSignedDataStreamGenerator();
424+
425+
ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(_origKP.getPrivate());
426+
427+
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build()).build(sha1Signer, _origCert));
428+
gen.addCertificates(certs);
429+
430+
gen.addCRLs(crls);
431+
432+
Set<AlgorithmIdentifier> oids = new HashSet<AlgorithmIdentifier>();
433+
oids.add(new AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption));
434+
gen.addDigestAlgorithms(oids);
435+
436+
OutputStream sigOut = gen.open(bOut);
437+
438+
sigOut.write(TEST_MESSAGE.getBytes());
439+
440+
sigOut.close();
441+
442+
checkSigParseable(bOut.toByteArray());
443+
444+
CMSSignedDataParser sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(),
445+
new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray());
446+
447+
sp.getSignedContent().drain();
448+
449+
//
450+
// compute expected content digest
451+
//
452+
MessageDigest md1 = MessageDigest.getInstance("SHA1", BC);
453+
verifySignatures(sp, md1.digest(TEST_MESSAGE.getBytes()), true);
454+
455+
456+
//
457+
// try using existing signer
458+
//
459+
gen = new CMSSignedDataStreamGenerator();
460+
461+
gen.addSigners(sp.getSignerInfos());
462+
463+
gen.addCertificates(sp.getCertificates());
464+
gen.addCRLs(sp.getCRLs());
465+
466+
bOut.reset();
467+
468+
sigOut = gen.open(bOut, true);
469+
470+
sigOut.write(TEST_MESSAGE.getBytes());
471+
472+
sigOut.close();
473+
474+
verifyEncodedData(bOut);
475+
sp = new CMSSignedDataParser(new JcaDigestCalculatorProviderBuilder().setProvider(BC).build(),
476+
new CMSTypedStream(new ByteArrayInputStream(TEST_MESSAGE.getBytes())), bOut.toByteArray());
477+
478+
sp.getSignedContent().drain();
479+
480+
//
481+
// look for the CRLs
482+
//
483+
Collection col = sp.getCRLs().getMatches(null);
484+
485+
assertEquals(2, col.size());
486+
assertTrue(col.contains(new JcaX509CRLHolder(_signCrl)));
487+
assertTrue(col.contains(new JcaX509CRLHolder(_origCrl)));
488+
}
489+
490+
private void verifySignatures2(CMSSignedDataParser sp, byte[] contentDigest1, byte[] contentDigest2)
491+
throws Exception
492+
{
493+
Store certStore = sp.getCertificates();
494+
Store crlStore = sp.getCRLs();
495+
SignerInformationStore signers = sp.getSignerInfos();
496+
497+
Set digestIDs = new HashSet(sp.getDigestAlgorithmIDs());
498+
499+
assertTrue(digestIDs.size() > 0);
500+
501+
Collection c = signers.getSigners();
502+
Iterator it = c.iterator();
503+
504+
while (it.hasNext())
505+
{
506+
SignerInformation signer = (SignerInformation)it.next();
507+
Collection certCollection = certStore.getMatches(signer.getSID());
508+
509+
Iterator certIt = certCollection.iterator();
510+
X509CertificateHolder cert = (X509CertificateHolder)certIt.next();
511+
512+
assertEquals(true, signer.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider(BC).build(cert)));
513+
514+
digestIDs.remove(signer.getDigestAlgorithmID());
515+
516+
assertTrue(MessageDigest.isEqual(contentDigest1, signer.getContentDigest()) ||
517+
MessageDigest.isEqual(contentDigest2, signer.getContentDigest()));
518+
519+
}
520+
521+
assertTrue(digestIDs.size() == 0);
522+
assertEquals(certStore.getMatches(null).size(), sp.getCertificates().getMatches(null).size());
523+
assertEquals(crlStore.getMatches(null).size(), sp.getCRLs().getMatches(null).size());
524+
}
525+
368526
public void testSHA1WithRSA()
369527
throws Exception
370528
{

0 commit comments

Comments
 (0)