/** * Embeds the new signature into the document, by copying the rest of the document * * @param docBytes byte array of the document * @param output target, where the file will be written * @throws IOException */ private void embedNewSignatureIntoDocument(byte[] docBytes, OutputStream output) throws IOException { int[] byteRange = signature.getByteRange(); output.write(docBytes, byteRange[0], byteRange[1] + 1); output.write(changedEncodedSignature); int addingLength = byteRange[2] - byteRange[1] - 2 - changedEncodedSignature.length; byte[] zeroes = Hex.getBytes(new byte[(addingLength + 1) / 2]); output.write(zeroes); output.write(docBytes, byteRange[2] - 1, byteRange[3] + 1); }
/** * Will return the embedded signature between the byterange gap. * * @param pdfFile The signed pdf file as byte array * @return a byte array containing the signature * @throws IOException if the pdfFile can't be read */ public byte[] getContents(byte[] pdfFile) throws IOException { int[] byteRange = getByteRange(); int begin = byteRange[0]+byteRange[1]+1; int len = byteRange[2]-begin; return getContents(new COSFilterInputStream(pdfFile,new int[] {begin,len})); }
/** * Will return the embedded signature between the byterange gap. * * @param pdfFile The signed pdf file as InputStream * @return a byte array containing the signature * @throws IOException if the pdfFile can't be read */ public byte[] getContents(InputStream pdfFile) throws IOException { int[] byteRange = getByteRange(); int begin = byteRange[0]+byteRange[1]+1; int len = byteRange[2]-begin; return getContents(new COSFilterInputStream(pdfFile,new int[] {begin,len})); }
/** * Extracts last Document-Signature from the document. The signature will be set on the signature-field. * * @param document to get the Signature from * @throws IOException */ private void getRelevantSignature(PDDocument document) throws IOException { // we can't use getLastSignatureDictionary() because this will fail (see PDFBOX-3978) // if a signature is assigned to a pre-defined empty signature field that isn't the last. // we get the last in time by looking at the offset in the PDF file. SortedMap<Integer, PDSignature> sortedMap = new TreeMap<>(); for (PDSignature sig : document.getSignatureDictionaries()) { int sigOffset = sig.getByteRange()[1]; sortedMap.put(sigOffset, sig); } if (sortedMap.size() > 0) { PDSignature lastSignature = sortedMap.get(sortedMap.lastKey()); COSBase type = lastSignature.getCOSObject().getItem(COSName.TYPE); if (type.equals(COSName.SIG)) { signature = lastSignature; } } }
/** * Gets the last relevant signature in the document, i.e. the one with the highest offset. * * @param document to get its last signature * @return last signature or null when none found * @throws IOException */ public static PDSignature getLastRelevantSignature(PDDocument document) throws IOException { SortedMap<Integer, PDSignature> sortedMap = new TreeMap<>(); for (PDSignature signature : document.getSignatureDictionaries()) { int sigOffset = signature.getByteRange()[1]; sortedMap.put(sigOffset, signature); } if (sortedMap.size() > 0) { PDSignature lastSignature = sortedMap.get(sortedMap.lastKey()); COSBase type = lastSignature.getCOSObject().getItem(COSName.TYPE); if (type.equals(COSName.SIG) || type.equals(COSName.DOC_TIME_STAMP)) { return lastSignature; } } return null; } }
/** * Return the signed content of the document. This is not a PDF file, nor is it the PDF file * before signing, it is the byte sequence made of the input minus the area where the signature * bytes will be. See "The ByteRange and signature value" in the document * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf#page=5">Digital * Signatures in a PDF</a>. * * @param pdfFile The signed pdf file as byte array * @return a byte array containing only the signed part of the content * @throws IOException if the pdfFile can't be read */ public byte[] getSignedContent(byte[] pdfFile) throws IOException { try (COSFilterInputStream fis = new COSFilterInputStream(pdfFile, getByteRange())) { return fis.toByteArray(); } }
/** * Return the signed content of the document. This is not a PDF file, nor is it the PDF file * before signing, it is the byte sequence made of the input minus the area where the signature * bytes will be. See "The ByteRange and signature value" in the document * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf#page=5">Digital * Signatures in a PDF</a>. * * @param pdfFile The signed pdf file as InputStream * @return a byte array containing only the signed part of the content * @throws IOException if the pdfFile can't be read */ public byte[] getSignedContent(InputStream pdfFile) throws IOException { try (COSFilterInputStream fis = new COSFilterInputStream(pdfFile, getByteRange())) { return fis.toByteArray(); } }
CMSSignedData signedData = new CMSSignedData(sigBlock); System.out.println("INFO: Byte Range: " + Arrays.toString(signature.getByteRange())); int maxSize = signature.getByteRange()[2] - signature.getByteRange()[1]; System.out.println( "INFO: New Signature has Size: " + newEncoded.length + " maxSize: " + maxSize);
int[] byteRange = foundSignature.getByteRange(); if (!Arrays.equals(byteRange, RESERVE_BYTE_RANGE))
int[] byteRange = sig.getByteRange(); if (byteRange.length != 4)
int offset = signature.getByteRange()[1] + 1;
int offset = signature.getByteRange()[1] + 1;
/** * Embeds the new signature into the document, by copying the rest of the document * * @param docBytes byte array of the document * @param output target, where the file will be written * @throws IOException */ private void embedNewSignatureIntoDocument(byte[] docBytes, OutputStream output) throws IOException { int[] byteRange = signature.getByteRange(); output.write(docBytes, byteRange[0], byteRange[1] + 1); output.write(changedEncodedSignature); int addingLength = byteRange[2] - byteRange[1] - 2 - changedEncodedSignature.length; byte[] zeroes = Hex.getBytes(new byte[(addingLength + 1) / 2]); output.write(zeroes); output.write(docBytes, byteRange[2] - 1, byteRange[3] + 1); }
/** * Will return the embedded signature between the byterange gap. * * @param pdfFile The signed pdf file as InputStream * @return a byte array containing the signature * @throws IOException if the pdfFile can't be read */ public byte[] getContents(InputStream pdfFile) throws IOException { int[] byteRange = getByteRange(); int begin = byteRange[0]+byteRange[1]+1; int len = byteRange[2]-begin; return getContents(new COSFilterInputStream(pdfFile,new int[] {begin,len})); }
/** * Will return the embedded signature between the byterange gap. * * @param pdfFile The signed pdf file as byte array * @return a byte array containing the signature * @throws IOException if the pdfFile can't be read */ public byte[] getContents(byte[] pdfFile) throws IOException { int[] byteRange = getByteRange(); int begin = byteRange[0]+byteRange[1]+1; int len = byteRange[2]-begin; return getContents(new COSFilterInputStream(pdfFile,new int[] {begin,len})); }
/** * Will return the embedded signature between the byterange gap. * * @param pdfFile The signed pdf file as InputStream * @return a byte array containing the signature * @throws IOException if the pdfFile can't be read */ public byte[] getContents(InputStream pdfFile) throws IOException { int[] byteRange = getByteRange(); int begin = byteRange[0]+byteRange[1]+1; int len = byteRange[2]-begin; return getContents(new COSFilterInputStream(pdfFile,new int[] {begin,len})); }
/** * Will return the embedded signature between the byterange gap. * * @param pdfFile The signed pdf file as byte array * @return a byte array containing the signature * @throws IOException if the pdfFile can't be read */ public byte[] getContents(byte[] pdfFile) throws IOException { int[] byteRange = getByteRange(); int begin = byteRange[0]+byteRange[1]+1; int len = byteRange[2]-begin; return getContents(new COSFilterInputStream(pdfFile,new int[] {begin,len})); }
/** * Return the signed content of the document. This is not a PDF file, nor is it the PDF file * before signing, it is the byte sequence made of the input minus the area where the signature * bytes will be. See "The ByteRange and signature value" in the document * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf#page=5">Digital * Signatures in a PDF</a>. * * @param pdfFile The signed pdf file as InputStream * @return a byte array containing only the signed part of the content * @throws IOException if the pdfFile can't be read */ public byte[] getSignedContent(InputStream pdfFile) throws IOException { try (COSFilterInputStream fis = new COSFilterInputStream(pdfFile, getByteRange())) { return fis.toByteArray(); } }
/** * Return the signed content of the document. This is not a PDF file, nor is it the PDF file * before signing, it is the byte sequence made of the input minus the area where the signature * bytes will be. See "The ByteRange and signature value" in the document * <a href="https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf#page=5">Digital * Signatures in a PDF</a>. * * @param pdfFile The signed pdf file as byte array * @return a byte array containing only the signed part of the content * @throws IOException if the pdfFile can't be read */ public byte[] getSignedContent(byte[] pdfFile) throws IOException { try (COSFilterInputStream fis = new COSFilterInputStream(pdfFile, getByteRange())) { return fis.toByteArray(); } }
/** * @return true if byte range covers entire document except for Contents * entry in signature dictionary */ @Override public Boolean getdoesByteRangeCoverEntireDocument() { try { SignatureParser parser = new SignatureParser(this.document.getPdfSource(), this.document.getDocument()); long[] actualByteRange = parser.getByteRangeBySignatureOffset(signatureOffset); int[] byteRange = ((org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature) this.simplePDObject).getByteRange(); for (int i = 0; i < 4; ++i) { if (byteRange[i] != actualByteRange[i]) { return Boolean.FALSE; } } return Boolean.TRUE; } catch (IOException ex) { LOGGER.debug("Can't create parser to process digital signature", ex); return Boolean.FALSE; } }