title: Detached signature in CMSSignedData verifies using Bouncy Castle but NOT using java.security.Signature
body: <p>I have been traversing the web for some days now to find the cause of this but without success. </p>
  
  <p><strong>I am doing this</strong>:</p>
  
  <ul>
  <li>generating fresh certificates (signer cert and his parent)</li>
  <li>creating signature using CMSSignedDataGenerator (<strong>bouncycastle 1.45</strong>)</li>
  <li>verifying it by java.security.Signature -> FAILS</li>
  <li>verifying it by BC classes -> SUCCESS</li>
  </ul>
  
  <p><strong>Facts I found out</strong>:</p>
  
  <ul>
  <li>Creation and verification of signature uses same algorithm - SHA1withRSA.</li>
  <li>No exception is thrown anywhere in the process.</li>
  </ul>
  
  <p><strong>Questions</strong>:</p>
  
  <ul>
  <li>Any idea what I am doing wrong?</li>
  </ul>
  
  <p><strong>Ideas to consider</strong>:</p>
  
  <p>I think that the cause lies in the generation of the signature but I suppose I am doing it according to docs. Or - the validation process may expect some kind of different structure like PKCS1 while the generator provides PKCS7. Nothing actually tells me what to search next.</p>
  
  <p>Here is a piece of code which should illustrate the problem and output (after providing your own certificates and a private key):</p>
  
  <pre><code>import org.bouncycastle.cms.*;
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  
  import java.security.PrivateKey;
  import java.security.Security;
  import java.security.Signature;
  import java.security.cert.CertStore;
  import java.security.cert.CollectionCertStoreParameters;
  import java.security.cert.X509Certificate;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.List;
  
  import static org.bouncycastle.cms.CMSSignedGenerator.DIGEST_SHA1;
  import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
  
  
  public final class VerifyCMSSignedData {
  
      private static final byte[] DATA_TO_BE_SIGNED = "data".getBytes();
      private static final String SHA_1_WITH_RSA = "SHA1WithRSA";
      private static final boolean DATA_NOT_ATTACHED = false;
      private static final String COLLECTION_STORE_TYPE = "Collection";
  
      private static X509Certificate signer;
      private static PrivateKey signerPrivateKey;
      private static X509Certificate parent;
  
      private VerifyCMSSignedData() {
      }
  
      public static void main(String[] args) throws Exception {
          Security.addProvider(new BouncyCastleProvider());
  
          setUpCertificates();
  
          shouldVerifySignature();
      }
  
      public static void shouldVerifySignature() throws Exception {
          CMSSignedData signature = createSignature();
  
          shouldVerifyBySignature(signature.getEncoded());
  
          shouldVerifyByBC(signature.getEncoded());
      }
  
      private static void shouldVerifyByBC(byte[] signatureBytes) {
          boolean verified = false;
  
          try {
              CMSSignedData cms = new CMSSignedData(new CMSProcessableByteArray(DATA_TO_BE_SIGNED), signatureBytes);
              CertStore certStore = cms.getCertificatesAndCRLs(COLLECTION_STORE_TYPE, PROVIDER_NAME);
              SignerInformationStore signers = cms.getSignerInfos();
              Collection c = signers.getSigners();
              for (Object aC : c) {
                  SignerInformation signer = (SignerInformation) aC;
                  Collection certCollection = certStore.getCertificates(signer.getSID());
                  Iterator certIt = certCollection.iterator();
                  X509Certificate cert = (X509Certificate) certIt.next();
                  verified = signer.verify(cert, PROVIDER_NAME);
              }
          } catch (Exception e) {
              e.printStackTrace();
              verified = false;
          }
  
          System.out.println(verified ? "VERIFIED BY BC" : "! Not verified through BC !");
      }
  
      private static void shouldVerifyBySignature(byte[] signatureBytes) throws Exception {
          Signature signatureVerifier = Signature.getInstance(SHA_1_WITH_RSA, PROVIDER_NAME);
          signatureVerifier.initVerify(signer.getPublicKey());
          signatureVerifier.update(DATA_TO_BE_SIGNED);
          boolean verified = signatureVerifier.verify(signatureBytes);
  
          System.out.println(verified ? "VERIFIED BY SIGNATURE CLASS" : "! Not verified by Signature class !");
      }
  
      private static CMSSignedData createSignature() throws Exception {
          CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
  
          gen.addSigner(signerPrivateKey, signer, DIGEST_SHA1);
  
          List&lt;X509Certificate&gt; allCerts = new ArrayList&lt;&gt;();
          if (parent != null) {
              allCerts.add(parent);
          }
          allCerts.add(signer);
  
          CertStore store = CertStore.getInstance(
                  COLLECTION_STORE_TYPE,
                  new CollectionCertStoreParameters(allCerts),
                  PROVIDER_NAME
          );
  
          gen.addCertificatesAndCRLs(store);
  
          return gen.generate(new CMSProcessableByteArray(DATA_TO_BE_SIGNED), DATA_NOT_ATTACHED, PROVIDER_NAME);
      }
  
      private static void setUpCertificates() throws Exception {
          // TODO setup your certificates here
      }
  }
  </code></pre>
  
  <p><strong>Output</strong>:</p>
  
  <blockquote>
    <p>! Not verified by Signature class !</p>
    
    <p>VERIFIED BY BC</p>
    
    <p>Process finished with exit code 0</p>
  </blockquote>