Package net.sf.jsignpdf

Source Code of net.sf.jsignpdf.SignerLogic

package net.sf.jsignpdf;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.Proxy;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import net.sf.jsignpdf.crl.CRLInfo;
import net.sf.jsignpdf.types.HashAlgorithm;
import net.sf.jsignpdf.utils.FontUtils;
import net.sf.jsignpdf.utils.KeyStoreUtils;
import net.sf.jsignpdf.utils.ResourceProvider;
import net.sf.jsignpdf.utils.StringUtils;

import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.AcroFields;
import com.lowagie.text.pdf.OcspClientBouncyCastle;
import com.lowagie.text.pdf.PdfDate;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfPKCS7;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSignature;
import com.lowagie.text.pdf.PdfSignatureAppearance;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfString;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.TSAClientBouncyCastle;

/**
* Main logic of signer application. It uses iText to create signature in PDF.
*
* @author Josef Cacek
*/
public class SignerLogic implements Runnable {

  protected final static ResourceProvider res = ResourceProvider.getInstance();

  private BasicSignerOptions options;

  /**
   * Constructor with all necessary parameters.
   *
   * @param anOptions
   *            options of signer
   */
  public SignerLogic(final BasicSignerOptions anOptions) {
    options = anOptions;
  }

  /*
   * (non-Javadoc)
   *
   * @see java.lang.Runnable#run()
   */
  @SuppressWarnings("unchecked")
  public void run() {
    if (options == null) {
      throw new NullPointerException("Options has to be filled.");
    }
    final String outFile = options.getOutFileX();
    if (!validateInOutFiles(options.getInFile(), outFile)) {
      options.log("console.skippingSigning");
      return;
    }

    Exception tmpResult = null;
    FileOutputStream fout = null;
    try {
      final PrivateKeyInfo pkInfo = KeyStoreUtils.getPkInfo(options);
      final PrivateKey key = pkInfo.getKey();
      final Certificate[] chain = pkInfo.getChain();
      options.log("console.createPdfReader", options.getInFile());
      PdfReader reader;
      try {
        // try to read without password
        reader = new PdfReader(options.getInFile());
      } catch (Exception e) {
        try {
          reader = new PdfReader(options.getInFile(), new byte[0]);
        } catch (Exception e2) {
          reader = new PdfReader(options.getInFile(), options.getPdfOwnerPwdStr().getBytes());
        }
      }

      options.log("console.createOutPdf", outFile);
      fout = new FileOutputStream(outFile);

      final HashAlgorithm hashAlgorithm = options.getHashAlgorithmX();

      options.log("console.createSignature");
      char tmpPdfVersion = '\0'; // default version - the same as input
      if (reader.getPdfVersion() < hashAlgorithm.getPdfVersion()) {
        tmpPdfVersion = hashAlgorithm.getPdfVersion();
        options.log("console.updateVersion", new String[] { String.valueOf(reader.getPdfVersion()),
            String.valueOf(tmpPdfVersion) });
      }
      final PdfStamper stp = PdfStamper.createSignature(reader, fout, tmpPdfVersion, null, options.isAppendX());
      if (!options.isAppendX()) {
        // we are not in append mode, let's remove existing signatures
        // (otherwise we're getting to troubles)
        final AcroFields acroFields = stp.getAcroFields();
        final List<String> sigNames = acroFields.getSignatureNames();
        for (String sigName : sigNames) {
          acroFields.removeField(sigName);
        }
      }
      if (options.isEncryptedX()) {
        options.log("console.setEncryption");
        final int tmpRight = options.getRightPrinting().getRight()
            | (options.isRightCopy() ? PdfWriter.ALLOW_COPY : 0)
            | (options.isRightAssembly() ? PdfWriter.ALLOW_ASSEMBLY : 0)
            | (options.isRightFillIn() ? PdfWriter.ALLOW_FILL_IN : 0)
            | (options.isRightScreanReaders() ? PdfWriter.ALLOW_SCREENREADERS : 0)
            | (options.isRightModifyAnnotations() ? PdfWriter.ALLOW_MODIFY_ANNOTATIONS : 0)
            | (options.isRightModifyContents() ? PdfWriter.ALLOW_MODIFY_CONTENTS : 0);
        stp.setEncryption(true, options.getPdfUserPwdStr(), options.getPdfOwnerPwdStr(), tmpRight);
      }

      final PdfSignatureAppearance sap = stp.getSignatureAppearance();
      sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
      if (!StringUtils.isEmpty(options.getReason())) {
        options.log("console.setReason", options.getReason());
        sap.setReason(options.getReason());
      }
      if (!StringUtils.isEmpty(options.getLocation())) {
        options.log("console.setLocation", options.getLocation());
        sap.setLocation(options.getLocation());
      }
      if (!StringUtils.isEmpty(options.getContact())) {
        options.log("console.setContact", options.getContact());
        sap.setContact(options.getContact());
      }
      options.log("console.setCertificationLevel");
      sap.setCertificationLevel(options.getCertLevelX().getLevel());

      if (options.isVisible()) {
        // visible signature is enabled
        options.log("console.configureVisible");
        options.log("console.setAcro6Layers");
        sap.setAcro6Layers(true);

        final String tmpImgPath = options.getImgPath();
        if (tmpImgPath != null) {
          options.log("console.createImage", tmpImgPath);
          final Image img = Image.getInstance(tmpImgPath);
          options.log("console.setSignatureGraphic");
          sap.setSignatureGraphic(img);
        }
        final String tmpBgImgPath = options.getBgImgPath();
        if (tmpBgImgPath != null) {
          options.log("console.createImage", tmpBgImgPath);
          final Image img = Image.getInstance(tmpBgImgPath);
          options.log("console.setImage");
          sap.setImage(img);
        }
        options.log("console.setImageScale");
        sap.setImageScale(options.getBgImgScale());
        options.log("console.setL2Text");
        if (options.getL2Text() != null) {
          sap.setLayer2Text(options.getL2Text());
        } else {
          final StringBuilder buf = new StringBuilder();
          buf.append(res.get("default.l2text.signedBy")).append(" ");
          buf.append(PdfPKCS7.getSubjectFields((X509Certificate) chain[0]).getField("CN")).append('\n');
          final SimpleDateFormat sd = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
          buf.append(res.get("default.l2text.date")).append(" ").append(
              sd.format(sap.getSignDate().getTime()));
          if (StringUtils.hasLength(options.getReason()))
            buf.append('\n').append(res.get("default.l2text.reason")).append(" ").append(
                options.getReason());
          if (StringUtils.hasLength(options.getLocation()))
            buf.append('\n').append(res.get("default.l2text.location")).append(" ").append(
                options.getLocation());
          sap.setLayer2Text(buf.toString());
          ;
        }
        if (FontUtils.getL2BaseFont() != null) {
          sap.setLayer2Font(new Font(FontUtils.getL2BaseFont(), options.getL2TextFontSize()));
        }
        options.log("console.setL4Text");
        sap.setLayer4Text(options.getL4Text());
        options.log("console.setRender");
        sap.setRender(options.getRenderMode().getRender());
        options.log("console.setVisibleSignature");
        sap.setVisibleSignature(new Rectangle(options.getPositionLLX(), options.getPositionLLY(), options
            .getPositionURX(), options.getPositionURY()), options.getPage(), null);
      }

      options.log("console.processing");
      final PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
      dic.setReason(sap.getReason());
      dic.setLocation(sap.getLocation());
      dic.setContact(sap.getContact());
      dic.setDate(new PdfDate(sap.getSignDate()));
      sap.setCryptoDictionary(dic);

      final Proxy tmpProxy = options.createProxy();

      final CRLInfo crlInfo = new CRLInfo(options, chain);

      // CRLs are stored twice in PDF c.f.
      // PdfPKCS7.getAuthenticatedAttributeBytes
      final int contentEstimated = (int) (Constants.DEFVAL_SIG_SIZE + 2L * crlInfo.getByteCount());
      HashMap exc = new HashMap();
      exc.put(PdfName.CONTENTS, new Integer(contentEstimated * 2 + 2));
      sap.preClose(exc);

      PdfPKCS7 sgn = new PdfPKCS7(key, chain, crlInfo.getCrls(), hashAlgorithm.getAlgorithmName(), null, false);
      InputStream data = sap.getRangeStream();
      final MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm.getAlgorithmName());
      byte buf[] = new byte[8192];
      int n;
      while ((n = data.read(buf)) > 0) {
        messageDigest.update(buf, 0, n);
      }
      byte hash[] = messageDigest.digest();
      Calendar cal = Calendar.getInstance();
      byte[] ocsp = null;
      if (options.isOcspEnabledX() && chain.length >= 2) {
        options.log("console.getOCSPURL");
        String url = PdfPKCS7.getOCSPURL((X509Certificate) chain[0]);
        if (url != null && url.length() > 0) {
          options.log("console.readingOCSP");
          final OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle((X509Certificate) chain[0],
              (X509Certificate) chain[1], url);
          ocspClient.setProxy(tmpProxy);
          ocsp = ocspClient.getEncoded();
        }
      }
      byte sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, ocsp);
      sgn.update(sh, 0, sh.length);

