/**
   * Basic Constructor - set up a calculator based on signerInfoGen with a ESSCertID calculated from
   * the signer's associated certificate using the sha1DigestCalculator.
   *
   * @param sha1DigestCalculator calculator for SHA-1 of certificate.
   * @param signerInfoGen the generator for the signer we are using.
   * @param tsaPolicy tasPolicy to send.
   * @throws IllegalArgumentException if calculator is not SHA-1 or there is no associated
   *     certificate for the signer,
   * @throws TSPException if the signer certificate cannot be processed.
   */
  public TimeStampTokenGenerator(
      DigestCalculator sha1DigestCalculator,
      final SignerInfoGenerator signerInfoGen,
      ASN1ObjectIdentifier tsaPolicy)
      throws IllegalArgumentException, TSPException {
    this.signerInfoGen = signerInfoGen;
    this.tsaPolicyOID = tsaPolicy;

    if (!sha1DigestCalculator
        .getAlgorithmIdentifier()
        .getAlgorithm()
        .equals(OIWObjectIdentifiers.idSHA1)) {
      throw new IllegalArgumentException("Digest calculator must be for SHA-1");
    }

    if (!signerInfoGen.hasAssociatedCertificate()) {
      throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate");
    }

    TSPUtil.validateCertificate(signerInfoGen.getAssociatedCertificate());

    try {
      OutputStream dOut = sha1DigestCalculator.getOutputStream();

      dOut.write(signerInfoGen.getAssociatedCertificate().getEncoded());

      dOut.close();

      final ESSCertID essCertid = new ESSCertID(sha1DigestCalculator.getDigest());

      this.signerInfoGen =
          new SignerInfoGenerator(
              signerInfoGen,
              new CMSAttributeTableGenerator() {
                public AttributeTable getAttributes(Map parameters)
                    throws CMSAttributeTableGenerationException {
                  AttributeTable table =
                      signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);

                  return table.add(
                      PKCSObjectIdentifiers.id_aa_signingCertificate,
                      new SigningCertificate(essCertid));
                }
              },
              signerInfoGen.getUnsignedAttributeTableGenerator());

    } catch (IOException e) {
      throw new TSPException("Exception processing certificate.", e);
    }
  }
  private String getSigAlgorithm(PrivateKey key, String digestOID) {
    String enc = null;

    if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "RSA";
    } else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "DSA";
    } else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm())
        || "EC".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "ECDSA";
    } else if (key instanceof GOST3410PrivateKey
        || "GOST3410".equalsIgnoreCase(key.getAlgorithm())) {
      enc = "GOST3410";
    } else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm())) {
      enc = CMSSignedGenerator.ENCRYPTION_ECGOST3410;
    }

    return TSPUtil.getDigestAlgName(digestOID) + "with" + enc;
  }
  /**
   * create with a signer with extra signed/unsigned attributes.
   *
   * @deprecated use SignerInfoGenerator constructor
   */
  public TimeStampTokenGenerator(
      PrivateKey key,
      X509Certificate cert,
      String digestOID,
      String tsaPolicyOID,
      AttributeTable signedAttr,
      AttributeTable unsignedAttr)
      throws IllegalArgumentException, TSPException {
    this.key = key;
    this.cert = cert;
    this.digestOID = digestOID;
    this.tsaPolicyOID = tsaPolicyOID;
    this.unsignedAttr = unsignedAttr;

    //
    // add the essCertid
    //
    Hashtable signedAttrs = null;

    if (signedAttr != null) {
      signedAttrs = signedAttr.toHashtable();
    } else {
      signedAttrs = new Hashtable();
    }

    TSPUtil.validateCertificate(cert);

    try {
      ESSCertID essCertid =
          new ESSCertID(MessageDigest.getInstance("SHA-1").digest(cert.getEncoded()));
      signedAttrs.put(
          PKCSObjectIdentifiers.id_aa_signingCertificate,
          new Attribute(
              PKCSObjectIdentifiers.id_aa_signingCertificate,
              new DERSet(new SigningCertificate(essCertid))));
    } catch (NoSuchAlgorithmException e) {
      throw new TSPException("Can't find a SHA-1 implementation.", e);
    } catch (CertificateEncodingException e) {
      throw new TSPException("Exception processing certificate.", e);
    }

    this.signedAttr = new AttributeTable(signedAttrs);
  }
  public TimeStampTokenGenerator(
      final SignerInfoGenerator signerInfoGen, ASN1ObjectIdentifier tsaPolicy)
      throws IllegalArgumentException, TSPException {
    this.signerInfoGen = signerInfoGen;
    this.tsaPolicyOID = tsaPolicy.getId();

    if (!signerInfoGen.hasAssociatedCertificate()) {
      throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate");
    }

    TSPUtil.validateCertificate(signerInfoGen.getAssociatedCertificate());

    try {
      final ESSCertID essCertid =
          new ESSCertID(
              MessageDigest.getInstance("SHA-1")
                  .digest(signerInfoGen.getAssociatedCertificate().getEncoded()));

      this.signerInfoGen =
          new SignerInfoGenerator(
              signerInfoGen,
              new CMSAttributeTableGenerator() {
                public AttributeTable getAttributes(Map parameters)
                    throws CMSAttributeTableGenerationException {
                  AttributeTable table =
                      signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);

                  return table.add(
                      PKCSObjectIdentifiers.id_aa_signingCertificate,
                      new SigningCertificate(essCertid));
                }
              },
              signerInfoGen.getUnsignedAttributeTableGenerator());

    } catch (NoSuchAlgorithmException e) {
      throw new TSPException("Can't find a SHA-1 implementation.", e);
    } catch (IOException e) {
      throw new TSPException("Exception processing certificate.", e);
    }
  }
  /**
   * Basic Constructor - set up a calculator based on signerInfoGen with a ESSCertID calculated from
   * the signer's associated certificate using the sha1DigestCalculator. If alternate values are
   * required for id-aa-signingCertificate they should be added to the signerInfoGen object before
   * it is passed in, otherwise a standard digest based value will be added.
   *
   * @param signerInfoGen the generator for the signer we are using.
   * @param digestCalculator calculator for to use for digest of certificate.
   * @param tsaPolicy tasPolicy to send.
   * @param isIssuerSerialIncluded should issuerSerial be included in the ESSCertIDs, true if yes,
   *     by default false.
   * @throws IllegalArgumentException if calculator is not SHA-1 or there is no associated
   *     certificate for the signer,
   * @throws TSPException if the signer certificate cannot be processed.
   */
  public TimeStampTokenGenerator(
      final SignerInfoGenerator signerInfoGen,
      DigestCalculator digestCalculator,
      ASN1ObjectIdentifier tsaPolicy,
      boolean isIssuerSerialIncluded)
      throws IllegalArgumentException, TSPException {
    this.signerInfoGen = signerInfoGen;
    this.tsaPolicyOID = tsaPolicy;

    if (!signerInfoGen.hasAssociatedCertificate()) {
      throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate");
    }

    X509CertificateHolder assocCert = signerInfoGen.getAssociatedCertificate();
    TSPUtil.validateCertificate(assocCert);

    try {
      OutputStream dOut = digestCalculator.getOutputStream();

      dOut.write(assocCert.getEncoded());

      dOut.close();

      if (digestCalculator
          .getAlgorithmIdentifier()
          .getAlgorithm()
          .equals(OIWObjectIdentifiers.idSHA1)) {
        final ESSCertID essCertid =
            new ESSCertID(
                digestCalculator.getDigest(),
                isIssuerSerialIncluded
                    ? new IssuerSerial(
                        new GeneralNames(new GeneralName(assocCert.getIssuer())),
                        assocCert.getSerialNumber())
                    : null);

        this.signerInfoGen =
            new SignerInfoGenerator(
                signerInfoGen,
                new CMSAttributeTableGenerator() {
                  public AttributeTable getAttributes(Map parameters)
                      throws CMSAttributeTableGenerationException {
                    AttributeTable table =
                        signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);

                    if (table.get(PKCSObjectIdentifiers.id_aa_signingCertificate) == null) {
                      return table.add(
                          PKCSObjectIdentifiers.id_aa_signingCertificate,
                          new SigningCertificate(essCertid));
                    }

                    return table;
                  }
                },
                signerInfoGen.getUnsignedAttributeTableGenerator());
      } else {
        AlgorithmIdentifier digAlgID =
            new AlgorithmIdentifier(digestCalculator.getAlgorithmIdentifier().getAlgorithm());
        final ESSCertIDv2 essCertid =
            new ESSCertIDv2(
                digAlgID,
                digestCalculator.getDigest(),
                isIssuerSerialIncluded
                    ? new IssuerSerial(
                        new GeneralNames(new GeneralName(assocCert.getIssuer())),
                        new ASN1Integer(assocCert.getSerialNumber()))
                    : null);

        this.signerInfoGen =
            new SignerInfoGenerator(
                signerInfoGen,
                new CMSAttributeTableGenerator() {
                  public AttributeTable getAttributes(Map parameters)
                      throws CMSAttributeTableGenerationException {
                    AttributeTable table =
                        signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);

                    if (table.get(PKCSObjectIdentifiers.id_aa_signingCertificateV2) == null) {
                      return table.add(
                          PKCSObjectIdentifiers.id_aa_signingCertificateV2,
                          new SigningCertificateV2(essCertid));
                    }

                    return table;
                  }
                },
                signerInfoGen.getUnsignedAttributeTableGenerator());
      }
    } catch (IOException e) {
      throw new TSPException("Exception processing certificate.", e);
    }
  }