package com.opentrust.pdfsign;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.bouncycastle.asn1.esf.OcspResponsesID;
import org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
import org.bouncycastle.ocsp.BasicOCSPResp;
import org.bouncycastle.ocsp.OCSPResp;
import com.keynectis.sequoia.ca.crypto.truststore.LongTermValidationInfos;
import com.keynectis.sequoia.ca.crypto.truststore.Truststore.ValidationResult;
import com.keynectis.sequoia.security.signeddocument.DocumentVerifier;
import com.keynectis.sequoia.security.xml.dsig.SignatureAlgorithm;
import com.opentrust.spi.cms.helpers.OCSPResponse;
import com.opentrust.spi.pdf.PDFEnvelopedSignature;
import com.opentrust.spi.pdf.PDFVerifSignature;
import com.opentrust.spi.pdf.PdfSignParameters.PAdESParameters.PadesLevel;
import com.opentrust.spi.tsp.TimestampToken;
public class PdfVerifier extends DocumentVerifier {
public static class PdfValidationResult
{
public boolean pdfValidation;
public PDFEnvelopedSignature signature;
public ValidationResult trustValidationResult;
public boolean containsRequiredAC = true;
public String missingCa;
public boolean isValid()
{
return pdfValidation && trustValidationResult.valid && containsRequiredAC;
}
public String getSignatureName()
{
return signature.getSignatureFieldName();
}
public X509Certificate getSignatureCertificate()
{
return trustValidationResult.tree.finalNode.entry.cert;
}
}
private List<SignatureAlgorithm> acceptableSignatureAlgorithms = null;
private PadesLevel padesConformanceLevel = PadesLevel.PADES_NONE;
private String signatureType;
public void setSignatureValidationParams(List<SignatureAlgorithm> acceptableSignatureAlgorithms) {
this.acceptableSignatureAlgorithms = acceptableSignatureAlgorithms;
}
public void setPadesConformanceLevel(PadesLevel level) {
this.padesConformanceLevel = level;
}
/**
* Verify the validity of the pdf document
* - the format
* - the validity of the signature certificate
* @param document
* @param signatureNames : the list of signatures to verify, if null, all the signatures are verified
* @return
* @throws Exception
*/
public List<PdfValidationResult> verify(PdfDocument document, String ...signatureNames) throws Exception {
//FIXME
ArrayList<String> signatureNameList = null;
if (signatureNames != null && signatureNames.length > 0)
{
signatureNameList= new ArrayList<String>();
for (String signatureName : signatureNames)
signatureNameList.add(signatureName);
}
signatureType = "PADES-BASIC";
ArrayList<PdfValidationResult> result = new ArrayList<PdfValidationResult>();
List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify(document.reader);
for (PDFEnvelopedSignature signatureVerifResult : verifResults)
{
String signatureFieldName = signatureVerifResult.getSignatureFieldName();
if (signatureNameList != null && !signatureNameList.contains(signatureFieldName))
continue;
PdfValidationResult current = new PdfValidationResult();
result.add(current);
current.signature = signatureVerifResult;
current.pdfValidation = signatureVerifResult.verify();
X509Certificate [] list = null;
Certificate[] includedCerts = signatureVerifResult.getCertificates();
if (includedCerts != null && includedCerts.length > 0)
{
list = new X509Certificate[includedCerts.length];
for (int i=0 ; i<includedCerts.length ; i++)
list[i] = (X509Certificate) includedCerts[i];
}
TimestampToken timestampToken = signatureVerifResult.getTimestampToken();
LongTermValidationInfos ltvInfos = null;
if (timestampToken != null)
{
ltvInfos = new LongTermValidationInfos();
ltvInfos.timeStampDate = timestampToken.getDateTime();
ltvInfos.tspCertificate = (X509Certificate) timestampToken.getSignerCertificate();
Collection<OCSPResponse> ocspResponses = signatureVerifResult.getOcspResponses();
ArrayList<BasicOCSPResp> ocspList = new ArrayList<BasicOCSPResp>();
for (OCSPResponse resp : ocspResponses)
{
OCSPResp bcResp = new OCSPResp(resp.getEncoded());
BasicOCSPResp basicResp = (BasicOCSPResp) bcResp.getResponseObject();
ocspList.add(basicResp);
}
ltvInfos.ocspResponse = ocspList.toArray(new BasicOCSPResp[] {});
Collection<X509CRL> crLs = signatureVerifResult.getCRLs();
ArrayList<X509CRL> crlList = new ArrayList<X509CRL>();
for (X509CRL crl : crLs)
{
crlList.add(crl);
}
ltvInfos.crls = crlList.toArray(new X509CRL[] {});
}
current.trustValidationResult = signingCertificateTruststore.validate(signatureVerifResult.getSigningCertificate(), ltvInfos, list);
X509Certificate []requiredCa = getAcceptedCACertificates();
if (requiredCa != null)
{
List<X509Certificate> missingCA = current.trustValidationResult.treeContains(requiredCa);
current.containsRequiredAC = (missingCA.size() == 0);
StringBuilder sb = new StringBuilder();
for (X509Certificate missingCert : missingCA)
sb.append(missingCert.getSubjectX500Principal().toString()+";");
current.missingCa = sb.toString();
}
}
return result;
}
@Override
protected String getSignatureType() {
return signatureType;
}
}