/**
* DSS - Digital Signature Services
* Copyright (C) 2015 European Commission, provided under the CEF programme
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package eu.europa.esig.dss.pdf;
import java.security.cert.X509CRL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.utils.Utils;
import eu.europa.esig.dss.x509.CertificateToken;
/**
* This class is a representation of a DSS (Document Security Store) Dictionary embedded in a PDF file.
* The dictionary is unique in a PDF file and can contain : VRI dictionary, certificates (Certs), OCSP responses (OCSPs)
* and CRLs.
* This dictionary is filled in PAdES-BASELINE-LT extension process.
*/
public class PdfDssDict {
private static final Logger logger = LoggerFactory.getLogger(PdfDssDict.class);
private static final String DSS_DICTIONARY_NAME = "DSS";
private static final String CERT_ARRAY_NAME_DSS = "Certs";
private static final String OCSP_ARRAY_NAME_DSS = "OCSPs";
private static final String CRL_ARRAY_NAME_DSS = "CRLs";
private static final String VRI_DICTIONARY_NAME = "VRI";
private static final String CERT_ARRAY_NAME_VRI = "Cert";
private static final String OCSP_ARRAY_NAME_VRI = "OCSP";
private static final String CRL_ARRAY_NAME_VRI = "CRL";
private Set<X509CRL> crlList = new HashSet<X509CRL>();
private Set<BasicOCSPResp> ocspList = new HashSet<BasicOCSPResp>();
private Set<CertificateToken> certList = new HashSet<CertificateToken>();
public static PdfDssDict extract(PdfDict documentDict) {
if (documentDict != null) {
final PdfDict dssCatalog = documentDict.getAsDict(DSS_DICTIONARY_NAME);
if (dssCatalog != null) {
return new PdfDssDict(dssCatalog);
}
}
logger.debug("No DSS dictionary found");
return null;
}
private PdfDssDict(PdfDict dssDictionary) {
readVRI(dssDictionary);
readCerts(dssDictionary);
readCrls(dssDictionary);
readOcsps(dssDictionary);
}
private void readVRI(PdfDict dssDictionary) {
PdfDict vriDict = dssDictionary.getAsDict(VRI_DICTIONARY_NAME);
if (vriDict != null) {
logger.debug("There is a VRI dictionary in DSS dictionary");
try {
String[] names = vriDict.list();
if (Utils.isArrayNotEmpty(names)) {
for (String name : names) {
extractCertsFromArray(vriDict.getAsDict(name), VRI_DICTIONARY_NAME + "/" + name, CERT_ARRAY_NAME_VRI);
extractOCSPsFromArray(vriDict.getAsDict(name), VRI_DICTIONARY_NAME + "/" + name, OCSP_ARRAY_NAME_VRI);
extractCRLsFromArray(vriDict.getAsDict(name), VRI_DICTIONARY_NAME + "/" + name, CRL_ARRAY_NAME_VRI);
}
}
} catch (Exception e) {
logger.debug("Unable to analyse VRI dictionary : " + e.getMessage());
}
} else {
logger.debug("No VRI dictionary found in DSS dictionary");
}
}
private void readCerts(PdfDict dssDictionary) {
extractCertsFromArray(dssDictionary, DSS_DICTIONARY_NAME, CERT_ARRAY_NAME_DSS);
}
private void readOcsps(PdfDict dssDictionary) {
extractOCSPsFromArray(dssDictionary, DSS_DICTIONARY_NAME, OCSP_ARRAY_NAME_DSS);
}
private void readCrls(PdfDict dssDictionary) {
extractCRLsFromArray(dssDictionary, DSS_DICTIONARY_NAME, CRL_ARRAY_NAME_DSS);
}
private void extractCRLsFromArray(PdfDict dict, String dictionaryName, String arrayName) {
final PdfArray crlArray = dict.getAsArray(arrayName);
if (crlArray != null) {
logger.debug("There are {} CRLs in {} dictionary", crlArray.size(), dictionaryName);
for (int ii = 0; ii < crlArray.size(); ii++) {
try {
final byte[] bytes = crlArray.getBytes(ii);
final X509CRL x509CRL = DSSUtils.loadCRL(bytes);
crlList.add(x509CRL);
} catch (Exception e) {
logger.debug("Unable to read CRL " + ii + " from " + dictionaryName + " dictionary : " + e.getMessage(), e);
}
}
} else {
logger.debug("No CRLs found in {} dictionary", dictionaryName);
}
}
private void extractCertsFromArray(PdfDict dict, String dictionaryName, String arrayName) {
final PdfArray certsArray = dict.getAsArray(arrayName);
if (certsArray != null) {
logger.debug("There are {} certificates in {} dictionary", certsArray.size(), dictionaryName);
for (int ii = 0; ii < certsArray.size(); ii++) {
try {
final byte[] stream = certsArray.getBytes(ii);
final CertificateToken cert = DSSUtils.loadCertificate(stream);
certList.add(cert);
} catch (Exception e) {
logger.debug("Unable to read Cert " + ii + " from " + dictionaryName + " dictionary : " + e.getMessage(), e);
}
}
} else {
logger.debug("No Certs found in {} dictionary", dictionaryName);
}
}
private void extractOCSPsFromArray(PdfDict dict, String dictionaryName, String arrayName) {
PdfArray ocspArray = dict.getAsArray(arrayName);
if (ocspArray != null) {
logger.debug("There are {} OCSPs in {} dictionary", ocspArray.size(), dictionaryName);
for (int ii = 0; ii < ocspArray.size(); ii++) {
try {
final byte[] stream = ocspArray.getBytes(ii);
final OCSPResp ocspResp = new OCSPResp(stream);
final BasicOCSPResp responseObject = (BasicOCSPResp) ocspResp.getResponseObject();
ocspList.add(responseObject);
} catch (Exception e) {
logger.debug("Unable to read OCSP " + ii + " from " + dictionaryName + " dictionary : " + e.getMessage(), e);
}
}
} else {
logger.debug("No OCSPs found in {} dictionary", dictionaryName);
}
}
public Set<X509CRL> getCrlList() {
return Collections.unmodifiableSet(crlList);
}
public Set<BasicOCSPResp> getOcspList() {
return Collections.unmodifiableSet(ocspList);
}
public Set<CertificateToken> getCertList() {
return Collections.unmodifiableSet(certList);
}
}