Example usage for com.lowagie.text.pdf PdfPKCS7 PdfPKCS7

List of usage examples for com.lowagie.text.pdf PdfPKCS7 PdfPKCS7

Introduction

In this page you can find the example usage for com.lowagie.text.pdf PdfPKCS7 PdfPKCS7.

Prototype

public PdfPKCS7(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, String hashAlgorithm,
        String provider, boolean hasRSAdata)
        throws InvalidKeyException, NoSuchProviderException, NoSuchAlgorithmException 

Source Link

Document

Generates a signature.

Usage

From source file:androidGLUESigner.pdf.PDFSignerEngine.java

License:Open Source License

/**
 * Prepare the signing of the pdf (siganture appearance, placeholders, sigimage, ..) 
 * @param inputStream the stream to the input pdf file
 * @param outputStream the stream to the output pdf file
 * @return hash value with ocsp included
 * @throws IOException//from   w w  w. j  a va  2 s. c om
 * @throws DocumentException
 * @throws GeneralSecurityException
 */
public byte[] prepareSign(InputStream inputStream, OutputStream outputStream)
        throws IOException, DocumentException, GeneralSecurityException {

    PdfReader reader = new PdfReader(inputStream);

    PdfStamper stp = PdfStamper.createSignature(reader, outputStream, '\0', null, true);

    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    sap.setCrypto(null, getCertificateChain(), null, PdfSignatureAppearance.WINCER_SIGNED);
    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
    dic.setReason(siginfo.getSignatureReason());
    dic.setLocation(siginfo.getSignatureLocation());
    dic.setName(siginfo.getSignatureName());
    dic.setDate(new PdfDate(sap.getSignDate()));
    sap.setCryptoDictionary(dic);

    // get the selected rectangle and pagenumber for visible signature
    Rectangle signatureRect = new Rectangle(siginfo.getSignatureRect().left, siginfo.getSignatureRect().bottom,
            siginfo.getSignatureRect().right, siginfo.getSignatureRect().top);
    int pageNumber = siginfo.getPageNumber();
    sap.setVisibleSignature(signatureRect, pageNumber, null);

    // set signature picture, if there is one
    if (siginfo.getSignatureType() == SignatureType.PICTURE) {
        Image obj_pic = Image.getInstance(siginfo.getImagePath());
        sap.setImage(obj_pic);
    }

    // preserve some space for the contents
    HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
    exc.put(PdfName.CONTENTS, new Integer(SIGNATURE_MAX_SIZE * 2 + 2));
    sap.preClose(exc);

    // Save placeholder which will be replaced with actual signature later
    byte[] placeHolder = getPlaceHolderArr(SIGNATURE_MAX_SIZE * 2);
    // Replace the contents
    PdfDictionary dic2 = new PdfDictionary();
    dic2.put(PdfName.CONTENTS, new PdfString(placeHolder).setHexWriting(true));
    sap.close(dic2);

    // Calculate the digest
    InputStream data = sap.getRangeStream();

    MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
    byte buf[] = new byte[8192];
    int n;
    while ((n = data.read(buf)) > 0) {
        messageDigest.update(buf, 0, n);
    }

    hash = messageDigest.digest();

    calendar = Calendar.getInstance();
    ocsp = ocspRequest(cert, issuerCert);
    System.out.println("Got OCSP response, length = " + ocsp.length);

    // Calculate another digest over authenticatedAttributes
    PdfPKCS7 sgn = new PdfPKCS7(null, getCertificateChain(), null, hashAlgo, null, true);
    byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, calendar, ocsp);

    return sh;
}

From source file:androidGLUESigner.pdf.PDFSignerEngine.java

License:Open Source License

/**
 * Finalize signature with timestamp and store into result file
 * @param signedHash the signed hash value
 * @param inputStream the stream to the input pdf file
 * @param outputStream the stream to the output pdf file
 * @throws Exception/*from  ww  w .j  a  va  2s .  co m*/
 */
