private void tryKekAlgorithm(SecretKey kek, ASN1ObjectIdentifier algOid, byte[] encodedParameters)
      throws NoSuchAlgorithmException, NoSuchProviderException, CMSException,
          OperatorCreationException, IOException {
    byte[] data = "Eric H. Echidna".getBytes();

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    byte[] kekId = new byte[] {1, 2, 3, 4, 5};

    adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC));

    AlgorithmParameters algParams =
        AlgorithmParameters.getInstance(CMSAlgorithm.DES_EDE3_CBC.getId(), "BC");

    algParams.init(encodedParameters);

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC)
                .setAlgorithmParameters(algParams)
                .setProvider(BC)
                .build());

    RecipientInformationStore recipients = ad.getRecipientInfos();

    Collection c = recipients.getRecipients();
    Iterator it = c.iterator();

    assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC);
    assertEquals(
        ad.getMacAlgorithm().getParameters(), ASN1Primitive.fromByteArray(encodedParameters));

    if (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId());

      byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    } else {
      fail("no recipient found");
    }
  }
  private void checkData(byte[] data, SecretKey kek, CMSAuthenticatedData ad) throws CMSException {
    RecipientInformationStore recipients = ad.getRecipientInfos();

    Collection c = recipients.getRecipients();
    Iterator it = c.iterator();

    if (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
      assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest()));
    } else {
      fail("no recipient found");
    }
  }
  public void testOriginatorInfo() throws Exception {
    byte[] data = "Eric H. Echidna".getBytes();
    ASN1ObjectIdentifier macAlg = CMSAlgorithm.DES_EDE3_CBC;

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded());

    adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate());

    adGen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build());

    assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert));

    RecipientInformationStore recipients = ad.getRecipientInfos();

    assertEquals(ad.getMacAlgOID(), macAlg.getId());

    Collection c = recipients.getRecipients();

    assertEquals(1, c.size());

    Iterator it = c.iterator();

    while (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());

      byte[] recData =
          recipient.getContent(
              new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    }
  }
  public void testECKeyAgree() throws Exception {
    byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    JceKeyAgreeRecipientInfoGenerator recipientGenerator =
        new JceKeyAgreeRecipientInfoGenerator(
                CMSAlgorithm.ECDH_SHA1KDF,
                _origEcKP.getPrivate(),
                _origEcKP.getPublic(),
                CMSAlgorithm.AES128_WRAP)
            .setProvider(BC);

    recipientGenerator.addRecipient(_reciEcCert);

    adGen.addRecipientInfoGenerator(recipientGenerator);

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());

    RecipientInformationStore recipients = ad.getRecipientInfos();

    assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC);

    Collection c = recipients.getRecipients();
    Iterator it = c.iterator();

    if (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      byte[] recData =
          recipient.getContent(
              new JceKeyAgreeAuthenticatedRecipient(_reciEcKP.getPrivate()).setProvider(BC));
      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    } else {
      fail("no recipient found");
    }
  }
  private void tryKekAlgorithmWithDigest(SecretKey kek, ASN1ObjectIdentifier algOid)
      throws NoSuchAlgorithmException, NoSuchProviderException, CMSException,
          OperatorCreationException {
    byte[] data = "Eric H. Echidna".getBytes();

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
    DigestCalculatorProvider calcProvider =
        new JcaDigestCalculatorProviderBuilder().setProvider(BC).build();

    byte[] kekId = new byte[] {1, 2, 3, 4, 5};

    adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build(),
            calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)));

    RecipientInformationStore recipients = ad.getRecipientInfos();

    Collection c = recipients.getRecipients();
    Iterator it = c.iterator();

    assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC);

    if (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), algOid.getId());

      byte[] recData = recipient.getContent(new JceKEKAuthenticatedRecipient(kek).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
      assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest()));
    } else {
      fail("no recipient found");
    }
  }
  private void tryKeyTransWithDigest(ASN1ObjectIdentifier macAlg) throws Exception {
    byte[] data = "Eric H. Echidna".getBytes();

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
    DigestCalculatorProvider calcProvider =
        new JcaDigestCalculatorProviderBuilder().setProvider(BC).build();

    adGen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(macAlg).setProvider(BC).build(),
            calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)));

    RecipientInformationStore recipients = ad.getRecipientInfos();

    assertEquals(ad.getMacAlgOID(), macAlg.getId());

    Collection c = recipients.getRecipients();

    assertEquals(1, c.size());

    Iterator it = c.iterator();

    while (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());

      byte[] recData =
          recipient.getContent(
              new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
      assertTrue(Arrays.equals(ad.getContentDigest(), recipient.getContentDigest()));
    }
  }
  private void passwordTest(String algorithm) throws Exception {
    byte[] data = Hex.decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    adGen.addRecipientInfoGenerator(
        new JcePasswordRecipientInfoGenerator(
                new ASN1ObjectIdentifier(algorithm), "password".toCharArray())
            .setProvider(BC)
            .setSaltAndIterationCount(new byte[20], 5));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());

    RecipientInformationStore recipients = ad.getRecipientInfos();

    assertEquals(ad.getMacAlgOID(), CMSAuthenticatedDataGenerator.DES_EDE3_CBC);

    Collection c = recipients.getRecipients();
    Iterator it = c.iterator();

    if (it.hasNext()) {
      PasswordRecipientInformation recipient = (PasswordRecipientInformation) it.next();

      PasswordRecipient pbeRep =
          new JcePasswordAuthenticatedRecipient("password".toCharArray()).setProvider(BC);

      byte[] recData = recipient.getContent(pbeRep);

      assertTrue(Arrays.equals(data, recData));
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    } else {
      fail("no recipient found");
    }
  }
  public void testAES256CCM() throws Exception {
    byte[] data = "Eric H. Echidna".getBytes();
    ASN1ObjectIdentifier macAlg = CMSAlgorithm.AES256_CCM;
    AlgorithmParameters algParams = AlgorithmParameters.getInstance("CCM", BC);

    algParams.init(new CCMParameters(Hex.decode("000102030405060708090a0b"), 16).getEncoded());

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();

    X509CertificateHolder origCert = new X509CertificateHolder(_origCert.getEncoded());

    adGen.setOriginatorInfo(new OriginatorInfoGenerator(origCert).generate());

    adGen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(macAlg)
                .setAlgorithmParameters(algParams)
                .setProvider(BC)
                .build());

    assertTrue(ad.getOriginatorInfo().getCertificates().getMatches(null).contains(origCert));

    RecipientInformationStore recipients = ad.getRecipientInfos();

    assertEquals(ad.getMacAlgOID(), macAlg.getId());

    Collection c = recipients.getRecipients();

    assertEquals(1, c.size());

    Iterator it = c.iterator();

    while (it.hasNext()) {
      RecipientInformation recipient = (RecipientInformation) it.next();

      assertEquals(recipient.getKeyEncryptionAlgOID(), PKCSObjectIdentifiers.rsaEncryption.getId());

      byte[] recData =
          recipient.getContent(
              new JceKeyTransAuthenticatedRecipient(_reciKP.getPrivate()).setProvider(BC));

      assertTrue(Arrays.equals(data, recData));
      assertEquals(16, ad.getMac().length);
      assertTrue(Arrays.equals(ad.getMac(), recipient.getMac()));
    }
  }
  public void testCMSAlgorithmProtection() throws Exception {
    byte[] data = "Eric H. Echidna".getBytes();

    CMSAuthenticatedDataGenerator adGen = new CMSAuthenticatedDataGenerator();
    DigestCalculatorProvider calcProvider =
        new JcaDigestCalculatorProviderBuilder().setProvider(BC).build();

    byte[] kekId = new byte[] {1, 2, 3, 4, 5};
    SecretKey kek = CMSTestUtil.makeDesede192Key();

    adGen.addRecipientInfoGenerator(new JceKEKRecipientInfoGenerator(kekId, kek).setProvider(BC));

    CMSAuthenticatedData ad =
        adGen.generate(
            new CMSProcessableByteArray(data),
            new JceCMSMacCalculatorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build(),
            calcProvider.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1)));

    checkData(data, kek, ad);

    ContentInfo adInfo = ad.toASN1Structure();
    AuthenticatedData iAd =
        AuthenticatedData.getInstance(adInfo.getContent().toASN1Primitive().getEncoded());

    try {
      new CMSAuthenticatedData(
          new ContentInfo(
              CMSObjectIdentifiers.authenticatedData,
              new AuthenticatedData(
                  iAd.getOriginatorInfo(),
                  iAd.getRecipientInfos(),
                  iAd.getMacAlgorithm(),
                  new AlgorithmIdentifier(TeleTrusTObjectIdentifiers.ripemd160, DERNull.INSTANCE),
                  iAd.getEncapsulatedContentInfo(),
                  iAd.getAuthAttrs(),
                  iAd.getMac(),
                  iAd.getUnauthAttrs())),
          calcProvider);
    } catch (CMSException e) {
      Assert.assertEquals(
          e.getMessage(), "CMS Algorithm Identifier Protection check failed for digestAlgorithm");
    }

    AlgorithmIdentifier newDigAlgId =
        new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
    Assert.assertFalse(iAd.getDigestAlgorithm().equals(newDigAlgId));
    checkData(
        data,
        kek,
        new CMSAuthenticatedData(
            new ContentInfo(
                CMSObjectIdentifiers.authenticatedData,
                new AuthenticatedData(
                    iAd.getOriginatorInfo(),
                    iAd.getRecipientInfos(),
                    iAd.getMacAlgorithm(),
                    newDigAlgId,
                    iAd.getEncapsulatedContentInfo(),
                    iAd.getAuthAttrs(),
                    iAd.getMac(),
                    iAd.getUnauthAttrs())),
            calcProvider));

    try {
      new CMSAuthenticatedData(
          new ContentInfo(
              CMSObjectIdentifiers.authenticatedData,
              new AuthenticatedData(
                  iAd.getOriginatorInfo(),
                  iAd.getRecipientInfos(),
                  new AlgorithmIdentifier(CMSAlgorithm.AES192_CBC),
                  iAd.getDigestAlgorithm(),
                  iAd.getEncapsulatedContentInfo(),
                  iAd.getAuthAttrs(),
                  iAd.getMac(),
                  iAd.getUnauthAttrs())),
          calcProvider);
    } catch (CMSException e) {
      Assert.assertEquals(
          e.getMessage(), "CMS Algorithm Identifier Protection check failed for macAlgorithm");
    }

    try {
      AlgorithmIdentifier newMacAlgId = new AlgorithmIdentifier(CMSAlgorithm.DES_EDE3_CBC);
      Assert.assertFalse(iAd.getMacAlgorithm().equals(newMacAlgId));
      new CMSAuthenticatedData(
          new ContentInfo(
              CMSObjectIdentifiers.authenticatedData,
              new AuthenticatedData(
                  iAd.getOriginatorInfo(),
                  iAd.getRecipientInfos(),
                  newMacAlgId,
                  iAd.getDigestAlgorithm(),
                  iAd.getEncapsulatedContentInfo(),
                  iAd.getAuthAttrs(),
                  iAd.getMac(),
                  iAd.getUnauthAttrs())),
          calcProvider);
    } catch (CMSException e) {
      Assert.assertEquals(
          e.getMessage(), "CMS Algorithm Identifier Protection check failed for macAlgorithm");
    }
  }