Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync core logic from Autogram v2.2.2 #7

Merged
merged 2 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .run/Main.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<option name="ALTERNATIVE_JRE_PATH" value="$PROJECT_DIR$/target/jdkCache/LIBERICA_jdk17.0.10+13_linux_amd64-full" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="MAIN_CLASS_NAME" value="digital.slovensko.avm.Main" />
<module name="autogram" />
<module name="avm" />
<option name="PROGRAM_PARAMETERS" value="-p 7200" />
<option name="VM_PARAMETERS" value="--add-exports jdk.crypto.cryptoki/sun.security.pkcs11.wrapper=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens jdk.crypto.cryptoki/sun.security.pkcs11=ALL-UNNAMED --add-exports java.base/sun.security.x509=ALL-UNNAMED" />
<method v="2">
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/digital/slovensko/avm/core/AVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import eu.europa.esig.dss.model.DSSDocument;
import eu.europa.esig.dss.pdfa.PDFAStructureValidator;
import eu.europa.esig.dss.spi.x509.tsp.TSPSource;
import eu.europa.esig.dss.validation.reports.Reports;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;

Expand All @@ -27,9 +27,9 @@ public AVM(TSPSource tspSource, boolean plainXmlEnabled) {
this.plainXmlEnabled = plainXmlEnabled;
}

