aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-pdfbox-2/src/main/java
diff options
context:
space:
mode:
authorThomas <>2024-09-05 09:55:35 +0200
committerThomas <>2024-09-05 09:55:35 +0200
commitd46ce27508d11be00ce247457f30e5381e7d280b (patch)
tree7621bc717a798d1889439064c062ec29cd2d45d9 /pdf-as-pdfbox-2/src/main/java
parentdbdee1a6a73053602d4f8ff0817ac3e9ecf7911f (diff)
downloadpdf-as-4-d46ce27508d11be00ce247457f30e5381e7d280b.tar.gz
pdf-as-4-d46ce27508d11be00ce247457f30e5381e7d280b.tar.bz2
pdf-as-4-d46ce27508d11be00ce247457f30e5381e7d280b.zip
fix(verify): broken signature verification if documents contains a signature-field that was not used yet
Diffstat (limited to 'pdf-as-pdfbox-2/src/main/java')
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/pdfbox2/PDFBOXVerifier.java173
1 files changed, 106 insertions, 67 deletions
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/pdfbox2/PDFBOXVerifier.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/pdfbox2/PDFBOXVerifier.java
index 270e9e28..1fab2793 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/pdfbox2/PDFBOXVerifier.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/verify/pdfbox2/PDFBOXVerifier.java
@@ -33,7 +33,7 @@ public class PDFBOXVerifier implements VerifyBackend {
@Override
public List<VerifyResult> verify(VerifyParameter parameter) throws PDFASError {
int signatureToVerify = parameter.getWhichSignature();
- int currentSignature = 0;
+
PDDocument doc = null;
try {
List<VerifyResult> result = new ArrayList<VerifyResult>();
@@ -62,97 +62,136 @@ public class PDFBOXVerifier implements VerifyBackend {
return result;
}
- int lastSig = -1;
- for (int i = 0; i < fields.size(); i++) {
- COSDictionary field = (COSDictionary) fields.getObject(i);
- String type = field.getNameAsString("FT");
- if ("Sig".equals(type)) {
- lastSig = i;
- }
- }
-
+ int lastSig = selectLastSigIndex(fields);
byte[] inputData = IOUtils.toByteArray(parameter.getDataSource().getInputStream());
+ int currentSignature = 0;
for (int i = 0; i < fields.size(); i++) {
COSDictionary field = (COSDictionary) fields.getObject(i);
String type = field.getNameAsString("FT");
- if ("Sig".equals(type)) {
- boolean verifyThis = true;
-
- if (signatureToVerify >= 0) {
- // verify only specific siganture!
- verifyThis = signatureToVerify == currentSignature;
- }
-
- if (signatureToVerify == -2) {
- verifyThis = i == lastSig;
- }
-
- if (verifyThis) {
- logger.trace("Found Signature: ");
+ if ("Sig".equals(type)) {
+ if (verifyCurrentSig(signatureToVerify, i, lastSig, currentSignature)) {
+ logger.trace("Found Signature Form: ");
COSBase base = field.getDictionaryObject("V");
- COSDictionary dict = (COSDictionary) base;
-
- logger.debug("Signer: " + dict.getNameAsString("Name"));
- logger.debug("SubFilter: " + dict.getNameAsString("SubFilter"));
- logger.debug("Filter: " + dict.getNameAsString("Filter"));
- logger.debug("Modified: " + dict.getNameAsString("M"));
- COSArray byteRange = (COSArray) dict.getDictionaryObject("ByteRange");
-
- StringBuilder sb = new StringBuilder();
- int[] bytes = new int[byteRange.size()];
- for (int j = 0; j < byteRange.size(); j++) {
- bytes[j] = byteRange.getInt(j);
- sb.append(" " + bytes[j]);
- }
-
- logger.debug("ByteRange" + sb.toString());
-
- COSString content = (COSString) dict.getDictionaryObject("Contents");
-
- ByteArrayOutputStream contentData = new ByteArrayOutputStream();
- for (int j = 0; j < bytes.length; j = j + 2) {
- int offset = bytes[j];
- int length = bytes[j + 1];
-
- contentData.write(inputData, offset, length);
- }
- contentData.close();
-
- IVerifyFilter verifyFilter = verifier.getVerifier(dict.getNameAsString("Filter"),
- dict.getNameAsString("SubFilter"));
-
- IVerifier lvlVerifier = verifier.getVerifierByLevel(parameter.getSignatureVerificationLevel());
- synchronized (lvlVerifier) {
- lvlVerifier.setConfiguration(parameter.getConfiguration());
- if (verifyFilter != null) {
- List<VerifyResult> results = verifyFilter.verify(contentData.toByteArray(),
- content.getBytes(), parameter.getVerificationTime(), bytes, lvlVerifier);
- if (results != null && !results.isEmpty()) {
- result.addAll(results);
- }
- }
+ if (base != null) {
+ checkTechicalSig(base, inputData, verifier, parameter, result, i);
+
+ } else {
+ logger.info("Skipping signature form, because it looks empty");
+
}
+
}
- currentSignature++;
+
+ currentSignature++;
}
- }
+ }
return result;
+
} catch (IOException e) {
logger.warn("Failed to verify document", e);
throw ErrorExtractor.searchPdfAsError(e, null);
+
} catch (PdfAsException e) {
logger.warn("Failed to verify document", e);
throw ErrorExtractor.searchPdfAsError(e, null);
+
} finally {
if (doc != null) {
try {
doc.close();
+
} catch (IOException e) {
logger.info("Failed to close doc");
+
}
}
}
}
+ private boolean verifyCurrentSig(int signatureToVerify, int i, int lastSig, int currentSignature) {
+ if (signatureToVerify >= 0) {
+ // verify only specific siganture!
+ return signatureToVerify == currentSignature;
+
+ }
+
+ if (signatureToVerify == -2) {
+ return i == lastSig;
+
+ }
+
+ return true;
+ }
+
+ private int selectLastSigIndex(COSArray fields) {
+ int lastSig = -1;
+ for (int i = 0; i < fields.size(); i++) {
+ COSDictionary field = (COSDictionary) fields.getObject(i);
+ String type = field.getNameAsString("FT");
+ if ("Sig".equals(type)) {
+ lastSig = i;
+ }
+ }
+
+ return lastSig;
+
+ }
+
+ private void checkTechicalSig(COSBase base, byte[] inputData, VerifierDispatcher verifier, VerifyParameter parameter,
+ List<VerifyResult> result, int i) throws IOException, PdfAsException {
+ try {
+ COSDictionary dict = (COSDictionary) base;
+
+ logger.debug("Signer: " + dict.getNameAsString("Name"));
+ logger.debug("SubFilter: " + dict.getNameAsString("SubFilter"));
+ logger.debug("Filter: " + dict.getNameAsString("Filter"));
+ logger.debug("Modified: " + dict.getNameAsString("M"));
+ COSArray byteRange = (COSArray) dict.getDictionaryObject("ByteRange");
+
+ StringBuilder sb = new StringBuilder();
+ int[] bytes = new int[byteRange.size()];
+ for (int j = 0; j < byteRange.size(); j++) {
+ bytes[j] = byteRange.getInt(j);
+ sb.append(" " + bytes[j]);
+ }
+
+ logger.debug("ByteRange" + sb.toString());
+
+ COSString content = (COSString) dict.getDictionaryObject("Contents");
+
+ ByteArrayOutputStream contentData = new ByteArrayOutputStream();
+ for (int j = 0; j < bytes.length; j = j + 2) {
+ int offset = bytes[j];
+ int length = bytes[j + 1];
+
+ contentData.write(inputData, offset, length);
+ }
+ contentData.close();
+
+ IVerifyFilter verifyFilter = verifier.getVerifier(dict.getNameAsString("Filter"),
+ dict.getNameAsString("SubFilter"));
+
+ IVerifier lvlVerifier = verifier.getVerifierByLevel(parameter.getSignatureVerificationLevel());
+ synchronized (lvlVerifier) {
+ lvlVerifier.setConfiguration(parameter.getConfiguration());
+ if (verifyFilter != null) {
+ List<VerifyResult> results = verifyFilter.verify(contentData.toByteArray(),
+ content.getBytes(), parameter.getVerificationTime(), bytes, lvlVerifier);
+ if (results != null && !results.isEmpty()) {
+ result.addAll(results);
+ }
+ }
+ }
+
+ } catch (NullPointerException e) {
+ logger.info("Verification of signature #{} failed with generic error", i);
+ }
+
+ }
+
}
+
+
+
+