/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE file at the root of the source * tree and available online at * * https://github.com/keeps/roda */ package org.roda.core.plugins.plugins.characterization; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.cert.CertStoreException; import java.security.cert.CertificateException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.xml.crypto.MarshalException; import javax.xml.crypto.dsig.XMLSignatureException; import org.apache.commons.io.IOUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.bouncycastle.cms.CMSException; import org.roda.core.RodaCoreFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.itextpdf.text.DocumentException; public class DigitalSignatureDIPPluginUtils { private static final Logger LOGGER = LoggerFactory.getLogger(DigitalSignatureDIPPluginUtils.class); private static String KEYSTORE_PATH = RodaCoreFactory.getRodaHomePath() .resolve(RodaCoreFactory.getRodaConfigurationAsString("core", "signature", "keystore", "path")).toString(); private static final String KEYSTORE_PASSWORD = RodaCoreFactory.getRodaConfigurationAsString("core", "signature", "keystore", "password"); private static final String KEYSTORE_ALIAS = RodaCoreFactory.getRodaConfigurationAsString("core", "signature", "keystore", "alias"); private DigitalSignatureDIPPluginUtils() { // do nothing } public static void setKeystorePath(String path) { KEYSTORE_PATH = path; } public static void addDetachedSignature(Path input) throws IOException, GeneralSecurityException, CMSException { SignatureUtility signatureUtility = new SignatureUtility(); if (KEYSTORE_PATH != null) { try (InputStream is = new FileInputStream(KEYSTORE_PATH)) { signatureUtility.loadKeyStore(is, KEYSTORE_PASSWORD.toCharArray()); } } signatureUtility.initSign(KEYSTORE_ALIAS); File inputFile = input.toFile(); signatureUtility.sign(inputFile, input.getParent().resolve(inputFile.getName() + ".p7s").toFile()); } public static Path addEmbeddedSignature(Path input, String fileFormat, String mimetype) throws IOException, GeneralSecurityException, InvalidFormatException, XMLSignatureException, MarshalException, DocumentException { String generalFileFormat = SignatureUtils.canHaveEmbeddedSignature(fileFormat, mimetype); if (DigitalSignaturePluginUtils.PDF_FORMAT.equals(generalFileFormat)) { String reason = RodaCoreFactory.getRodaConfigurationAsString("core", "signature", "reason"); String location = RodaCoreFactory.getRodaConfigurationAsString("core", "signature", "location"); String contact = RodaCoreFactory.getRodaConfigurationAsString("core", "signature", "contact"); return PDFSignatureUtils.runDigitalSignatureSign(input, KEYSTORE_PATH, KEYSTORE_ALIAS, KEYSTORE_PASSWORD, reason, location, contact); } else if (DigitalSignaturePluginUtils.OOXML_FORMAT.equals(generalFileFormat)) { return OOXMLSignatureUtils.runDigitalSignatureSign(input, KEYSTORE_PATH, KEYSTORE_ALIAS, KEYSTORE_PASSWORD, fileFormat); } else if (DigitalSignaturePluginUtils.ODF_FORMAT.equals(generalFileFormat)) { return ODFSignatureUtils.runDigitalSignatureSign(input, KEYSTORE_PATH, KEYSTORE_ALIAS, KEYSTORE_PASSWORD, fileFormat); } return null; } /**** Digital signing with zip files ****/ public static void addElementToRepresentationZip(ZipOutputStream zout, Path file, String name) throws IOException { ZipEntry entry = new ZipEntry(name); try (InputStream in = Files.newInputStream(file)) { zout.putNextEntry(entry); byte[] data = IOUtils.toByteArray(in); zout.write(data); zout.closeEntry(); } } public static Path runZipDigitalSigner(Path input) { try { SignatureUtility signatureUtility = new SignatureUtility(); if (KEYSTORE_PATH != null) { try (InputStream is = new FileInputStream(KEYSTORE_PATH)) { signatureUtility.loadKeyStore(is, KEYSTORE_PASSWORD.toCharArray()); } } signatureUtility.initSign(KEYSTORE_ALIAS); Path signatureTempFile = Files.createTempFile("signature_", ".p7s"); signatureUtility.sign(input.toFile(), signatureTempFile.toFile()); Path zipResult = Files.createTempFile("signed_", ".zip"); OutputStream os = new FileOutputStream(zipResult.toString()); try (ZipOutputStream zout = new ZipOutputStream(os)) { // add representation zip ZipEntry zipEntry = new ZipEntry(input.toFile().getName()); try (InputStream in = Files.newInputStream(input)) { zout.putNextEntry(zipEntry); byte[] data = IOUtils.toByteArray(in); zout.write(data); zout.closeEntry(); } // add signature ZipEntry zipEntry2 = new ZipEntry(signatureTempFile.toFile().getName()); try (InputStream in2 = Files.newInputStream(signatureTempFile)) { zout.putNextEntry(zipEntry2); byte[] data2 = IOUtils.toByteArray(in2); zout.write(data2); zout.closeEntry(); } zout.finish(); } input.toFile().delete(); signatureTempFile.toFile().delete(); return zipResult; } catch (CertificateException | IOException e) { LOGGER.error("Cannot load keystore " + KEYSTORE_PATH, e); } catch (KeyStoreException | NoSuchAlgorithmException | NoSuchProviderException e) { LOGGER.error("Error initializing SignatureUtility", e); } catch (UnrecoverableKeyException | CMSException | InvalidAlgorithmParameterException e) { LOGGER.error("Error running initSign of SignatureUtility", e); } catch (CertStoreException e) { LOGGER.error("Error retrieving certificate from store", e); } return null; } }