diff --git a/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PRTokeniser.java b/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PRTokeniser.java index fb012bb4..03007403 100644 --- a/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PRTokeniser.java +++ b/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PRTokeniser.java @@ -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); diff --git a/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PdfReader.java b/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PdfReader.java index 6ca74d6f..ba9a0959 100644 --- a/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PdfReader.java +++ b/jsignpdf-itxt/src/core/com/lowagie/text/pdf/PdfReader.java @@ -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 @@ -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; @@ -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(); } @@ -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 true if the PDF is encrypted. * @return true if the PDF is encrypted diff --git a/res/net/sf/jsignpdf/translations/messages.properties b/res/net/sf/jsignpdf/translations/messages.properties index fdaaceb3..61fd488a 100644 --- a/res/net/sf/jsignpdf/translations/messages.properties +++ b/res/net/sf/jsignpdf/translations/messages.properties @@ -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. diff --git a/res/net/sf/jsignpdf/translations/messages_cs.properties b/res/net/sf/jsignpdf/translations/messages_cs.properties index a1cce957..d94a8545 100644 --- a/res/net/sf/jsignpdf/translations/messages_cs.properties +++ b/res/net/sf/jsignpdf/translations/messages_cs.properties @@ -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. diff --git a/res/net/sf/jsignpdf/translations/messages_el.properties b/res/net/sf/jsignpdf/translations/messages_el.properties index b2d42a59..5b997c12 100644 --- a/res/net/sf/jsignpdf/translations/messages_el.properties +++ b/res/net/sf/jsignpdf/translations/messages_el.properties @@ -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. diff --git a/res/net/sf/jsignpdf/translations/messages_fr.properties b/res/net/sf/jsignpdf/translations/messages_fr.properties index d1d236f7..648a1cc3 100644 --- a/res/net/sf/jsignpdf/translations/messages_fr.properties +++ b/res/net/sf/jsignpdf/translations/messages_fr.properties @@ -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 diff --git a/src/net/sf/jsignpdf/SignerLogic.java b/src/net/sf/jsignpdf/SignerLogic.java index a578b4e6..9f878c9e 100644 --- a/src/net/sf/jsignpdf/SignerLogic.java +++ b/src/net/sf/jsignpdf/SignerLogic.java @@ -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; @@ -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) @@ -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()); diff --git a/src/net/sf/jsignpdf/types/HashAlgorithm.java b/src/net/sf/jsignpdf/types/HashAlgorithm.java index 81593020..4c231151 100644 --- a/src/net/sf/jsignpdf/types/HashAlgorithm.java +++ b/src/net/sf/jsignpdf/types/HashAlgorithm.java @@ -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; + } } diff --git a/src/net/sf/jsignpdf/types/SemVer.java b/src/net/sf/jsignpdf/types/SemVer.java new file mode 100644 index 00000000..4728c827 --- /dev/null +++ b/src/net/sf/jsignpdf/types/SemVer.java @@ -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 { + //@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; + } +} \ No newline at end of file