public void finalizeSign(byte[] signedHash, InputStream inputStream, OutputStream outputStream)
        throws Exception {

    // Create a temporary file
    File tmpFile = File.createTempFile("PDFSigner-", ".pdf");
    //tmpFile.deleteOnExit();

    // Save the PDF in the temporary file
    UtilityHelper.copyStream(inputStream, new FileOutputStream(tmpFile));

    // Add a timestamp:
    TSAClient tsc = new TSAClientBouncyCastle(tsa_url, tsa_login, tsa_passw);

    // Create the signature
    PdfPKCS7 sgn = new PdfPKCS7(null, getCertificateChain(), null, hashAlgo, null, true);
    sgn.setExternalDigest(signedHash, hash, "RSA");
    byte[] encodedSig = sgn.getEncodedPKCS7(hash, calendar, tsc, ocsp);
    System.out.println("finelizeSign: signedHash.length    = " + signedHash.length);
    System.out.println("finelizeSign: encodedSig.length    = " + encodedSig.length);

    if (SIGNATURE_MAX_SIZE + 2 < encodedSig.length)
        throw new DocumentException("Not enough space");

    String encodedSigHex = UtilityHelper.byteArrayToHexString(encodedSig);

    byte[] placeHolder = getPlaceHolder(SIGNATURE_MAX_SIZE * 2).getBytes();

    byte[] paddedSig = new byte[placeHolder.length];
    // fill with harmless data
    for (int i = 0; i < paddedSig.length; i++)
        paddedSig[i] = 0x30;

    System.out.println("finelizeSign: placeHolder.length   = " + placeHolder.length);
    System.out.println("finelizeSign: encodedSigHex.length = " + encodedSigHex.length());
    assert (placeHolder.length == paddedSig.length);

    System.arraycopy(encodedSigHex.getBytes(), 0, paddedSig, 0, encodedSigHex.getBytes().length);

    // Replace the contents
    FilePatchHelper.replace(tmpFile.getPath(), placeHolder, paddedSig);

    // Save the PDF in the outputStream
    UtilityHelper.copyStream(new FileInputStream(tmpFile), outputStream);
    tmpFile.delete();
}

From source file:net.sf.jsignpdf.SignerLogic.java

License:Mozilla Public License

/**
 * Signs a single file.// w  ww .jav a 2 s. c  om
 * 
 * @return true when signing is finished succesfully, false otherwise
 */
