Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for PDF 2.0+ #25

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions jsignpdf-itxt/src/core/com/lowagie/text/pdf/PRTokeniser.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@ public char checkPdfHeader() throws IOException {
file.setStartOffset(idx);
return str.charAt(idx + 7);
}

public String checkPdfHeaderStr() throws IOException {
file.setStartOffset(0);
String str = readString(1024);
int idx = str.indexOf("%PDF-");
if (idx < 0)
throw new IOException("PDF header signature not found.");
file.setStartOffset(idx);
return str.substring(idx + 5, idx + 8);
}

public void checkFdfHeader() throws IOException {
file.setStartOffset(0);
Expand Down
14 changes: 13 additions & 1 deletion jsignpdf-itxt/src/core/com/lowagie/text/pdf/PdfReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ public class PdfReader implements PdfViewerPreferences {
protected int lastXref;
protected int eofPos;
protected char pdfVersion;
protected String pdfVersionStr;
protected PdfEncryption decrypt;
protected byte password[] = null; //added by ujihara for decryption
protected Key certificateKey = null; //added by Aiken Sam for certificate decryption
Expand Down Expand Up @@ -269,6 +270,7 @@ public PdfReader(PdfReader reader) {
this.tampered = reader.tampered;
this.password = reader.password;
this.pdfVersion = reader.pdfVersion;
this.pdfVersionStr = reader.pdfVersionStr;
this.eofPos = reader.eofPos;
this.freeXref = reader.freeXref;
this.lastXref = reader.lastXref;
Expand Down Expand Up @@ -487,7 +489,8 @@ public static Rectangle getNormalizedRectangle(PdfArray box) {
protected void readPdf() throws IOException {
try {
fileLength = tokens.getFile().length();
pdfVersion = tokens.checkPdfHeader();
pdfVersionStr = tokens.checkPdfHeaderStr();
pdfVersion = pdfVersionStr.charAt(2);
try {
readXref();
}
Expand Down Expand Up @@ -2325,6 +2328,15 @@ public char getPdfVersion() {
return pdfVersion;
}

/**
* Gets the PDF version - the whole friggin thing.
* (working with just the last char was "excellent" idea ...).
* @return the PDF version
*/
public String getFullPdfVersion() {
return pdfVersionStr;
}

/**
* Returns <CODE>true</CODE> if the PDF is encrypted.
* @return <CODE>true</CODE> if the PDF is encrypted
Expand Down
2 changes: 1 addition & 1 deletion res/net/sf/jsignpdf/translations/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ console.settingTsaPolicy = Setting TSA policy OID: {0}
console.skippingSigning = File validation failed, check your PDF paths. Skipping sign proccess.
console.starting = Starting JSignPdf
console.unsupportedEncryptionType = Unsupported encryption type.
console.updateVersion = Updating PDF version info 1.{0} -> 1.{1}
console.updateVersion = Updating PDF version info {0} -> {1}
console.updateVersionNotPossibleInAppendMode = Choosen configuration requires PDF version update, but it's not possible in the "append" signature mode.
console.usedKeyAlias = Used key alias: {0}
console.validatingFiles = Checking input and output PDF paths.
Expand Down
2 changes: 1 addition & 1 deletion res/net/sf/jsignpdf/translations/messages_cs.properties
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ console.settingTsaPolicy = Nastavuji OID politiky \u010Dasov
console.skippingSigning = Kontrola PDF soubor\u016F selhala, zkontrolujte nastaven\u00E9 cesty. Podpis nebude vytvo\u0159en.
console.starting = Spou\u0161t\u00EDm JSignPdf
console.unsupportedEncryptionType = Nepodporovan\u00FD typ k\u00F3dov\u00E1n\u00ED PDF.
console.updateVersion = Aktualizuji verzi PDF 1.{0} -> 1.{1}
console.updateVersion = Aktualizuji verzi PDF {0} -> {1}
console.updateVersionNotPossibleInAppendMode = Pro danou konfiguraci je vy\u017Eadov\u00E1na zm\u011Bna verze v\u00FDstupn\u00EDho PDF dokumentu, ale tato zm\u011Bna nen\u00ED mo\u017En\u00E1 v m\u00F3du "p\u0159id\u00E1n\u00ED podpisu" (append mode).
console.usedKeyAlias = Pou\u017Eit\u00FD priv\u00E1tn\u00ED kl\u00ED\u010D: {0}
console.validatingFiles = Kontroluji cesty k vstupn\u00EDmu a v\u00FDstupn\u00EDmu PDF souboru.
Expand Down
2 changes: 1 addition & 1 deletion res/net/sf/jsignpdf/translations/messages_el.properties
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ console.settingTsaPolicy = \u039F\u03C1\u03B9\u03C3\u03BC\u0
console.skippingSigning = \u0397 \u03B5\u03C0\u03B1\u03BB\u03AE\u03B8\u03B5\u03C5\u03C3\u03B7 \u03C4\u03BF\u03C5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5 \u03B1\u03C0\u03AD\u03C4\u03C5\u03C7\u03B5, \u03B5\u03BB\u03AD\u03B3\u03BE\u03C4\u03B5 \u03C4\u03B9\u03C2 \u03B4\u03B9\u03B1\u03B4\u03C1\u03BF\u03BC\u03AD\u03C2 \u03C4\u03C9\u03BD PDF. \u03A0\u03B1\u03C1\u03AC\u03BB\u03B5\u03B9\u03C8\u03B7 \u03C4\u03B7\u03C2 \u03B4\u03B9\u03B1\u03B4\u03B9\u03BA\u03B1\u03C3\u03AF\u03B1\u03C2 \u03C5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2.
console.starting = \u0395\u03BA\u03BA\u03AF\u03BD\u03B7\u03C3\u03B7 \u03C4\u03BF\u03C5 JSignPdf
console.unsupportedEncryptionType = \u039C\u03B7 \u03C5\u03C0\u03BF\u03C3\u03C4\u03B7\u03C1\u03B9\u03B6\u03CC\u03BC\u03B5\u03BD\u03BF\u03C2 \u03C4\u03CD\u03C0\u03BF\u03C2 \u03BA\u03C1\u03C5\u03C0\u03C4\u03BF\u03B3\u03C1\u03AC\u03C6\u03B7\u03C3\u03B7\u03C2.
console.updateVersion = \u0395\u03BD\u03B7\u03BC\u03AD\u03C1\u03C9\u03C3\u03B7 \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03AF\u03B1\u03C2 \u03AD\u03BA\u03B4\u03BF\u03C3\u03B7\u03C2 PDF 1.{0} -> 1.{1}
console.updateVersion = \u0395\u03BD\u03B7\u03BC\u03AD\u03C1\u03C9\u03C3\u03B7 \u03C0\u03BB\u03B7\u03C1\u03BF\u03C6\u03BF\u03C1\u03AF\u03B1\u03C2 \u03AD\u03BA\u03B4\u03BF\u03C3\u03B7\u03C2 PDF {0} -> {1}
console.updateVersionNotPossibleInAppendMode = \u0397 \u03B5\u03C0\u03B9\u03BB\u03B5\u03B3\u03BC\u03AD\u03BD\u03B7 \u03C1\u03CD\u03B8\u03BC\u03B9\u03C3\u03B7 \u03B1\u03C0\u03B1\u03B9\u03C4\u03B5\u03AF \u03C4\u03B7\u03BD \u03B1\u03BD\u03B1\u03B2\u03AC\u03B8\u03BC\u03B9\u03C3\u03B7 \u03C4\u03B7\u03C2 \u03AD\u03BA\u03B4\u03BF\u03C3\u03B7\u03C2 PDF, \u03B1\u03BB\u03BB\u03AC \u03B4\u03B5\u03BD \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B4\u03C5\u03BD\u03B1\u03C4\u03AE \u03C3\u03C4\u03B7 \u03BB\u03B5\u03B9\u03C4\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1 "\u03B5\u03C0\u03B9\u03C3\u03CD\u03BD\u03B1\u03C8\u03B7" \u03C5\u03C0\u03BF\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2.
console.usedKeyAlias = \u03A7\u03C1\u03B7\u03C3\u03B9\u03BC\u03BF\u03C0\u03BF\u03B9\u03AE\u03B8\u03B7\u03BA\u03B5 \u03C4\u03BF \u03C0\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03B9\u03B7\u03C4\u03B9\u03BA\u03CC: {0}
console.validatingFiles = \u0388\u03BB\u03B5\u03B3\u03C7\u03BF\u03C2 \u03C4\u03C9\u03BD \u03B4\u03B9\u03B1\u03B4\u03C1\u03BF\u03BC\u03CE\u03BD \u03C4\u03C9\u03BD PDF \u03B5\u03B9\u03C3\u03CC\u03B4\u03BF\u03C5 \u03BA\u03B1\u03B9 \u03B5\u03BE\u03CC\u03B4\u03BF\u03C5.
Expand Down
2 changes: 1 addition & 1 deletion res/net/sf/jsignpdf/translations/messages_fr.properties
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ console.setVisibleSignature = Cr\u00E9ation de l'attache de signature,
console.settingTsaPolicy = Param\u00E8tre de la politique d'horodatage r\u00E9f\u00E9renc\u00E9e par l'OID : {0}
console.skippingSigning = Echec de la validation du fichier. V\u00E9rifier le chemin. Signature interrompue.
console.starting = Lancement de PDF Signer
console.updateVersion = Mise \u00E0 jour de la version PDF 1.{0} -> 1.{1}
console.updateVersion = Mise \u00E0 jour de la version PDF {0} -> {1}
console.usedKeyAlias = Utiliser un alias pour la cl\u00E9 : {0}
console.validatingFiles = V\u00E9rification des chemins des fichiers d'entr\u00E9e/sortie

Expand Down
12 changes: 8 additions & 4 deletions src/net/sf/jsignpdf/SignerLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@
import java.util.List;
import java.util.Map;


import net.sf.jsignpdf.crl.CRLInfo;
import net.sf.jsignpdf.extcsp.CloudFoxy;
import net.sf.jsignpdf.ssl.SSLInitializer;
import net.sf.jsignpdf.types.HashAlgorithm;
import net.sf.jsignpdf.types.PDFEncryption;
import net.sf.jsignpdf.types.RenderMode;
import net.sf.jsignpdf.types.SemVer;
import net.sf.jsignpdf.types.ServerAuthentication;
import net.sf.jsignpdf.utils.FontUtils;
import net.sf.jsignpdf.utils.KeyStoreUtils;
Expand Down Expand Up @@ -176,7 +178,10 @@ public boolean signFile() {

LOGGER.info(RES.get("console.createSignature"));
char tmpPdfVersion = '\0'; // default version - the same as input
if (reader.getPdfVersion() < hashAlgorithm.getPdfVersion()) {
String pdfVer = reader.getFullPdfVersion();
String hashVer = hashAlgorithm.getPdfVersion();

if (new SemVer(pdfVer).compareTo(new SemVer(hashVer)) < 0) {
// 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)
Expand All @@ -186,9 +191,8 @@ public boolean signFile() {
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) }));
tmpPdfVersion = hashVer.charAt(2);
LOGGER.info(RES.get("console.updateVersion", new String[] { pdfVer, hashVer }));
}

final PdfStamper stp = PdfStamper.createSignature(reader, fout, tmpPdfVersion, null, options.isAppendX());
Expand Down
55 changes: 28 additions & 27 deletions src/net/sf/jsignpdf/types/HashAlgorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,37 @@
*
* @author Josef Cacek
*/

public enum HashAlgorithm {
SHA1("SHA-1", PdfWriter.VERSION_1_3),
SHA256("SHA-256", PdfWriter.VERSION_1_6),
SHA384("SHA-384", PdfWriter.VERSION_1_7),
SHA512("SHA-512", PdfWriter.VERSION_1_7),
RIPEMD160("RIPEMD160", PdfWriter.VERSION_1_7);
SHA1("SHA-1", "1.3"),
SHA256("SHA-256", "1.6"),
SHA384("SHA-384", "1.7"),
SHA512("SHA-512", "1.7"),
RIPEMD160("RIPEMD160", "1.7");

private final char pdfVersion;
private final String algorithmName;
private final String pdfVersion;
private final String algorithmName;

private HashAlgorithm(final String aName, char aVersion) {
algorithmName = aName;
pdfVersion = aVersion;
}
private HashAlgorithm(final String aName, String aVersion) {
algorithmName = aName;
pdfVersion = aVersion;
}

/**
* Gets algorithm name.
*
* @return
*/
public String getAlgorithmName() {
return algorithmName;
}
/**
* Gets algorithm name.
*
* @return
*/
public String getAlgorithmName() {
return algorithmName;
}

/**
* Gets minimal PDF version supporting the algorithm.
*
* @return
*/
public char getPdfVersion() {
return pdfVersion;
}
/**
* Gets minimal PDF version supporting the algorithm.
*
* @return
*/
public String getPdfVersion() {
return pdfVersion;
}
}
56 changes: 56 additions & 0 deletions src/net/sf/jsignpdf/types/SemVer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* [source: https://gist.github.com/brianguertin/ada4b65c6d1c4f6d3eee3c12b6ce021b]
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to http://unlicense.org
*/
package net.sf.jsignpdf.types;

public class SemVer implements Comparable<SemVer> {
//@NonNull
public final int[] numbers;

public SemVer(//@NonNull
String version) {
final String split[] = version.split("\\-")[0].split("\\.");
numbers = new int[split.length];
for (int i = 0; i < split.length; i++) {
numbers[i] = Integer.valueOf(split[i]);
}
}

@Override
public int compareTo(//@NonNull
SemVer another) {
final int maxLength = Math.max(numbers.length, another.numbers.length);
for (int i = 0; i < maxLength; i++) {
final int left = i < numbers.length ? numbers[i] : 0;
final int right = i < another.numbers.length ? another.numbers[i] : 0;
if (left != right) {
return left < right ? -1 : 1;
}
}
return 0;
}
}