private void verifyParserAlgorithm(String algorithmOid, MimeBodyPart msg) throws Exception {
    SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();

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

    //
    // generate a MimeBodyPart object which encapsulates the content
    // we want encrypted.
    //

    MimeBodyPart mp =
        gen.generate(
            msg,
            new JceCMSContentEncryptorBuilder(new ASN1ObjectIdentifier(algorithmOid))
                .setProvider(BC)
                .build());
    SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(mp);
    RecipientId recId = getRecipientId(_reciCert);

    RecipientInformationStore recipients = m.getRecipientInfos();
    RecipientInformation recipient = recipients.get(recId);

    MimeBodyPart res =
        SMIMEUtil.toMimeBodyPart(
            recipient.getContent(
                new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)));

    verifyMessageBytes(msg, res);
  }
Пример #2
0
  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 testTwoRecipients() throws Exception {
    MimeBodyPart _msg = SMIMETestUtil.makeMimeBodyPart("WallaWallaWashington");

    SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();

    gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider(BC));
    gen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(_reciCert2).setProvider(BC));

    //
    // generate a MimeBodyPart object which encapsulates the content
    // we want encrypted.
    //
    MimeBodyPart mp =
        gen.generate(
            _msg,
            new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC, 40).setProvider(BC).build());

    SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(mp);

    RecipientId recId = getRecipientId(_reciCert2);

    RecipientInformationStore recipients = m.getRecipientInfos();
    RecipientInformation recipient = recipients.get(recId);

    FileBackedMimeBodyPart res =
        SMIMEUtil.toMimeBodyPart(
            recipient.getContentStream(
                new JceKeyTransEnvelopedRecipient(_reciKP2.getPrivate()).setProvider(BC)));

    verifyMessageBytes(_msg, res);

    m = new SMIMEEnvelopedParser(mp);

    res.dispose();

    recId = getRecipientId(_reciCert);

    recipients = m.getRecipientInfos();
    recipient = recipients.get(recId);

    res =
        SMIMEUtil.toMimeBodyPart(
            recipient.getContentStream(
                new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)));

    verifyMessageBytes(_msg, res);

    res.dispose();
  }
  public void testAES256() throws Exception {
    MimeMessage message = loadMessage("test256.message");

    SMIMEEnveloped env = new SMIMEEnveloped(message);

    RecipientInformationStore store = env.getRecipientInfos();

    RecipientInformation recipInfo = store.get(new JceKeyTransRecipientId(loadCert("cert.pem")));

    assertNotNull(recipInfo);

    byte[] content = recipInfo.getContent(new JceKeyTransEnvelopedRecipient(loadKey("key.pem")));

    assertTrue(org.bouncycastle.util.Arrays.areEqual(testMessage, content));
  }
  public void testSubKeyId() throws Exception {
    MimeBodyPart msg = SMIMETestUtil.makeMimeBodyPart("WallaWallaWashington");

    SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();

    //
    // create a subject key id - this has to be done the same way as
    // it is done in the certificate associated with the private key
    //
    MessageDigest dig = MessageDigest.getInstance("SHA1", BC);
    dig.update(
        SubjectPublicKeyInfo.getInstance(_reciCert.getPublicKey().getEncoded())
            .getPublicKeyData()
            .getBytes());

    gen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(dig.digest(), _reciCert.getPublicKey())
            .setProvider(BC));

    //
    // generate a MimeBodyPart object which encapsulates the content
    // we want encrypted.
    //

    MimeBodyPart mp =
        gen.generate(
            msg,
            new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider(BC).build());

    SMIMEEnveloped m = new SMIMEEnveloped(mp);

    dig.update(
        SubjectPublicKeyInfo.getInstance(_reciCert.getPublicKey().getEncoded())
            .getPublicKeyData()
            .getBytes());

    RecipientId recId = new KeyTransRecipientId(dig.digest());

    RecipientInformationStore recipients = m.getRecipientInfos();
    RecipientInformation recipient = recipients.get(recId);

    MimeBodyPart res =
        SMIMEUtil.toMimeBodyPart(
            recipient.getContent(
                new JceKeyTransEnvelopedRecipient(_reciKP.getPrivate()).setProvider(BC)));

    verifyMessageBytes(msg, res);
  }
Пример #6
0
 /**
  * Gets the content from a recipient.
  *
  * @param recipientInfo
  * @param certificateKey
  * @param certificateKeyProvider
  * @return
  * @throws CMSException
  */
 public static byte[] getContent(
     RecipientInformation recipientInfo, PrivateKey certificateKey, String certificateKeyProvider)
     throws CMSException {
   Recipient jceKeyTransRecipient =
       new JceKeyTransEnvelopedRecipient(certificateKey).setProvider(certificateKeyProvider);
   return recipientInfo.getContent(jceKeyTransRecipient);
 }
Пример #7
0
  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");
    }
  }
Пример #8
0
  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");
    }
  }
Пример #9
0
  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()));
    }
  }
Пример #10
0
  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");
    }
  }