      TSAClientBouncyCastle tsc = null;
      if (options.isTimestampX() && !StringUtils.isEmpty(options.getTsaUrl())) {
        options.log("console.creatingTsaClient");
        tsc = new TSAClientBouncyCastle(options.getTsaUrl(), StringUtils.emptyNull(options.getTsaUser()),
            StringUtils.emptyNull(options.getTsaPasswd()));
        tsc.setProxy(tmpProxy);
        final String policyOid = options.getTsaPolicy();
        if (StringUtils.hasLength(policyOid)) {
          options.log("console.settingTsaPolicy", policyOid);
          tsc.setPolicy(policyOid);
        }
      }
      byte[] encodedSig = sgn.getEncodedPKCS7(hash, cal, tsc, ocsp);

      if (contentEstimated + 2 < encodedSig.length) {
        System.err.println("SigSize - contentEstimated=" + contentEstimated + ", sigLen=" + encodedSig.length);
        throw new Exception("Not enough space");
      }

      byte[] paddedSig = new byte[contentEstimated];
      System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);

      PdfDictionary dic2 = new PdfDictionary();
      dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
      options.log("console.closeStream");
      sap.close(dic2);
      fout.close();

    } catch (Exception e) {
      options.log("console.exception");
      e.printStackTrace(options.getPrintWriter());
      tmpResult = e;
    } catch (OutOfMemoryError e) {
      e.printStackTrace(options.getPrintWriter());
      options.log("console.memoryError");
    } finally {
      if (fout != null) {
        try {
          fout.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    options.log("console.finished." + (tmpResult == null ? "ok" : "error"));
    options.fireSignerFinishedEvent(tmpResult);
  }

  /**
   * Validates if input and output files are valid for signing.
   *
   * @param inFile
   *            input file
   * @param outFile
   *            output file
   * @return true if valid, false otherwise
   */
  private boolean validateInOutFiles(final String inFile, final String outFile) {
    options.log("console.validatingFiles");
    if (StringUtils.isEmpty(inFile) || StringUtils.isEmpty(outFile)) {
      options.log("console.fileNotFilled.error");
      return false;
    }
    final File tmpInFile = new File(inFile);
    final File tmpOutFile = new File(outFile);
    if (!(tmpInFile.exists() && tmpInFile.isFile() && tmpInFile.canRead())) {
      options.log("console.inFileNotFound.error");
      return false;
    }
    if (tmpInFile.getAbsolutePath().equals(tmpOutFile.getAbsolutePath())) {
      options.log("console.filesAreEqual.error");
      return false;
    }
    return true;
  }

}
TOP

Related Classes of net.sf.jsignpdf.SignerLogic

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.