/**
   * Encrypts an entity using the provided certificates.
   *
   * @param entity The entity that will be encrypted.
   * @param encryptingCertificate The public certificates that will be used to encrypt the message.
   * @return A MimeEntity containing the encrypted part.
   */
  public MimeEntity encrypt(MimeEntity entity, Collection<X509Certificate> encryptingCertificates) {
    if (entity == null) {
      throw new IllegalArgumentException();
    }

    MimeBodyPart partToEncrypt = entity;
    MimeBodyPart encryptedPart = this.encrypt(partToEncrypt, encryptingCertificates);
    MimeEntity encryptedEntity = null;

    try {
      byte[] encBytes = EntitySerializer.Default.serializeToBytes(encryptedPart);
      ByteArrayInputStream inStream =
          new ByteArrayInputStream(EntitySerializer.Default.serializeToBytes(encryptedPart));
      encryptedEntity = new MimeEntity(inStream);

      if (LOGGER.isDebugEnabled()) {
        writePostEncypt(encBytes);
      }

      encryptedEntity.setHeader(
          MimeStandard.ContentTypeHeader, SMIMEStandard.EncryptedContentTypeHeaderValue);

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

    return encryptedEntity;
  }
  /**
   * Decrypts an entity with the provided certificate's private key.
   *
   * @param encryptedEntity The entity that will be decrypted.
   * @param decryptingCertificate The certificate whose private key will be used to decrypt the
   *     message.
   * @return A MimeEntity containing the decrypted part.
   */
  public MimeEntity decrypt(MimeEntity encryptedEntity, X509CertificateEx decryptingCertificate) {
    if (encryptedEntity == null || decryptingCertificate == null) {
      throw new IllegalArgumentException();
    }

    if (!decryptingCertificate.hasPrivateKey()) {
      throw new IllegalArgumentException("Certificate has no private key");
    }

    encryptedEntity.verifyContentType(SMIMEStandard.EncryptedContentTypeHeaderValue);
    encryptedEntity.verifyTransferEncoding(MimeStandard.TransferEncodingBase64);

    Collection<X509CertificateEx> certs = new ArrayList<X509CertificateEx>();
    certs.add(decryptingCertificate);

    MimeEntity retVal = this.decrypt(encryptedEntity, certs);

    //
    // And turn the decrypted bytes back into an entity
    //
    return retVal;
  }
  /**
   * 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;
  }