List of usage examples for com.lowagie.text.pdf OcspClientBouncyCastle OcspClientBouncyCastle
public OcspClientBouncyCastle(X509Certificate checkCert, X509Certificate rootCert, String url)
From source file:androidGLUESigner.pdf.PDFSignerEngine.java
License:Open Source License
/** * Send a ocsp request to the ocsp url stored in the certificate information * @param cert the signer cert// w w w .j ava 2s . c om * @param root the corresponding root cert * @return ocsp information * @throws CertificateException * @throws FileNotFoundException */ private static byte[] ocspRequest(X509Certificate cert, X509Certificate root) throws CertificateException, FileNotFoundException { String url = PdfPKCS7.getOCSPURL(cert); return new OcspClientBouncyCastle(cert, root, url).getEncoded(); }
From source file:net.sf.jsignpdf.SignerLogic.java
License:Mozilla Public License
/** * Signs a single file.// ww w.j av 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:net.sf.jsignpdf.verify.VerifierLogic.java
License:Mozilla Public License
/** * Validates certificate (chain) using OCSP. * /*www .jav a 2 s . co m*/ * @param pkc * certificate chain, 1st certificate will be validated * @param url * OCSP url for validation * @return */ private static boolean validateCertificateOCSP(Certificate pkc[], String url) { if (pkc.length < 2) { return false; } try { X509Certificate sigcer = (X509Certificate) pkc[0]; X509Certificate isscer = (X509Certificate) pkc[1]; OcspClientBouncyCastle ocspClient = new OcspClientBouncyCastle(sigcer, isscer, url); // TODO implement proxy support // ocspClient.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888))); byte[] encoded = ocspClient.getEncoded(); ASN1InputStream inp = new ASN1InputStream(encoded); BasicOCSPResponse resp = BasicOCSPResponse.getInstance(inp.readObject()); org.bouncycastle.ocsp.BasicOCSPResp basicResp = new org.bouncycastle.ocsp.BasicOCSPResp(resp); SingleResp sr = basicResp.getResponses()[0]; CertificateID cid = sr.getCertID(); CertificateID tis = new CertificateID(CertificateID.HASH_SHA1, isscer, sigcer.getSerialNumber()); return tis.equals(cid); } catch (Exception e) { return false; } }
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."); }/* www .ja v a 2 s. co 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(); }