package com.opentrust.spi.pdf;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import com.opentrust.spi.crypto.ExceptionHandler;
import com.opentrust.spi.logger.Channel;
import com.opentrust.spi.logger.SPILogger;
import com.opentrust.spi.pdf.PDFSign.CRLWithRevisionFactory;
import com.opentrust.spi.pdf.PDFSign.CertificateWithRevisionFactory;
import com.opentrust.spi.pdf.PDFSign.OCSPResponseWithRevisionFactory;
import com.opentrust.spi.pdf.PDFSign.ObjectWithRevision;
import com.opentrust.spi.pdf.PDFSign.ObjectWithRevisionAbstractFactory;
import com.opentrust.spi.pdf.PDFSign.VRIValidationData;
import com.opentrust.spi.pdf.PDFSign.ValidationData;
import com.spilowagie.text.pdf.AcroFields;
import com.spilowagie.text.pdf.PRStream;
import com.spilowagie.text.pdf.PdfArray;
import com.spilowagie.text.pdf.PdfDictionary;
import com.spilowagie.text.pdf.PdfIndirectReference;
import com.spilowagie.text.pdf.PdfName;
import com.spilowagie.text.pdf.PdfObject;
import com.spilowagie.text.pdf.PdfReader;
import com.spilowagie.text.pdf.PdfStream;
import com.spilowagie.text.pdf.RandomAccessFileOrArray;
public class PDFVerifSignature {
private static SPILogger log = SPILogger.getLogger("PDFSIGN");
public static PDFEnvelopedSignature verify(InputStream pdf_file, String signatureName) {
PDFEnvelopedSignature verifResult = null;
try {
PdfReader reader = new PdfReader(pdf_file, null);
AcroFields af = reader.getAcroFields();
verifResult = af.verifySignature(signatureName);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
public static PDFEnvelopedSignature verify(File file, String signatureName){
PDFEnvelopedSignature verifResult = null;
try {
PdfReader reader = new PdfReader(new FileInputStream(file));
verifResult = verify(reader, signatureName);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
// use for large files
public static PDFEnvelopedSignature verify(String fileName, String signatureName){
PDFEnvelopedSignature verifResult = null;
try {
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(fileName), null);
verifResult = verify(reader, signatureName);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
public static List<PDFEnvelopedSignature> verify(InputStream pdf_file){
return verify(pdf_file, false);
}
public static List<PDFEnvelopedSignature> verify(InputStream pdf_file, boolean withDocTS) {
List<PDFEnvelopedSignature> verifResult = null;
try {
PdfReader reader = new PdfReader(pdf_file, null);
verifResult = verify(reader, withDocTS);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
public static List<PDFEnvelopedSignature> verify(File file){
return verify(file, false);
}
public static List<PDFEnvelopedSignature> verify(File file, boolean withDocTS) {
List<PDFEnvelopedSignature> verifResult = null;
try {
PdfReader reader = new PdfReader(new FileInputStream(file));
verifResult = verify(reader, withDocTS);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
// use for large files
public static List<PDFEnvelopedSignature> verify(String fileName) {
return verify(fileName, false);
}
public static List<PDFEnvelopedSignature> verify(String fileName, boolean withDocTS) {
List<PDFEnvelopedSignature> verifResult = null;
try {
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(fileName), null);
verifResult = verify(reader, withDocTS);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
public static List<PDFEnvelopedSignature> verify(PdfReader reader){
return verify(reader, false);
}
public static List<PDFEnvelopedSignature> verify(PdfReader reader, boolean withDocTS) {
List<PDFEnvelopedSignature> verifResult = new ArrayList<PDFEnvelopedSignature>();
try {
AcroFields af = reader.getAcroFields();
ArrayList names = af.getSignatureNames(withDocTS);
log.debug(Channel.TECH, "%1$s signatures were found", names.size());
for (int k = 0; k < names.size(); ++k) {
String name = (String) names.get(k);
//FIXME : also perform document-wide verifications, for instance those involving reader.getCertificationLevel
verifResult.add(af.verifySignature(name));
}
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
protected static PDFEnvelopedSignature verify(PdfReader reader, String name) {
PDFEnvelopedSignature verifResult = null;
try {
AcroFields af = reader.getAcroFields();
verifResult = af.verifySignature(name);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
public static ValidationData verifyDSS(InputStream pdf_file) {
ValidationData verifResult = null;
try {
PdfReader reader = new PdfReader(pdf_file, null);
verifResult = verifyDSS(reader);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
public static ValidationData verifyDSS(File file) {
ValidationData verifResult = null;
try {
PdfReader reader = new PdfReader(new FileInputStream(file));
verifResult = verifyDSS(reader);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
// use for large files
public static ValidationData verifyDSS(String fileName) {
ValidationData verifResult = null;
try {
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(fileName), null);
verifResult = verifyDSS(reader);
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return verifResult;
}
protected static ValidationData verifyDSS(PdfReader reader) {
ValidationData validationData = new ValidationData();
try {
PdfDictionary catalog = reader.getCatalog();
PdfDictionary dssDico = catalog.getAsDict(PDFSign.DSS);
if(dssDico!=null) {
PdfArray ocsps = dssDico.getAsArray(PDFSign.OCSPS);
PdfArray crls = dssDico.getAsArray(PDFSign.CRLS);
PdfArray certs = dssDico.getAsArray(PDFSign.CERTS);
PdfDictionary vri = dssDico.getAsDict(PDFSign.VRI);
log.debug(Channel.TECH, "Looking for certs, crls and ocsp responses in DSS dictionary");
validationData.setCertificates(getObjectsFromDSS(reader, certs, new CertificateWithRevisionFactory()));
validationData.setCRLs(getObjectsFromDSS(reader, crls, new CRLWithRevisionFactory()));
validationData.setOCSPs(getObjectsFromDSS(reader, ocsps, new OCSPResponseWithRevisionFactory()));
if (vri != null) {
for (Object sigName : vri.getKeys()) {
PdfDictionary sigVri = vri.getAsDict((PdfName)sigName);
if (sigVri != null) {
VRIValidationData vriData = new VRIValidationData(((PdfName)sigName));
PdfArray vriCerts = sigVri.getAsArray(PdfName.CERT);
PdfArray vriCrls = sigVri.getAsArray(PDFSign.CRL);
PdfArray vriOcsps = sigVri.getAsArray(PDFSign.OCSP);
log.debug(Channel.TECH, "Looking for certs, crls and ocsp responses in VRI dictionary for key '%1$s'", sigName);
vriData.setCertificates(getObjectsFromDSS(reader, vriCerts, new CertificateWithRevisionFactory()));
vriData.setCRLs(getObjectsFromDSS(reader, vriCrls, new CRLWithRevisionFactory()));
vriData.setOCSPs(getObjectsFromDSS(reader, vriOcsps, new OCSPResponseWithRevisionFactory()));
validationData.addVRI(vriData);
}
}
}
}
} catch (Exception e) {
ExceptionHandler.handle(e);
}
return validationData;
}
private static <ConcreteObjectWithRevision extends ObjectWithRevision> List<ConcreteObjectWithRevision> getObjectsFromDSS(
PdfReader reader, PdfArray objects, ObjectWithRevisionAbstractFactory<ConcreteObjectWithRevision> factory) {
List<ConcreteObjectWithRevision> list = new ArrayList<ConcreteObjectWithRevision>();
if (objects != null) {
int readerReverseRevisionNbr = reader.getReverseRevisionNbr();
for (int i = 0; i < objects.size(); i++) {
PdfIndirectReference pdfIR = objects.getAsIndirectObject(i);
if (pdfIR != null) {
PdfObject object = reader.getPdfObject(pdfIR.getNumber());
if (object != null && object.isStream()) {
PdfStream stream = (PdfStream) object;
if (stream instanceof PRStream) {
try {
byte[] objectBytes = PdfReader.getStreamBytes((PRStream) stream);
if (objectBytes != null) {
int revision = readerReverseRevisionNbr - object.getReverseRevision();
ConcreteObjectWithRevision createObjectWithRevision = factory.createObjectWithRevision(objectBytes, revision);
list.add(createObjectWithRevision);
} else
log.debug(Channel.TECH, "objectBytes null");
} catch (Exception e) {
ExceptionHandler.handleNoThrow(e,
"Found invalid bytes in DSS or VRI dictionary. Skipping it");
}
} else
log.debug(Channel.TECH, "stream not a PRStream");
} else
log.debug(Channel.TECH, "object null or not a stream : %1$s", object);
} else
log.debug(Channel.TECH, "pdfIR null");
}
}
return list;
}
}