xades4j.verification.XAdESFormChecker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xades4j Show documentation
Show all versions of xades4j Show documentation
The XAdES4j library is an high-level, configurable and extensible Java implementation of XML Advanced
Electronic Signatures (XAdES 1.3.2 and 1.4.1). It enables producing, verifying and extending signatures in the
main XAdES forms: XAdES-BES, XAdES-EPES, XAdES-T and XAdES-C. Also, extended forms are supported through the
enrichment of an existing signature.
/*
* XAdES4j - A Java library for generation and verification of XAdES signatures.
* Copyright (C) 2010 Luis Goncalves.
*
* XAdES4j 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 3 of the License, or any later version.
*
* XAdES4j 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 XAdES4j. If not, see .
*/
package xades4j.verification;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import xades4j.properties.ArchiveTimeStampProperty;
import xades4j.properties.CertificateValuesProperty;
import xades4j.properties.CompleteCertificateRefsProperty;
import xades4j.properties.CompleteRevocationRefsProperty;
import xades4j.properties.RevocationValuesProperty;
import xades4j.properties.SigAndRefsTimeStampProperty;
import xades4j.properties.SignaturePolicyBase;
import xades4j.properties.SignatureTimeStampProperty;
import xades4j.properties.SigningCertificateProperty;
/**
*
* @author Luís
*/
class XAdESFormChecker
{
private XAdESFormChecker()
{
}
static XAdESForm checkForm(Collection props) throws InvalidXAdESFormException
{
Set availablePropsNames = new HashSet();
for (PropertyInfo propInfo : props)
{
availablePropsNames.add(propInfo.getProperty().getName());
}
XAdESFormDesc formDesc = XADES_C_DESC;
do
{
if (formDesc.check(availablePropsNames))
return formDesc.getForm();
} while ((formDesc = formDesc.getPrevious()) != null);
// XAdES G.2.2.1: "The verification process should assess whether the signature
// is a XAdES signature and if so, identify the specific form, by inspecting
// the different qualifying properties present. The verification process
// should not accept as XAdES signature any combination not aligned with
// those established in the normative part of the present document or the
// extended forms defined in the informative annex B."
throw new InvalidXAdESFormException("Signature doesn't follow any of the XAdES forms");
}
static final XAdESFormDesc XADES_BES_DESC = new XAdES_BES_Desc(),
XADES_EPES_DESC = new XAdES_EPES_Desc(),
XADES_T_DESC = new XAdES_T_Desc(),
XADES_C_DESC = new XAdES_C_Desc(),
XADES_X_DESC = new XAdES_X_Desc(),
XADES_X_L_DESC = new XAdES_X_L_Desc();
/**************************************************************************/
/**/
private static abstract class XAdESFormDesc
{
private XAdESFormDesc[] baseForms;
// Ordered from the top format to the lower format.
public XAdESFormDesc(XAdESFormDesc... baseForms)
{
this.baseForms = baseForms;
}
boolean check(Set availablePropsNames) throws InvalidXAdESFormException
{
// Check the properties for the current form.
if (!checkProps(availablePropsNames))
return false;
// If the properties of the current form are available, at least one
// of the base forms has to be well-formed.
if (baseForms.length == 0)
return true;
for (int i = 0; i < baseForms.length; i++)
{
if (baseForms[i].check(availablePropsNames))
return true;
}
throw new InvalidXAdESFormException(String.format("Required base forms for %s are not present", this.getForm().toString()));
}
XAdESFormDesc getPrevious()
{
return baseForms[0];
}
/**
* Checks the properties for the current form. Should throw an exception
* when the form is malformed.
* @return true if the format specific properties are available; false otherwise
*/
protected abstract boolean checkProps(Set availablePropsNames) throws InvalidXAdESFormException;
abstract XAdESForm getForm();
}
/**/
static class XAdES_BES_Desc extends XAdESFormDesc
{
@Override
protected boolean checkProps(Set availablePropsNames)
{
return availablePropsNames.contains(SigningCertificateProperty.PROP_NAME);
}
@Override
XAdESForm getForm()
{
return XAdESForm.BES;
}
}
/**/
static class XAdES_EPES_Desc extends XAdESFormDesc
{
public XAdES_EPES_Desc()
{
super(XADES_BES_DESC);
}
@Override
protected boolean checkProps(Set availablePropsNames)
{
return availablePropsNames.contains(SignaturePolicyBase.PROP_NAME);
}
@Override
XAdESForm getForm()
{
return XAdESForm.EPES;
}
}
/**/
static class XAdES_T_Desc extends XAdESFormDesc
{
public XAdES_T_Desc()
{
super(XADES_EPES_DESC, XADES_BES_DESC);
}
@Override
protected boolean checkProps(Set availablePropsNames)
{
return availablePropsNames.contains(SignatureTimeStampProperty.PROP_NAME);
}
@Override
XAdESForm getForm()
{
return XAdESForm.T;
}
}
/**/
static class XAdES_C_Desc extends XAdESFormDesc
{
public XAdES_C_Desc()
{
super(XADES_T_DESC);
}
@Override
protected boolean checkProps(Set availablePropsNames) throws InvalidXAdESFormException
{
boolean hasCompCertRefs = availablePropsNames.contains(CompleteCertificateRefsProperty.PROP_NAME);
boolean hasCompRevocRefs = availablePropsNames.contains(CompleteRevocationRefsProperty.PROP_NAME);
boolean xor = hasCompCertRefs ^ hasCompRevocRefs;
if (xor)
throw new InvalidXAdESFormException(String.format(
"Both %s and %s have to be present in %s form",
CompleteCertificateRefsProperty.PROP_NAME,
CompleteRevocationRefsProperty.PROP_NAME,
this.getForm().toString()));
// If has both props, it's C form.
if (hasCompCertRefs)
return true;
// Can't have attr properties if the other 2 are not present.
if (availablePropsNames.contains("AttributeCertificateRefs") || availablePropsNames.contains("AttributeRevocationRefs"))
throw new InvalidXAdESFormException("Attr properties cannot be present without the base C form properties");
return false;
}
@Override
XAdESForm getForm()
{
return XAdESForm.C;
}
}
/**/
static class XAdES_X_Desc extends XAdESFormDesc
{
public XAdES_X_Desc()
{
super(XADES_C_DESC);
}
@Override
protected boolean checkProps(Set availablePropsNames) throws InvalidXAdESFormException
{
return availablePropsNames.contains(SigAndRefsTimeStampProperty.PROP_NAME) ||
availablePropsNames.contains("RefsOnlyTimeStamp");
}
@Override
XAdESForm getForm()
{
return XAdESForm.X;
}
}
/**/
static class XAdES_X_L_Desc extends XAdESFormDesc
{
public XAdES_X_L_Desc()
{
super(XADES_X_DESC);
}
@Override
protected boolean checkProps(Set availablePropsNames) throws InvalidXAdESFormException
{
boolean hasCompCert = availablePropsNames.contains(CertificateValuesProperty.PROP_NAME);
boolean hasCompRevoc = availablePropsNames.contains(RevocationValuesProperty.PROP_NAME);
boolean xor = hasCompCert ^ hasCompRevoc;
if (xor)
throw new InvalidXAdESFormException(String.format(
"Both %s and %s have to be present in %s form",
"CertificateValues",
"RevocationValues",
this.getForm().toString()));
return hasCompCert;
}
@Override
XAdESForm getForm()
{
return XAdESForm.X_L;
}
}
/**/
static class XAdES_A_Desc extends XAdESFormDesc
{
public XAdES_A_Desc()
{
super(XADES_X_L_DESC);
}
@Override
protected boolean checkProps(Set availablePropsNames) throws InvalidXAdESFormException
{
return availablePropsNames.contains(ArchiveTimeStampProperty.PROP_NAME);
}
@Override
XAdESForm getForm()
{
return XAdESForm.A;
}
}
}