Пример #11
0
  /**
   * Decrypts an entity with the provided certificates' private key.
   *
   * @param encryptedEntity The entity that will be decrypted.
   * @param decryptingCertificate The certificates whose private keys will be used to decrypt the
   *     message.
   * @return A MimeEntity containing the decrypted part.
   */
  public MimeEntity decrypt(
      MimeEntity encryptedEntity, Collection<X509CertificateEx> decryptingCertificates) {
    if (decryptingCertificates == null || decryptingCertificates.size() == 0) {
      throw new IllegalArgumentException();
    }

    MimeEntity retEntity = null;
    try {
      if (LOGGER.isDebugEnabled()) {
        byte[] encryptedContent = encryptedEntity.getContentAsBytes();
        writePreDecrypt(encryptedContent);
      }

      SMIMEEnveloped m = new SMIMEEnveloped(encryptedEntity);

      X509CertificateEx decryptCert = decryptingCertificates.iterator().next();

      RecipientId recId = generateRecipientSelector(decryptCert);

      RecipientInformationStore recipients = m.getRecipientInfos();
      RecipientInformation recipient = recipients.get(recId);

      byte[] decryptedPayload =
          recipient.getContent(decryptCert.getPrivateKey(), CryptoExtensions.getJCEProviderName());

      if (LOGGER.isDebugEnabled()) {
        writePostDecrypt(decryptedPayload);
      }

      ByteArrayInputStream inStream = new ByteArrayInputStream(decryptedPayload);

      retEntity = new MimeEntity(inStream);

    } catch (MessagingException e) {
      throw new MimeException(MimeError.InvalidMimeEntity, e);
    } catch (Exception e) {
      throw new MimeException(MimeError.Unexpected, e);
    }

    return retEntity;
  }
Пример #12
0
  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");
    }
  }
Пример #13
0
  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()));
    }
  }
  /**
   * Prepares everything to decrypt the document.
   *
   * <p>If {@link #decryptDocument(PDDocument, DecryptionMaterial)} is used, this method is called
   * from there. Only if decryption of single objects is needed this should be called instead.
   *
   * @param encDictionary encryption dictionary, can be retrieved via {@link
   *     PDDocument#getEncryptionDictionary()}
   * @param documentIDArray document id which is returned via {@link COSDocument#getDocumentID()}
   *     (not used by this handler)
   * @param decryptionMaterial Information used to decrypt the document.
   * @throws IOException If there is an error accessing data.
   * @throws CryptographyException If there is an error with decryption.
   */
  public void prepareForDecryption(
      PDEncryptionDictionary encDictionary,
      COSArray documentIDArray,
      DecryptionMaterial decryptionMaterial)
      throws CryptographyException, IOException {

    if (encDictionary.getLength() != 0) {
      this.keyLength = encDictionary.getLength();
    }

    if (!(decryptionMaterial instanceof PublicKeyDecryptionMaterial)) {
      throw new CryptographyException(
          "Provided decryption material is not compatible with the document");
    }

    PublicKeyDecryptionMaterial material = (PublicKeyDecryptionMaterial) decryptionMaterial;

    try {
      boolean foundRecipient = false;

      // the decrypted content of the enveloped data that match
      // the certificate in the decryption material provided
      byte[] envelopedData = null;

      // the bytes of each recipient in the recipients array
      byte[][] recipientFieldsBytes = new byte[encDictionary.getRecipientsLength()][];

      int recipientFieldsLength = 0;

      for (int i = 0; i < encDictionary.getRecipientsLength(); i++) {
        COSString recipientFieldString = encDictionary.getRecipientStringAt(i);
        byte[] recipientBytes = recipientFieldString.getBytes();
        CMSEnvelopedData data = new CMSEnvelopedData(recipientBytes);
        Iterator recipCertificatesIt = data.getRecipientInfos().getRecipients().iterator();
        while (recipCertificatesIt.hasNext()) {
          RecipientInformation ri = (RecipientInformation) recipCertificatesIt.next();
          // Impl: if a matching certificate was previously found it is an error,
          // here we just don't care about it
          if (ri.getRID().match(material.getCertificate()) && !foundRecipient) {
            foundRecipient = true;
            envelopedData = ri.getContent(material.getPrivateKey(), "BC");
          }
        }
        recipientFieldsBytes[i] = recipientBytes;
        recipientFieldsLength += recipientBytes.length;
      }
      if (!foundRecipient || envelopedData == null) {
        throw new CryptographyException("The certificate matches no recipient entry");
      }
      if (envelopedData.length != 24) {
        throw new CryptographyException("The enveloped data does not contain 24 bytes");
      }
      // now envelopedData contains:
      // - the 20 bytes seed
      // - the 4 bytes of permission for the current user

      byte[] accessBytes = new byte[4];
      System.arraycopy(envelopedData, 20, accessBytes, 0, 4);

      currentAccessPermission = new AccessPermission(accessBytes);
      currentAccessPermission.setReadOnly();

      // what we will put in the SHA1 = the seed + each byte contained in the recipients array
      byte[] sha1Input = new byte[recipientFieldsLength + 20];

      // put the seed in the sha1 input
      System.arraycopy(envelopedData, 0, sha1Input, 0, 20);

      // put each bytes of the recipients array in the sha1 input
      int sha1InputOffset = 20;
      for (int i = 0; i < recipientFieldsBytes.length; i++) {
        System.arraycopy(
            recipientFieldsBytes[i], 0, sha1Input, sha1InputOffset, recipientFieldsBytes[i].length);
        sha1InputOffset += recipientFieldsBytes[i].length;
      }

      MessageDigest md = MessageDigest.getInstance("SHA-1");
      byte[] mdResult = md.digest(sha1Input);

      // we have the encryption key ...
      encryptionKey = new byte[this.keyLength / 8];
      System.arraycopy(mdResult, 0, encryptionKey, 0, this.keyLength / 8);
    } catch (CMSException e) {
      throw new CryptographyException(e);
    } catch (KeyStoreException e) {
      throw new CryptographyException(e);
    } catch (NoSuchProviderException e) {
      throw new CryptographyException(e);
    } catch (NoSuchAlgorithmException e) {
      throw new CryptographyException(e);
    }
  }