public boolean signFile() {
    final String outFile = options.getOutFileX();
    if (!validateInOutFiles(options.getInFile(), outFile)) {
        LOGGER.info(RES.get("console.skippingSigning"));
        return false;
    }

    boolean finished = false;
    Throwable tmpException = null;
    FileOutputStream fout = null;
    try {
        SSLInitializer.init(options);

        final PrivateKeyInfo pkInfo = KeyStoreUtils.getPkInfo(options);
        final PrivateKey key = pkInfo.getKey();
        final Certificate[] chain = pkInfo.getChain();
        if (ArrayUtils.isEmpty(chain)) {
            // the certificate was not found
            LOGGER.info(RES.get("console.certificateChainEmpty"));
            return false;
        }
        LOGGER.info(RES.get("console.createPdfReader", options.getInFile()));
        PdfReader reader;
        try {
            reader = new PdfReader(options.getInFile(), options.getPdfOwnerPwdStrX().getBytes());
        } catch (Exception e) {
            try {
                reader = new PdfReader(options.getInFile(), new byte[0]);
            } catch (Exception e2) {
                // try to read without password
                reader = new PdfReader(options.getInFile());
            }
        }

        LOGGER.info(RES.get("console.createOutPdf", outFile));
        fout = new FileOutputStream(outFile);

        final HashAlgorithm hashAlgorithm = options.getHashAlgorithmX();

        LOGGER.info(RES.get("console.createSignature"));
        char tmpPdfVersion = '\0'; // default version - the same as input
        if (reader.getPdfVersion() < hashAlgorithm.getPdfVersion()) {
            // this covers also problems with visible signatures (embedded
            // fonts) in PDF 1.2, because the minimal version
            // for hash algorithms is 1.3 (for SHA1)
            if (options.isAppendX()) {
                // if we are in append mode and version should be updated
                // then return false (not possible)
                LOGGER.info(RES.get("console.updateVersionNotPossibleInAppendMode"));
                return false;
            }
            tmpPdfVersion = hashAlgorithm.getPdfVersion();
            LOGGER.info(RES.get("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();
            @SuppressWarnings("unchecked")
            final List<String> sigNames = acroFields.getSignatureNames();
            for (String sigName : sigNames) {
                acroFields.removeField(sigName);
            }
        }
        if (options.isAdvanced() && options.getPdfEncryption() != PDFEncryption.NONE) {
            LOGGER.info(RES.get("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);
            switch (options.getPdfEncryption()) {
            case PASSWORD:
                stp.setEncryption(true, options.getPdfUserPwdStr(), options.getPdfOwnerPwdStrX(), tmpRight);
                break;
            case CERTIFICATE:
                final X509Certificate encCert = KeyStoreUtils
                        .loadCertificate(options.getPdfEncryptionCertFile());
                if (encCert == null) {
                    LOGGER.error(RES.get("console.pdfEncError.wrongCertificateFile",
                            StringUtils.defaultString(options.getPdfEncryptionCertFile())));
                    return false;
                }
                if (!KeyStoreUtils.isEncryptionSupported(encCert)) {
                    LOGGER.error(RES.get("console.pdfEncError.cantUseCertificate",
                            encCert.getSubjectDN().getName()));
                    return false;
                }
                stp.setEncryption(new Certificate[] { encCert }, new int[] { tmpRight },
                        PdfWriter.ENCRYPTION_AES_128);
                break;
            default:
                LOGGER.error(RES.get("console.unsupportedEncryptionType"));
                return false;
            }
        }

        final PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
        final String reason = options.getReason();
        if (StringUtils.isNotEmpty(reason)) {
            LOGGER.info(RES.get("console.setReason", reason));
            sap.setReason(reason);
        }
        final String location = options.getLocation();
        if (StringUtils.isNotEmpty(location)) {
            LOGGER.info(RES.get("console.setLocation", location));
            sap.setLocation(location);
        }
        final String contact = options.getContact();
        if (StringUtils.isNotEmpty(contact)) {
            LOGGER.info(RES.get("console.setContact", contact));
            sap.setContact(contact);
        }
        LOGGER.info(RES.get("console.setCertificationLevel"));
        sap.setCertificationLevel(options.getCertLevelX().getLevel());

        if (options.isVisible()) {
            // visible signature is enabled
            LOGGER.info(RES.get("console.configureVisible"));
            LOGGER.info(RES.get("console.setAcro6Layers", Boolean.toString(options.isAcro6Layers())));
            sap.setAcro6Layers(options.isAcro6Layers());

            final String tmpImgPath = options.getImgPath();
            if (tmpImgPath != null) {
                LOGGER.info(RES.get("console.createImage", tmpImgPath));
                final Image img = Image.getInstance(tmpImgPath);
                LOGGER.info(RES.get("console.setSignatureGraphic"));
                sap.setSignatureGraphic(img);
            }
            final String tmpBgImgPath = options.getBgImgPath();
            if (tmpBgImgPath != null) {
                LOGGER.info(RES.get("console.createImage", tmpBgImgPath));
                final Image img = Image.getInstance(tmpBgImgPath);
                LOGGER.info(RES.get("console.setImage"));
                sap.setImage(img);
            }
            LOGGER.info(RES.get("console.setImageScale"));
            sap.setImageScale(options.getBgImgScale());
            LOGGER.info(RES.get("console.setL2Text"));
            final String signer = PdfPKCS7.getSubjectFields((X509Certificate) chain[0]).getField("CN");
            final String timestamp = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z")
                    .format(sap.getSignDate().getTime());
            if (options.getL2Text() != null) {
                final Map<String, String> replacements = new HashMap<String, String>();
                replacements.put(L2TEXT_PLACEHOLDER_SIGNER, StringUtils.defaultString(signer));
                replacements.put(L2TEXT_PLACEHOLDER_TIMESTAMP, timestamp);
                replacements.put(L2TEXT_PLACEHOLDER_LOCATION, StringUtils.defaultString(location));
                replacements.put(L2TEXT_PLACEHOLDER_REASON, StringUtils.defaultString(reason));
                replacements.put(L2TEXT_PLACEHOLDER_CONTACT, StringUtils.defaultString(contact));
                final String l2text = StrSubstitutor.replace(options.getL2Text(), replacements);
                sap.setLayer2Text(l2text);
            } else {
                final StringBuilder buf = new StringBuilder();
                buf.append(RES.get("default.l2text.signedBy")).append(" ").append(signer).append('\n');
                buf.append(RES.get("default.l2text.date")).append(" ").append(timestamp);
                if (StringUtils.isNotEmpty(reason))
                    buf.append('\n').append(RES.get("default.l2text.reason")).append(" ").append(reason);
                if (StringUtils.isNotEmpty(location))
                    buf.append('\n').append(RES.get("default.l2text.location")).append(" ").append(location);
                sap.setLayer2Text(buf.toString());
            }
            if (FontUtils.getL2BaseFont() != null) {
                sap.setLayer2Font(new Font(FontUtils.getL2BaseFont(), options.getL2TextFontSize()));
            }
            LOGGER.info(RES.get("console.setL4Text"));
            sap.setLayer4Text(options.getL4Text());
            LOGGER.info(RES.get("console.setRender"));
            RenderMode renderMode = options.getRenderMode();
            if (renderMode == RenderMode.GRAPHIC_AND_DESCRIPTION && sap.getSignatureGraphic() == null) {
                LOGGER.warn(
                        "Render mode of visible signature is set to GRAPHIC_AND_DESCRIPTION, but no image is loaded. Fallback to DESCRIPTION_ONLY.");
                LOGGER.info(RES.get("console.renderModeFallback"));
                renderMode = RenderMode.DESCRIPTION_ONLY;
            }
            sap.setRender(renderMode.getRender());
            LOGGER.info(RES.get("console.setVisibleSignature"));
            int page = options.getPage();
            if (page < 1 || page > reader.getNumberOfPages()) {
                page = reader.getNumberOfPages();
            }
            sap.setVisibleSignature(new Rectangle(options.getPositionLLX(), options.getPositionLLY(),
                    options.getPositionURX(), options.getPositionURY()), page, null);
        }

        LOGGER.info(RES.get("console.processing"));
        final PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
        if (!StringUtils.isEmpty(reason)) {
            dic.setReason(sap.getReason());
        }
        if (!StringUtils.isEmpty(location)) {
            dic.setLocation(sap.getLocation());
        }
        if (!StringUtils.isEmpty(contact)) {
            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());
        final Map<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
        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) {
            LOGGER.info(RES.get("console.getOCSPURL"));
            String url = PdfPKCS7.getOCSPURL((X509Certificate) chain[0]);
            if (StringUtils.isEmpty(url)) {
                // get from options
                LOGGER.info(RES.get("console.noOCSPURL"));
                url = options.getOcspServerUrl();
            }
            if (!StringUtils.isEmpty(url)) {
                LOGGER.info(RES.get("console.readingOCSP", url));
                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())) {
            LOGGER.info(RES.get("console.creatingTsaClient"));
            if (options.getTsaServerAuthn() == ServerAuthentication.PASSWORD) {
                tsc = new TSAClientBouncyCastle(options.getTsaUrl(),
                        StringUtils.defaultString(options.getTsaUser()),
                        StringUtils.defaultString(options.getTsaPasswd()));
            } else {
                tsc = new TSAClientBouncyCastle(options.getTsaUrl());

            }
            final String tsaHashAlg = options.getTsaHashAlgWithFallback();
            LOGGER.info(RES.get("console.settingTsaHashAlg", tsaHashAlg));
            tsc.setHashAlgorithm(tsaHashAlg);
            tsc.setProxy(tmpProxy);
            final String policyOid = options.getTsaPolicy();
            if (StringUtils.isNotEmpty(policyOid)) {
                LOGGER.info(RES.get("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));
        LOGGER.info(RES.get("console.closeStream"));
        sap.close(dic2);
        fout.close();
        fout = null;
        finished = true;
    } catch (Exception e) {
        LOGGER.error(RES.get("console.exception"), e);
    } catch (OutOfMemoryError e) {
        LOGGER.fatal(RES.get("console.memoryError"), e);
    } finally {
        if (fout != null) {
            try {
                fout.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        LOGGER.info(RES.get("console.finished." + (finished ? "ok" : "error")));
        options.fireSignerFinishedEvent(tmpException);
    }
    return finished;
}

From source file:org.signserver.module.pdfsigner.PDFSigner.java

License:Open Source License

protected byte[] addSignatureToPDFDocument(final ICryptoInstance crypto, PDFSignerParameters params,
        byte[] pdfbytes, byte[] password, int contentEstimated, final ProcessRequest request,
        final RequestContext context) throws IOException, DocumentException, CryptoTokenOfflineException,
        SignServerException, IllegalRequestException {
    // when given a content length (i.e. non-zero), it means we are running a second try
    boolean secondTry = contentEstimated != 0;

    // get signing cert certificate chain and private key
    final List<Certificate> certs = getSigningCertificateChain(crypto);
    if (certs == null) {
        throw new SignServerException("Null certificate chain. This signer needs a certificate.");
    }// w w w . java 2s  . c o m
    final List<Certificate> includedCerts = includedCertificates(certs);
    Certificate[] certChain = includedCerts.toArray(new Certificate[includedCerts.size()]);
    PrivateKey privKey = crypto.getPrivateKey();

    // need to check digest algorithms for DSA private key at signing
    // time since we can't be sure what key a configured alias selector gives back
    if (privKey instanceof DSAPrivateKey) {
        if (!"SHA1".equals(digestAlgorithm)) {
            throw new IllegalRequestException(
                    "Only SHA1 is permitted as digest algorithm for DSA private keys");
        }
    }

    PdfReader reader = new PdfReader(pdfbytes, password);
    boolean appendMode = true; // TODO: This could be good to have as a property in the future

    int pdfVersion;

    try {
        pdfVersion = Integer.parseInt(Character.toString(reader.getPdfVersion()));
    } catch (NumberFormatException e) {
        pdfVersion = 0;
    }

    if (LOG.isDebugEnabled()) {
        LOG.debug("PDF version: " + pdfVersion);
    }

    // Don't certify already certified documents
    if (reader.getCertificationLevel() != PdfSignatureAppearance.NOT_CERTIFIED
            && params.getCertification_level() != PdfSignatureAppearance.NOT_CERTIFIED) {
        throw new IllegalRequestException("Will not certify an already certified document");
    }

    // Don't sign documents where the certification does not allow it
    if (reader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED
            || reader.getCertificationLevel() == PdfSignatureAppearance.CERTIFIED_FORM_FILLING) {
        throw new IllegalRequestException("Will not sign a certified document where signing is not allowed");
    }

    Permissions currentPermissions = Permissions.fromInt(reader.getPermissions());

    if (params.getSetPermissions() != null && params.getRemovePermissions() != null) {
        throw new SignServerException("Signer " + workerId + " missconfigured. Only one of " + SET_PERMISSIONS
                + " and " + REMOVE_PERMISSIONS + " should be specified.");
    }

    Permissions newPermissions;
    if (params.getSetPermissions() != null) {
        newPermissions = params.getSetPermissions();
    } else if (params.getRemovePermissions() != null) {
        newPermissions = currentPermissions.withRemoved(params.getRemovePermissions());
    } else {
        newPermissions = null;
    }

    Permissions rejectPermissions = Permissions.fromSet(params.getRejectPermissions());
    byte[] userPassword = reader.computeUserPassword();
    int cryptoMode = reader.getCryptoMode();
    if (LOG.isDebugEnabled()) {
        StringBuilder buff = new StringBuilder();
        buff.append("Current permissions: ").append(currentPermissions).append("\n")
                .append("Remove permissions: ").append(params.getRemovePermissions()).append("\n")
                .append("Reject permissions: ").append(rejectPermissions).append("\n")
                .append("New permissions: ").append(newPermissions).append("\n").append("userPassword: ")
                .append(userPassword == null ? "null" : "yes").append("\n").append("ownerPassword: ")
                .append(password == null ? "no" : (isUserPassword(reader, password) ? "no" : "yes"))
                .append("\n").append("setOwnerPassword: ")
                .append(params.getSetOwnerPassword() == null ? "no" : "yes").append("\n").append("cryptoMode: ")
                .append(cryptoMode);
        LOG.debug(buff.toString());
    }

    if (appendMode && (newPermissions != null || params.getSetOwnerPassword() != null)) {
        appendMode = false;
        if (LOG.isDebugEnabled()) {
            LOG.debug("Changing appendMode to false to be able to change permissions");
        }
    }

    ByteArrayOutputStream fout = new ByteArrayOutputStream();

    // increase PDF version if needed by digest algorithm
    final char updatedPdfVersion;
    if (minimumPdfVersion > pdfVersion) {
        updatedPdfVersion = Character.forDigit(minimumPdfVersion, 10);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Need to upgrade PDF to version 1." + updatedPdfVersion);
        }

        // check that the document isn't already signed 
        // when trying to upgrade version
        final AcroFields af = reader.getAcroFields();
        final List<String> sigNames = af.getSignatureNames();

        if (!sigNames.isEmpty()) {
            // TODO: in the future we might want to support
            // a fallback option in this case to allow re-signing using the same version (using append)
            throw new IllegalRequestException(
                    "Can not upgrade an already signed PDF and a higher version is required to support the configured digest algorithm");
        }

        appendMode = false;
    } else {
        updatedPdfVersion = '\0';
    }

    PdfStamper stp = PdfStamper.createSignature(reader, fout, updatedPdfVersion, null, appendMode);
    PdfSignatureAppearance sap = stp.getSignatureAppearance();

    // Set the new permissions
    if (newPermissions != null || params.getSetOwnerPassword() != null) {
        if (cryptoMode < 0) {
            cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting default encryption algorithm");
            }
        }
        if (newPermissions == null) {
            newPermissions = currentPermissions;
        }
        if (params.getSetOwnerPassword() != null) {
            password = params.getSetOwnerPassword().getBytes("ISO-8859-1");
        } else if (isUserPassword(reader, password)) {
            // We do not have an owner password so lets use a random one
            password = new byte[16];
            random.nextBytes(password);
            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting random owner password");
            }
        }
        stp.setEncryption(userPassword, password, newPermissions.asInt(), cryptoMode);
        currentPermissions = newPermissions;
    }

    // Reject if any permissions are rejected and the document does not use a permission password
    // or if it contains any of the rejected permissions
    if (rejectPermissions.asInt() != 0) {
        if (cryptoMode < 0 || currentPermissions.containsAnyOf(rejectPermissions)) {
            throw new IllegalRequestException("Document contains permissions not allowed by this signer");
        }
    }

    // include signer certificate crl inside cms package if requested
    CRL[] crlList = null;
    if (params.isEmbed_crl()) {
        crlList = getCrlsForChain(certs);
    }
    sap.setCrypto(null, certChain, crlList, PdfSignatureAppearance.SELF_SIGNED);

    // add visible signature if requested
    if (params.isAdd_visible_signature()) {
        int signaturePage = getPageNumberForSignature(reader, params);
        sap.setVisibleSignature(new com.lowagie.text.Rectangle(params.getVisible_sig_rectangle_llx(),
                params.getVisible_sig_rectangle_lly(), params.getVisible_sig_rectangle_urx(),
                params.getVisible_sig_rectangle_ury()), signaturePage, null);

        // set custom image if requested
        if (params.isUse_custom_image()) {
            sap.setAcro6Layers(true);
            PdfTemplate n2 = sap.getLayer(2);
            params.getCustom_image().setAbsolutePosition(0, 0);
            n2.addImage(params.getCustom_image());
        }
    }

    // Certification level
    sap.setCertificationLevel(params.getCertification_level());

    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
    dic.setReason(params.getReason());
    dic.setLocation(params.getLocation());
    dic.setDate(new PdfDate(Calendar.getInstance()));

    sap.setCryptoDictionary(dic);

    // add timestamp to signature if requested
    TSAClient tsc = null;
    if (params.isUse_timestamp()) {
        final String tsaUrl = params.getTsa_url();

        if (tsaUrl != null) {
            tsc = getTimeStampClient(params.getTsa_url(), params.getTsa_username(), params.getTsa_password());
        } else {
            tsc = new InternalTSAClient(getWorkerSession(), params.getTsa_worker(), params.getTsa_username(),
                    params.getTsa_password());
        }
    }

    // embed ocsp response in cms package if requested
    // for ocsp request to be formed there needs to be issuer certificate in
    // chain
    byte[] ocsp = null;
    if (params.isEmbed_ocsp_response() && certChain.length >= 2) {
        String url;
        try {
            url = PdfPKCS7.getOCSPURL((X509Certificate) certChain[0]);
            if (url != null && url.length() > 0) {
                ocsp = new OcspClientBouncyCastle((X509Certificate) certChain[0],
                        (X509Certificate) certChain[1], url).getEncoded();
            }
        } catch (CertificateParsingException e) {
            throw new SignServerException("Error getting OCSP URL from certificate", e);
        }

    }

    PdfPKCS7 sgn;
    try {
        sgn = new PdfPKCS7(privKey, certChain, crlList, digestAlgorithm, null, false);
    } catch (InvalidKeyException e) {
        throw new SignServerException("Error constructing PKCS7 package", e);
    } catch (NoSuchProviderException e) {
        throw new SignServerException("Error constructing PKCS7 package", e);
    } catch (NoSuchAlgorithmException e) {
        throw new SignServerException("Error constructing PKCS7 package", e);
    }

    MessageDigest messageDigest;
    try {
        messageDigest = MessageDigest.getInstance(digestAlgorithm);
    } catch (NoSuchAlgorithmException e) {
        throw new SignServerException("Error creating " + digestAlgorithm + " digest", e);
    }

    Calendar cal = Calendar.getInstance();

    // calculate signature size
    if (contentEstimated == 0) {
        contentEstimated = calculateEstimatedSignatureSize(certChain, tsc, ocsp, crlList);
    }

    byte[] encodedSig = calculateSignature(sgn, contentEstimated, messageDigest, cal, params, certChain, tsc,
            ocsp, sap);

    if (LOG.isDebugEnabled()) {
        LOG.debug("Estimated size: " + contentEstimated);
        LOG.debug("Encoded length: " + encodedSig.length);
    }

    if (contentEstimated + 2 < encodedSig.length) {
        if (!secondTry) {
            int contentExact = encodedSig.length;
            LOG.warn(
                    "Estimated signature size too small, usinging accurate calculation (resulting in an extra signature computation).");

            if (LOG.isDebugEnabled()) {
                LOG.debug("Estimated size: " + contentEstimated + ", actual size: " + contentExact);
            }

            // try signing again
            return addSignatureToPDFDocument(crypto, params, pdfbytes, password, contentExact, request,
                    context);
        } else {
            // if we fail to get an accurate signature size on the second attempt, bail out (this shouldn't happen)
            throw new SignServerException("Failed to calculate signature size");
        }
    }

    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));
    sap.close(dic2);
    reader.close();

    fout.close();
    return fout.toByteArray();
}

From source file:si.vsrs.cif.svev.example.utils.PDFSignature.java

License:EUPL

public File signPDF(File document, InputStream keystore, String password, String keyPassord,
        String keystoreType, String alias, boolean bshowVisualization) {
    if (document == null || !document.exists()) {
        throw new RuntimeException("Error reading pdf");
    }//from www.ja v a2s  .  c  o m

    String name = document.getName();
    String substring = name.substring(0, name.lastIndexOf("."));

    File outputDocument = new File(document.getParent(), substring + "_signed.pdf");

    try (FileInputStream fis = new FileInputStream(document);
            FileOutputStream fout = new FileOutputStream(outputDocument)) {

        KeyStore ks = KeyStore.getInstance(keystoreType);
        ks.load(keystore, password.toCharArray());
        PrivateKey key = (PrivateKey) ks.getKey(alias, keyPassord.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        X509Certificate xcert = (X509Certificate) chain[0];
        PdfReader reader = new PdfReader(fis);

        char tmpPdfVersion = '\0'; // default version - the same as input
        final PdfStamper stp = PdfStamper.createSignature(reader, fout, tmpPdfVersion, null, true);
        final PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
        sap.setReason("Testni podpis");
        sap.setLocation("Maribor");
        sap.setContact(xcert.getSubjectDN().getName());

        //            sap.setLayer2Text("");
        //          sap.setLayer4Text("");
        sap.setAcro6Layers(true); // --:> 

        Rectangle rc = reader.getPageSize(1);
        if (bshowVisualization) {
            sap.setVisibleSignature(new Rectangle(5, rc.getHeight() - 40, 240, rc.getHeight() - 5), 1, null);
        }

        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 int contentEstimated = 15000;
        final HashMap<PdfName, Integer> exc = new HashMap<>();
        exc.put(PdfName.CONTENTS, contentEstimated * 2 + 2);
        sap.preClose(exc);

        PdfPKCS7 sgn = new PdfPKCS7(key, chain, null, "SHA-256", null, false);
        InputStream data = sap.getRangeStream();
        final MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        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 sh[] = sgn.getAuthenticatedAttributeBytes(hash, cal, null);
        sgn.update(sh, 0, sh.length);

        byte[] encodedSig = sgn.getEncodedPKCS7(hash, cal, null, null);

        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));

        sap.close(dic2);
    } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException
            | UnrecoverableKeyException | DocumentException | InvalidKeyException | NoSuchProviderException
            | SignatureException ex) {
        throw new RuntimeException(ex.getMessage(), ex);
    }

    return outputDocument;
}