public Reports checkAndValidateSignatures(DSSDocument document) {
var reports = SignatureValidator.getInstance().getSignatureValidationReport(document);
if (reports.getSimpleReport().getSignatureIdList().isEmpty())
public ValidationReports checkAndValidateSignatures(SigningJob job) {
var reports = SignatureValidator.getInstance().getSignatureValidationReport(job);
if (!reports.haveSignatures())
return null;

return reports;
Expand All @@ -40,8 +40,8 @@ public boolean checkPDFACompliance(SigningJob job) {
return result.isCompliant();
}

public void initializeSignatureValidator(ScheduledExecutorService scheduledExecutorService, ExecutorService cachedExecutorService) {
SignatureValidator.getInstance().initialize(cachedExecutorService);
public void initializeSignatureValidator(ScheduledExecutorService scheduledExecutorService, ExecutorService cachedExecutorService, List<String> tlCountries) {
SignatureValidator.getInstance().initialize(cachedExecutorService, tlCountries);

scheduledExecutorService.scheduleAtFixedRate(() -> SignatureValidator.getInstance().refresh(),
480, 480, java.util.concurrent.TimeUnit.MINUTES);
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/digital/slovensko/avm/core/AutogramMimeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public record AutogramMimeType(
String extension
) implements MimeType {
public static final AutogramMimeType XML_DATACONTAINER = new AutogramMimeType("application/vnd.gov.sk.xmldatacontainer+xml", null);
public static final AutogramMimeType XML_DATACONTAINER_WITH_CHARSET = new AutogramMimeType("application/vnd.gov.sk.xmldatacontainer+xml; charset=UTF-8", null);
public static final AutogramMimeType TEXT_WITH_CHARSET = new AutogramMimeType("text/plain; charset=UTF-8", null);
public static final AutogramMimeType APPLICATION_XML = new AutogramMimeType("application/xml", null);

@Override
Expand Down Expand Up @@ -41,10 +43,18 @@ public static boolean isXML(MimeType mimeType) {
}

public static boolean isXDC(MimeType mimeType) {
return mimeType.equals(XML_DATACONTAINER);
return mimeType.equals(XML_DATACONTAINER) || mimeType.equals(XML_DATACONTAINER_WITH_CHARSET);
}

public static boolean isPDF(MimeType mimeType) {
return mimeType.equals(MimeTypeEnum.PDF);
}

public static boolean isTxt(MimeType mimeType) {
return mimeType.equals(MimeTypeEnum.TEXT) || mimeType.equals(TEXT_WITH_CHARSET);
}

public static boolean isImage(MimeType mimeType) {
return mimeType.equals(MimeTypeEnum.PNG) || mimeType.equals(MimeTypeEnum.JPEG);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ private DSSDocument createVisualization() throws IOException, ParserConfiguratio
if (documentToDisplay.getMimeType().equals(MimeTypeEnum.HTML))
return documentToDisplay;

if (documentToDisplay.getMimeType().equals(MimeTypeEnum.TEXT))
if (isTxt(documentToDisplay.getMimeType()))
return documentToDisplay;

if (documentToDisplay.getMimeType().equals(MimeTypeEnum.PDF))
if (isPDF(documentToDisplay.getMimeType()))
return documentToDisplay;

if (documentToDisplay.getMimeType().equals(MimeTypeEnum.JPEG) || documentToDisplay.getMimeType().equals(MimeTypeEnum.PNG))
if (isImage(documentToDisplay.getMimeType()))
return transformImageToHTML(documentToDisplay);

return null;
Expand All @@ -97,8 +97,6 @@ private boolean isTranformationAvailable(String transformation) {
}

private boolean isDocumentSupportingTransformation(DSSDocument document) {
return document.getMimeType().equals(AutogramMimeType.XML_DATACONTAINER)
|| document.getMimeType().equals(AutogramMimeType.APPLICATION_XML)
|| document.getMimeType().equals(MimeTypeEnum.XML);
return isXDC(document.getMimeType()) || isXML(document.getMimeType());
}
}
30 changes: 22 additions & 8 deletions src/main/java/digital/slovensko/avm/core/SignatureValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;

import javax.xml.parsers.ParserConfigurationException;
Expand All @@ -16,6 +17,8 @@

import digital.slovensko.avm.util.DSSUtils;
import digital.slovensko.avm.util.XMLUtils;
import eu.europa.esig.dss.simplereport.SimpleReport;
import eu.europa.esig.dss.tsl.function.TLPredicateFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
Expand All @@ -40,6 +43,8 @@
import eu.europa.esig.dss.validation.SignedDocumentValidator;
import eu.europa.esig.dss.validation.reports.Reports;

import static digital.slovensko.avm.util.DSSUtils.createDocumentValidator;

public class SignatureValidator {
private static final String LOTL_URL = "https://ec.europa.eu/tools/lotl/eu-lotl.xml";
private static final String OJ_URL = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=uriserv:OJ.C_.2019.276.01.0001.01.ENG";
Expand Down Expand Up @@ -71,7 +76,7 @@ public synchronized void refresh() {
validationJob.offlineRefresh();
}

public synchronized void initialize(ExecutorService executorService) {
public synchronized void initialize(ExecutorService executorService, List<String> tlCountries) {
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
logger.debug("Initializing signature validator at {}", formatter.format(new Date()));

Expand All @@ -82,6 +87,7 @@ public synchronized void initialize(ExecutorService executorService) {
lotlSource.setSigningCertificatesAnnouncementPredicate(new OfficialJournalSchemeInformationURI(OJ_URL));
lotlSource.setUrl(LOTL_URL);
lotlSource.setPivotSupport(true);
lotlSource.setTlPredicate(TLPredicateFactory.createEUTLCountryCodePredicate(tlCountries.toArray(new String[0])));

var offlineFileLoader = new FileCacheDataLoader();
offlineFileLoader.setCacheExpirationTime(21600000);
Expand Down Expand Up @@ -121,12 +127,12 @@ private CertificateSource getJournalCertificateSource() throws AssertionError {
}
}

public synchronized Reports getSignatureValidationReport(DSSDocument document) {
var documentValidator = DSSUtils.createDocumentValidator(document);
public synchronized ValidationReports getSignatureValidationReport(SigningJob job) {
var documentValidator = createDocumentValidator(job.getDocument());
if (documentValidator == null)
return null;
return new ValidationReports(null, job);

return validate(documentValidator);
return new ValidationReports(validate(documentValidator), job);
}

public static String getSignatureValidationReportHTML(Reports signatureValidationReport) {
Expand All @@ -153,16 +159,16 @@ public static String getSignatureValidationReportHTML(Reports signatureValidatio
}

public static ValidationReports getSignatureCheckReport(SigningJob job) {
var validator = DSSUtils.createDocumentValidator(job.getDocument());
var validator = createDocumentValidator(job.getDocument());
if (validator == null)
return new ValidationReports(null, job);

validator.setCertificateVerifier(new CommonCertificateVerifier());
return new ValidationReports(validator.validateDocument(), job);
}

public static SignatureLevel getSignedDocumentSignatureLevel(DSSDocument document) {
var validator = DSSUtils.createDocumentValidator(document);
public static SimpleReport getSignedDocumentSimpleReport(DSSDocument document) {
var validator = createDocumentValidator(document);
if (validator == null)
return null;

Expand All @@ -171,10 +177,18 @@ public static SignatureLevel getSignedDocumentSignatureLevel(DSSDocument documen
if (report.getSignatureIdList().size() == 0)
return null;

return report;
}

public static SignatureLevel getSignedDocumentSignatureLevel(SimpleReport report) {
if (report == null)
return null;

return report.getSignatureFormat(report.getSignatureIdList().get(0));
}

public synchronized boolean areTLsLoaded() {
// TODO: consider validation turned off as well
return validationJob.getSummary().getNumberOfProcessedTLs() > 0;
}
}
52 changes: 33 additions & 19 deletions src/main/java/digital/slovensko/avm/core/SigningJob.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package digital.slovensko.avm.core;

import java.io.File;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.Date;

import digital.slovensko.avm.core.eforms.EFormUtils;
import digital.slovensko.avm.core.eforms.XDCBuilder;
import digital.slovensko.avm.core.eforms.XDCValidator;
import digital.slovensko.avm.core.eforms.xdc.XDCBuilder;
import digital.slovensko.avm.core.errors.AutogramException;
import digital.slovensko.avm.core.errors.CryptographicSignatureVerificationException;
import digital.slovensko.avm.core.errors.DataToSignMismatchException;
Expand All @@ -17,15 +15,19 @@
import eu.europa.esig.dss.cades.signature.CAdESService;
import eu.europa.esig.dss.enumerations.ASiCContainerType;
import eu.europa.esig.dss.enumerations.SignatureForm;
import eu.europa.esig.dss.enumerations.SignatureLevel;
import eu.europa.esig.dss.jades.signature.JAdESService;
import eu.europa.esig.dss.model.*;
import eu.europa.esig.dss.pades.PAdESSignatureParameters;
import eu.europa.esig.dss.pades.signature.PAdESService;
import eu.europa.esig.dss.signature.AbstractSignatureService;
import eu.europa.esig.dss.validation.CertificateVerifier;
import eu.europa.esig.dss.validation.CommonCertificateVerifier;
import eu.europa.esig.dss.xades.signature.XAdESService;

import static digital.slovensko.avm.core.AutogramMimeType.*;
import static digital.slovensko.avm.util.DSSUtils.createDocumentValidator;
import static digital.slovensko.avm.util.DSSUtils.getXdcfFilename;

public class SigningJob {
private final DSSDocument document;
Expand All @@ -52,20 +54,33 @@ public SignedDocument signDocument(DataToSignStructure dataToSignStructure, Stri
bLevelParameters.setSigningDate(new Date(dataToSignStructure.signingTime()));
signatureParameters.setBLevelParams(bLevelParameters);

if (signatureParameters.getSignatureLevel().equals(SignatureLevel.PAdES_BASELINE_T)) {
service.setTspSource(getParameters().getTspSource());
((PAdESSignatureParameters)signatureParameters).setContentSize(9472*2);
}

var dataToSign = service.getDataToSign(document, signatureParameters);
if (!new String(Base64.getEncoder().encode(dataToSign.getBytes())).equals(dataToSignStructure.dataToSign()))
throw new DataToSignMismatchException();

DSSDocument doc;
try {
var doc = service.signDocument(document, signatureParameters, signatureValue);
doc = service.signDocument(document, signatureParameters, signatureValue);
doc.setName(generatePrettyName(doc.getName(), document.getName()));
return new SignedDocument(doc, token);
} catch (DSSException e) {
if (e.getMessage().contains("Cryptographic signature verification has failed"))
throw new CryptographicSignatureVerificationException();

throw e;
}

var documentValidator = createDocumentValidator(doc);
documentValidator.setCertificateVerifier(commonCertificateVerifier);
var reports = documentValidator.validateDocument().getSimpleReport();
if (!reports.isValid(reports.getSignatureIdList().get(reports.getSignatureIdList().size() - 1)))
throw new CryptographicSignatureVerificationException();

return new SignedDocument(doc, token);
}

private static String generatePrettyName(String newName, String originalName) {
Expand Down Expand Up @@ -110,27 +125,26 @@ public DataToSignStructure buildDataToSign(String signingCertificate) throws Cer
bLevelParameters.setSigningDate(signingTime);
signatureParameters.setBLevelParams(bLevelParameters);

if (signatureParameters.getSignatureLevel().equals(SignatureLevel.PAdES_BASELINE_T)) {
service.setTspSource(getParameters().getTspSource());
((PAdESSignatureParameters)signatureParameters).setContentSize(9472*2);
}

var dataToSign = Base64.getEncoder().encode(service.getDataToSign(document, signatureParameters).getBytes());

return new DataToSignStructure(new String(dataToSign), signingTime.getTime(), signingCertificate);
}

public static FileDocument createDSSFileDocumentFromFile(File file) {
var fileDocument = new FileDocument(file);
private static SigningJob build(DSSDocument document, SigningParameters params) {
if (params.shouldCreateXdc() && !isXDC(document.getMimeType()) && !isAsice(document.getMimeType()))
document = XDCBuilder.transform(params, document.getName(), EFormUtils.getXmlFromDocument(document));

if (isXDC(fileDocument.getMimeType()) || isXML(fileDocument.getMimeType()) && XDCValidator.isXDCContent(fileDocument))
fileDocument.setMimeType(AutogramMimeType.XML_DATACONTAINER);
if (isTxt(document.getMimeType()))
document.setMimeType(AutogramMimeType.TEXT_WITH_CHARSET);

return fileDocument;
}

private static SigningJob build(DSSDocument document, SigningParameters params) {
if (params.shouldCreateXdc()) {
var mimeType = document.getMimeType();
if (!isXDC(mimeType) && !isAsice(mimeType)) {
document = XDCBuilder.transform(params, document.getName(), EFormUtils.getXmlFromDocument(document));
document.setMimeType(AutogramMimeType.XML_DATACONTAINER);
}
if (isXDC(document.getMimeType())) {
document.setMimeType(AutogramMimeType.XML_DATACONTAINER_WITH_CHARSET);
document.setName(getXdcfFilename(document.getName()));
}

return new SigningJob(document, params);
Expand Down
Loading