(0);
}
/***** Signed signature properties *****/
diff --git a/src/main/java/xades4j/production/XadesCSigningProfile.java b/src/main/java/xades4j/production/XadesCSigningProfile.java
index d522a024..5db0a88f 100644
--- a/src/main/java/xades4j/production/XadesCSigningProfile.java
+++ b/src/main/java/xades4j/production/XadesCSigningProfile.java
@@ -28,10 +28,19 @@
*
* The {@code AttributeCertificateRefs} and {@code AttributeRevocationRefs} properties
* are not supported.
+ *
+ * If the (implicit or explicit) policy you're following requires grace periods for
+ * signature creation, it is highly recommended not to use this signing profile
+ * but to use {@link XadesTSigningProfile} for initial signature creation and then extend
+ * the signature to XAdES-C form after the grace period has elapsed and new revocation
+ * information is available.
* @author Luís
*/
public class XadesCSigningProfile extends XadesTSigningProfile
{
+ /**
+ * @see XadesCSigningProfile
+ */
public XadesCSigningProfile(
KeyingDataProvider keyingProvider,
ValidationDataProvider validationDataProv)
@@ -40,6 +49,9 @@ public XadesCSigningProfile(
withBinding(ValidationDataProvider.class, validationDataProv);
}
+ /**
+ * @see XadesCSigningProfile
+ */
public XadesCSigningProfile(
KeyingDataProvider keyingProvider,
Class extends ValidationDataProvider> validationDataProvClass)
@@ -48,6 +60,9 @@ public XadesCSigningProfile(
withBinding(ValidationDataProvider.class, validationDataProvClass);
}
+ /**
+ * @see XadesCSigningProfile
+ */
public XadesCSigningProfile(
Class extends KeyingDataProvider> keyingProviderClass,
ValidationDataProvider validationDataProv)
@@ -56,6 +71,9 @@ public XadesCSigningProfile(
withBinding(ValidationDataProvider.class, validationDataProv);
}
+ /**
+ * @see XadesCSigningProfile
+ */
public XadesCSigningProfile(
Class extends KeyingDataProvider> keyingProviderClass,
Class extends ValidationDataProvider> validationDataProvClass)
diff --git a/src/main/java/xades4j/production/XadesFormatExtenderProfile.java b/src/main/java/xades4j/production/XadesFormatExtenderProfile.java
index 52a46c54..8c05a372 100644
--- a/src/main/java/xades4j/production/XadesFormatExtenderProfile.java
+++ b/src/main/java/xades4j/production/XadesFormatExtenderProfile.java
@@ -34,7 +34,7 @@
* is used to add unsigned signature properties to an existing signature in order
* augment its format. This can be done as part of the {@link xades4j.verification.XadesVerifier#verify(org.w3c.dom.Element, xades4j.verification.SignatureSpecificVerificationOptions, xades4j.production.XadesSignatureFormatExtender, xades4j.verification.XAdESForm) verification process}.
* The {@code XadesSignatureFormatExtender} can also be used separately, but no
- * checks are made on the correctness of the signature.
+ * checks are made on the correctness of the signature or added properties.
*
* This profile follows the same principles of {@link XadesSigningProfile}.
* @author Luís
diff --git a/src/main/java/xades4j/production/XadesSigningProfile.java b/src/main/java/xades4j/production/XadesSigningProfile.java
index 652eb7d0..6e10b13d 100644
--- a/src/main/java/xades4j/production/XadesSigningProfile.java
+++ b/src/main/java/xades4j/production/XadesSigningProfile.java
@@ -44,7 +44,9 @@
* The purpose of this class is to configure a {@link XadesSigner} that will actually
* produce signatures with those characteristics.
*
- * Only a {@link KeyingDataProvider} has to externally be supplied. All the other components
+ * Only a {@link KeyingDataProvider} has to externally be supplied. If you're creating
+ * a XAdES-T or XAdES-C form, it's highly recommended to change the default
+ * {@link TimeStampTokenProvider}. All the other components
* have default implementations that are used if no other actions are taken. However,
* all of them can be replaced through the corresponding methods, either by an instance
* or a class. When a class is used it may have dependencies on other components,
@@ -58,12 +60,14 @@
*
* The XAdES form is also part of the profile. Each form has additional requirements,
* hence being defined by a specific subclass. There are profiles up to XAdES-C.
- * The extended formats are also supported (with a few limitations) but can only
- * be added after verfication ({@link xades4j.verification.XadesVerifier}).
+ * If the policy you're implementing requires grace periods for signatures, it's highly
+ * recommended to not create XAdES-C form directly.
+ * The extended formats are also supported but can only
+ * be added after verification ({@link xades4j.verification.XadesVerifier}).
*
* Repeated dependency bindings will not cause an immediate error. An exception
* will be thrown when an instance of {@code XadesSigner} is requested.
- *
+ *
* @see XadesBesSigningProfile
* @see XadesEpesSigningProfile
* @see XadesTSigningProfile
@@ -103,7 +107,7 @@ protected XadesSigningProfile(
/**
* Creates a new {@code XadesSigner} based on the current state of the profile.
* If any changes are made after this call, the previously returned signer will
- * not be afected. Other signers can be created, accumulating the profile changes.
+ * not be affected. Other signers can be created, accumulating the profile changes.
* @return a {@code XadesSigner} accordingly to this profile
* @throws XadesProfileResolutionException if the dependencies of the signer (direct and indirect) cannot be resolved
*/
@@ -116,7 +120,7 @@ public final XadesSigner newSigner() throws XadesProfileResolutionException
/***/
/**
- * Adds a type dependency mapping to the profile. This is tipically done from an
+ * Adds a type dependency mapping to the profile. This is typically done from an
* interface to a type that implements that interface. When a dependency to
* {@code from} is found, the {@code to} class is used. The {@code to} class
* may in turn have its own dependencies.
diff --git a/src/main/java/xades4j/production/XadesTSigningProfile.java b/src/main/java/xades4j/production/XadesTSigningProfile.java
index 295b8442..dd8d31d0 100644
--- a/src/main/java/xades4j/production/XadesTSigningProfile.java
+++ b/src/main/java/xades4j/production/XadesTSigningProfile.java
@@ -22,22 +22,29 @@
/**
* A profile for producing XAdES-T signatures. A {@link KeyingDataProvider} has
* to be supplied. The library has a default {@link xades4j.providers.TimeStampTokenProvider}
- * that will be used to configure the {@code XadesSigner}. As all teh other components
+ * that will be used to configure the {@code XadesSigner}. As all the other components
* it can be exchanged.
*
* A {@link SignaturePolicyInfoProvider} should be added to produce a XAdES-T based
* on XAdES-EPES.
* @see XadesSigningProfile
+ * @see XadesCSigningProfile
* @author Luís
*/
public class XadesTSigningProfile extends XadesSigningProfile
{
+ /**
+ * @see XadesTSigningProfile
+ */
public XadesTSigningProfile(
Class extends KeyingDataProvider> keyingProviderClass)
{
super(keyingProviderClass);
}
+ /**
+ * @see XadesTSigningProfile
+ */
public XadesTSigningProfile(KeyingDataProvider keyingProvider)
{
super(keyingProvider);
diff --git a/src/main/java/xades4j/properties/AllDataObjsTimeStampProperty.java b/src/main/java/xades4j/properties/AllDataObjsTimeStampProperty.java
index b9af316a..efaa69d2 100644
--- a/src/main/java/xades4j/properties/AllDataObjsTimeStampProperty.java
+++ b/src/main/java/xades4j/properties/AllDataObjsTimeStampProperty.java
@@ -18,6 +18,8 @@
import java.util.Date;
+import xades4j.providers.ValidationData;
+
/**
* Represents a time-stamp computed before the signature production, over the sequence
* formed by ALL the {@code ds:Reference} elements within the {@code ds:SignedInfo}
@@ -31,9 +33,11 @@
* @author Luís
*/
public final class AllDataObjsTimeStampProperty extends SignedDataObjectProperty
+ implements BaseXAdESTimeStampProperty
{
public static final String PROP_NAME = "AllDataObjectsTimeStamp";
private Date time;
+ private ValidationData validationData;
public AllDataObjsTimeStampProperty()
{
@@ -64,4 +68,16 @@ public void setTime(Date time)
{
this.time = time;
}
+
+ @Override
+ public ValidationData getValidationData()
+ {
+ return validationData;
+ }
+
+ @Override
+ public void setValidationData(ValidationData validationData)
+ {
+ this.validationData = validationData;
+ }
}
diff --git a/src/main/java/xades4j/properties/ArchiveTimeStampProperty.java b/src/main/java/xades4j/properties/ArchiveTimeStampProperty.java
index 6af6f7f3..cfb0835b 100644
--- a/src/main/java/xades4j/properties/ArchiveTimeStampProperty.java
+++ b/src/main/java/xades4j/properties/ArchiveTimeStampProperty.java
@@ -18,21 +18,27 @@
import java.util.Date;
+import xades4j.providers.ValidationData;
+
/**
* The {@code xades141:ArchiveTimeStamp} unsigned signature property. Used for the
* XAdES-A form.
* @author Luís
*/
public final class ArchiveTimeStampProperty extends UnsignedSignatureProperty
+ implements BaseXAdESTimeStampProperty
{
- public static final String PROP_NAME = "xadesv141:ArchiveTimeStamp";
+ // it's in "xades141" namespace though!
+ public static final String PROP_NAME = "ArchiveTimeStamp";
/**/
private Date time;
+ private ValidationData validationData;
/**
* Gets the time-stamp time after signature production or verification.
* @return the time or {@code null} if the property wasn't part of a signature production
*/
+ @Override
public Date getTime()
{
return time;
@@ -43,6 +49,7 @@ public Date getTime()
* the time-stamp can be accessed afterwards.
* @param time the time
*/
+ @Override
public void setTime(Date time)
{
this.time = time;
@@ -51,6 +58,18 @@ public void setTime(Date time)
@Override
public String getName()
{
- throw new UnsupportedOperationException("Not supported yet.");
+ return PROP_NAME;
}
+
+ @Override
+ public ValidationData getValidationData()
+ {
+ return validationData;
+ }
+
+ @Override
+ public void setValidationData(ValidationData validationData)
+ {
+ this.validationData = validationData;
+ }
}
diff --git a/src/main/java/xades4j/properties/AttrAuthoritiesCertValuesProperty.java b/src/main/java/xades4j/properties/AttrAuthoritiesCertValuesProperty.java
new file mode 100644
index 00000000..39b29737
--- /dev/null
+++ b/src/main/java/xades4j/properties/AttrAuthoritiesCertValuesProperty.java
@@ -0,0 +1,56 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS
+ *
+ * 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.properties;
+
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+
+/**
+ * The {@code AttrAuthoritiesCertValues} is an optional unsigned property and qualifies
+ * the XML signatures. There can be at most one occurrence of this property in the
+ * signature.
+ *
+ * This element should have the full set of certificates that are needed to verify
+ * time stamps in {@code SignatureTimeStamp}, {@code SigAndRefsTimeStamp} and
+ * {@code RefsOnlyTimeStamp}.
+ * This property is optional part of XAdES-X-L form.
+ * @author Hubert Kario
+ */
+public final class AttrAuthoritiesCertValuesProperty extends UnsignedSignatureProperty
+{
+
+ public static final String PROP_NAME = "AttrAuthoritiesCertValues";
+ private final Collection certificates;
+
+ public AttrAuthoritiesCertValuesProperty(Collection certificates)
+ {
+ if (null == certificates)
+ throw new NullPointerException();
+ this.certificates = certificates;
+ }
+
+ public Collection getCertificates()
+ {
+ return certificates;
+ }
+
+ @Override
+ public String getName()
+ {
+ return PROP_NAME;
+ }
+}
diff --git a/src/main/java/xades4j/properties/AttributeRevocationValuesProperty.java b/src/main/java/xades4j/properties/AttributeRevocationValuesProperty.java
new file mode 100644
index 00000000..ed7a9179
--- /dev/null
+++ b/src/main/java/xades4j/properties/AttributeRevocationValuesProperty.java
@@ -0,0 +1,55 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS
+ *
+ * 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.properties;
+
+import java.security.cert.X509CRL;
+import java.util.Collection;
+
+/**
+ * The {@code AttributeRevocationValues} property is an optional unsigned property and
+ * qualifies the XML signature. There is at most one occurrence of this property in the
+ * signature.
+ *
+ * The {@code AttributeRevocationValues} property is used to hold the values of revocation
+ * information which are needed to check validity of TSA certificates in TimeStamps.
+ *
+ * @author Hubert Kario
+ *
+ */
+public class AttributeRevocationValuesProperty extends
+ UnsignedSignatureProperty
+{
+ public static final String PROP_NAME = "AttributeRevocationValues";
+ private final Collection crls;
+
+ public AttributeRevocationValuesProperty(Collection crls)
+ {
+ if (crls == null)
+ throw new NullPointerException();
+ this.crls = crls;
+ }
+ public Collection getCrls()
+ {
+ return crls;
+ }
+
+ @Override
+ public String getName()
+ {
+ return PROP_NAME;
+ }
+}
diff --git a/src/main/java/xades4j/properties/BaseXAdESTimeStampProperty.java b/src/main/java/xades4j/properties/BaseXAdESTimeStampProperty.java
new file mode 100644
index 00000000..d5ad262a
--- /dev/null
+++ b/src/main/java/xades4j/properties/BaseXAdESTimeStampProperty.java
@@ -0,0 +1,55 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.properties;
+
+import java.util.Date;
+
+import xades4j.providers.ValidationData;
+
+/**
+ * Interface applicable to all TimeStampProperties used in XAdES signatures.
+ * Provides the ability to query for time from time stamp token and validation data
+ * used to verify the token.
+ *
+ * @author Hubert Kario
+ *
+ */
+public interface BaseXAdESTimeStampProperty extends QualifyingProperty
+{
+ /**
+ * Return the time at which the token claims to be generated.
+ *
+ * Note: if there are multiple time stamp tokens in single property, only the time
+ * from last one will be returned.
+ * @return time from time stamp token in the property
+ */
+ public Date getTime();
+
+ public void setTime(Date time);
+
+ /**
+ * Validation data (certificates and CRLs) used to check validity of the time stamp
+ * token
+ *
+ * Note: if there are multiple time stamp tokens in property, only validation data
+ * for the last one will be returned.
+ * @return validation data
+ */
+ public ValidationData getValidationData();
+
+ public void setValidationData(ValidationData validationData);
+}
diff --git a/src/main/java/xades4j/properties/IndividualDataObjsTimeStampProperty.java b/src/main/java/xades4j/properties/IndividualDataObjsTimeStampProperty.java
index bfb77522..6c39ce7b 100644
--- a/src/main/java/xades4j/properties/IndividualDataObjsTimeStampProperty.java
+++ b/src/main/java/xades4j/properties/IndividualDataObjsTimeStampProperty.java
@@ -18,6 +18,8 @@
import java.util.Date;
+import xades4j.providers.ValidationData;
+
/**
* Represents a time-stamp computed before the signature production, over a sequence
* formed by some of the {@code ds:Reference} elements within the {@code ds:SignedInfo}
@@ -31,10 +33,12 @@
* @author Luís
*/
public final class IndividualDataObjsTimeStampProperty extends SignedDataObjectProperty
+ implements BaseXAdESTimeStampProperty
{
public static final String PROP_NAME = "IndividualDataObjectsTimeStamp";
/**/
private Date time;
+ private ValidationData validationData;
public IndividualDataObjsTimeStampProperty()
{
@@ -65,4 +69,16 @@ public void setTime(Date time)
{
this.time = time;
}
+
+ @Override
+ public ValidationData getValidationData()
+ {
+ return validationData;
+ }
+
+ @Override
+ public void setValidationData(ValidationData validationData)
+ {
+ this.validationData = validationData;
+ }
}
diff --git a/src/main/java/xades4j/properties/SigAndRefsTimeStampProperty.java b/src/main/java/xades4j/properties/SigAndRefsTimeStampProperty.java
index df397275..488bab0d 100644
--- a/src/main/java/xades4j/properties/SigAndRefsTimeStampProperty.java
+++ b/src/main/java/xades4j/properties/SigAndRefsTimeStampProperty.java
@@ -18,6 +18,8 @@
import java.util.Date;
+import xades4j.providers.ValidationData;
+
/**
* The {@code SigAndRefsTimeStamp} element is an unsigned property qualifying
* the signature.
@@ -29,10 +31,12 @@
* @author Luís
*/
public final class SigAndRefsTimeStampProperty extends UnsignedSignatureProperty
+ implements BaseXAdESTimeStampProperty
{
public static final String PROP_NAME = "SigAndRefsTimeStamp";
/**/
private Date time;
+ private ValidationData validationData;
/**
* Gets the time-stamp time.
@@ -53,4 +57,16 @@ public String getName()
{
return PROP_NAME;
}
+
+ @Override
+ public ValidationData getValidationData()
+ {
+ return validationData;
+ }
+
+ @Override
+ public void setValidationData(ValidationData validationData)
+ {
+ this.validationData = validationData;
+ }
}
diff --git a/src/main/java/xades4j/properties/SignatureTimeStampProperty.java b/src/main/java/xades4j/properties/SignatureTimeStampProperty.java
index ca01d980..d8719e0a 100644
--- a/src/main/java/xades4j/properties/SignatureTimeStampProperty.java
+++ b/src/main/java/xades4j/properties/SignatureTimeStampProperty.java
@@ -18,16 +18,19 @@
import java.util.Date;
+import xades4j.providers.ValidationData;
+
/**
* The {@code SignatureTimeStamp} property encapsulates the time-stamp over the
* {@code ds:SignatureValue} element.
* @author Luís
*/
public final class SignatureTimeStampProperty extends UnsignedSignatureProperty
+ implements BaseXAdESTimeStampProperty
{
public static final String PROP_NAME = "SignatureTimeStamp";
- /**/
private Date time;
+ private ValidationData validationData;
public SignatureTimeStampProperty()
{
@@ -39,17 +42,27 @@ public String getName()
return PROP_NAME;
}
- /**
- * Gets the time-stamp time.
- * @return the time or {@code null} if the property hasn't been processed in signature production or verification.
- */
+ @Override
public Date getTime()
{
return time;
}
+ @Override
public void setTime(Date time)
{
this.time = time;
}
+
+ @Override
+ public ValidationData getValidationData()
+ {
+ return validationData;
+ }
+
+ @Override
+ public void setValidationData(ValidationData validationData)
+ {
+ this.validationData = validationData;
+ }
}
diff --git a/src/main/java/xades4j/properties/TimeStampValidationDataProperty.java b/src/main/java/xades4j/properties/TimeStampValidationDataProperty.java
new file mode 100644
index 00000000..3caba07a
--- /dev/null
+++ b/src/main/java/xades4j/properties/TimeStampValidationDataProperty.java
@@ -0,0 +1,75 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.properties;
+
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+
+/**
+ * The {@code TimeStampValidationData} is an optional unsigned property that extends
+ * the XAdES-A format with information needed to verify previously signed time stamps.
+ * There can be multiple occurrences of this property in signature.
+ *
+ * In principle, the {@code TimeStampValidationData} element contains the full set of
+ * certificates and revocation information (CRLs or OCSP responses) that have been used
+ * to validate previous time stamp (XAdES-X time stamp in case of first
+ * {@code TimeStampValidationData} added after creation of first
+ * {@code ArchiveTimeStamp}).
+ * @author Hubert Kario
+ */
+public class TimeStampValidationDataProperty extends UnsignedSignatureProperty
+{
+ // it is in xadesv141 namespace though!
+ public static final String PROP_NAME = "TimeStampValidationData";
+ private final Collection certificateValues;
+ private final Collection crls;
+
+ /**
+ * Both parameters can be {@code null} or empty, but not at the same time
+ *
+ * @param certificates can be null
+ * @param crls can be null
+ */
+ public TimeStampValidationDataProperty(Collection certificates,
+ Collection crls)
+ {
+ if ((certificates == null || certificates.isEmpty()) &&
+ ((crls == null) || crls.isEmpty()))
+ throw new NullPointerException("Both parameters can't be null/empty");
+
+ this.certificateValues = certificates;
+ this.crls = crls;
+ }
+
+ public Collection getCrls()
+ {
+ return crls;
+ }
+
+ public Collection getCertificates()
+ {
+ return certificateValues;
+ }
+
+ @Override
+ public String getName()
+ {
+ return PROP_NAME;
+ }
+
+}
diff --git a/src/main/java/xades4j/properties/data/AttrAuthoritiesCertValuesData.java b/src/main/java/xades4j/properties/data/AttrAuthoritiesCertValuesData.java
new file mode 100644
index 00000000..e666feaa
--- /dev/null
+++ b/src/main/java/xades4j/properties/data/AttrAuthoritiesCertValuesData.java
@@ -0,0 +1,24 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.properties.data;
+
+/**
+ * @author Hubert Kario
+ */
+public class AttrAuthoritiesCertValuesData extends BaseEncapsulatedPKIData
+{
+}
diff --git a/src/main/java/xades4j/properties/data/AttributeRevocationValuesData.java b/src/main/java/xades4j/properties/data/AttributeRevocationValuesData.java
new file mode 100644
index 00000000..e1531dac
--- /dev/null
+++ b/src/main/java/xades4j/properties/data/AttributeRevocationValuesData.java
@@ -0,0 +1,21 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS
+ *
+ * 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.properties.data;
+
+public class AttributeRevocationValuesData extends BaseEncapsulatedPKIData
+{
+}
diff --git a/src/main/java/xades4j/properties/data/BaseValidationDataData.java b/src/main/java/xades4j/properties/data/BaseValidationDataData.java
new file mode 100644
index 00000000..02162078
--- /dev/null
+++ b/src/main/java/xades4j/properties/data/BaseValidationDataData.java
@@ -0,0 +1,59 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.properties.data;
+
+import java.util.Collection;
+
+public class BaseValidationDataData implements PropertyDataObject
+{
+ private final CertificateValuesData certificateValues;
+ private final RevocationValuesData crlData;
+
+ public BaseValidationDataData(
+ Collection certificates,
+ Collection crlData)
+ {
+ this.certificateValues = new CertificateValuesData(certificates);
+ this.crlData = new RevocationValuesData(crlData);
+ }
+
+ public BaseValidationDataData()
+ {
+ this.certificateValues = new CertificateValuesData();
+ this.crlData = new RevocationValuesData();
+ }
+
+ public void addCertificateData(byte[] d)
+ {
+ this.certificateValues.addData(d);
+ }
+
+ public void addCRLData(byte[] d)
+ {
+ this.crlData.addData(d);
+ }
+
+ public Collection getCertificateData()
+ {
+ return certificateValues.getData();
+ }
+
+ public Collection getCRLData()
+ {
+ return crlData.getData();
+ }
+}
diff --git a/src/main/java/xades4j/properties/data/BaseValidationDataStructureVerifier.java b/src/main/java/xades4j/properties/data/BaseValidationDataStructureVerifier.java
new file mode 100644
index 00000000..5d416e4b
--- /dev/null
+++ b/src/main/java/xades4j/properties/data/BaseValidationDataStructureVerifier.java
@@ -0,0 +1,38 @@
+package xades4j.properties.data;
+
+import java.util.Collection;
+
+public class BaseValidationDataStructureVerifier implements
+ PropertyDataObjectStructureVerifier
+{
+ private final String propName;
+
+ BaseValidationDataStructureVerifier(String propName)
+ {
+ this.propName = propName;
+ }
+
+ @Override
+ public void verifyStructure(PropertyDataObject propData)
+ throws PropertyDataStructureException
+ {
+ BaseValidationDataData validationData = (BaseValidationDataData) propData;
+
+ Collection certData = validationData.getCertificateData();
+ Collection revocData = validationData.getCRLData();
+ if ((certData == null || certData.isEmpty()) && (revocData == null || revocData.isEmpty()))
+ throw new PropertyDataStructureException(
+ "Neither certificate nor revocation data provided", propName);
+
+ for (byte[] d : certData)
+ {
+ if (d == null)
+ throw new PropertyDataStructureException("null cert data", propName);
+ }
+ for (byte[] d : revocData)
+ {
+ if (d == null)
+ throw new PropertyDataStructureException("null revoc data", propName);
+ }
+ }
+}
diff --git a/src/main/java/xades4j/properties/data/CertificateValuesData.java b/src/main/java/xades4j/properties/data/CertificateValuesData.java
index 86104ed2..a03f6ee0 100644
--- a/src/main/java/xades4j/properties/data/CertificateValuesData.java
+++ b/src/main/java/xades4j/properties/data/CertificateValuesData.java
@@ -16,10 +16,21 @@
*/
package xades4j.properties.data;
+import java.util.Collection;
+
/**
*
* @author Luís
*/
public final class CertificateValuesData extends BaseEncapsulatedPKIData
{
+ public CertificateValuesData()
+ {
+ super();
+ }
+
+ public CertificateValuesData(Collection certificates)
+ {
+ super(certificates);
+ }
}
diff --git a/src/main/java/xades4j/properties/data/PropertiesDataObjectsStructureVerifier.java b/src/main/java/xades4j/properties/data/PropertiesDataObjectsStructureVerifier.java
index 2316b8a0..c484240e 100644
--- a/src/main/java/xades4j/properties/data/PropertiesDataObjectsStructureVerifier.java
+++ b/src/main/java/xades4j/properties/data/PropertiesDataObjectsStructureVerifier.java
@@ -25,12 +25,15 @@
import java.util.Set;
import xades4j.properties.AllDataObjsTimeStampProperty;
import xades4j.properties.ArchiveTimeStampProperty;
+import xades4j.properties.AttrAuthoritiesCertValuesProperty;
+import xades4j.properties.AttributeRevocationValuesProperty;
import xades4j.properties.CertificateValuesProperty;
import xades4j.properties.CompleteCertificateRefsProperty;
import xades4j.properties.RevocationValuesProperty;
import xades4j.properties.SigAndRefsTimeStampProperty;
import xades4j.properties.SignatureTimeStampProperty;
import xades4j.properties.SigningCertificateProperty;
+import xades4j.properties.TimeStampValidationDataProperty;
/**
*
@@ -86,12 +89,21 @@ public class PropertiesDataObjectsStructureVerifier
structureVerifiers.put(CertificateValuesData.class,
new BaseEncapsulatedPKIDataStructureVerifier(CertificateValuesProperty.PROP_NAME));
+ structureVerifiers.put(AttrAuthoritiesCertValuesData.class,
+ new BaseEncapsulatedPKIDataStructureVerifier(AttrAuthoritiesCertValuesProperty.PROP_NAME));
+
structureVerifiers.put(RevocationValuesData.class,
new BaseEncapsulatedPKIDataStructureVerifier(RevocationValuesProperty.PROP_NAME));
+ structureVerifiers.put(AttributeRevocationValuesData.class,
+ new BaseEncapsulatedPKIDataStructureVerifier(AttributeRevocationValuesProperty.PROP_NAME));
+
structureVerifiers.put(ArchiveTimeStampData.class,
new BaseXAdESTimeStampDataStructureVerifier(ArchiveTimeStampProperty.PROP_NAME));
+ structureVerifiers.put(TimeStampValidationDataData.class,
+ new BaseValidationDataStructureVerifier(TimeStampValidationDataProperty.PROP_NAME));
+
structureVerifiers.put(GenericDOMData.class,
new GenericDOMDataStructureVerifier());
}
@@ -113,6 +125,12 @@ public void verifiyPropertiesDataStructure(
verifiyPropertiesDataStructure(propsData.getDataObjProps());
}
+ /**
+ * Checks if internal structure and included parameters of the property are present
+ * and sane
+ * @param propsData properties to check
+ * @throws PropertyDataStructureException
+ */
public void verifiyPropertiesDataStructure(
Collection propsData) throws PropertyDataStructureException
{
diff --git a/src/main/java/xades4j/properties/data/RevocationValuesData.java b/src/main/java/xades4j/properties/data/RevocationValuesData.java
index a42a5da8..42fc0c28 100644
--- a/src/main/java/xades4j/properties/data/RevocationValuesData.java
+++ b/src/main/java/xades4j/properties/data/RevocationValuesData.java
@@ -16,10 +16,21 @@
*/
package xades4j.properties.data;
+import java.util.Collection;
+
/**
*
* @author Luís
*/
public class RevocationValuesData extends BaseEncapsulatedPKIData
{
+ public RevocationValuesData()
+ {
+ super();
+ }
+
+ public RevocationValuesData(Collection revocationData)
+ {
+ super(revocationData);
+ }
}
diff --git a/src/main/java/xades4j/properties/data/TimeStampValidationDataData.java b/src/main/java/xades4j/properties/data/TimeStampValidationDataData.java
new file mode 100644
index 00000000..af4bafda
--- /dev/null
+++ b/src/main/java/xades4j/properties/data/TimeStampValidationDataData.java
@@ -0,0 +1,22 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.properties.data;
+
+public class TimeStampValidationDataData extends BaseValidationDataData
+{
+
+}
diff --git a/src/main/java/xades4j/providers/CertificateValidationProvider.java b/src/main/java/xades4j/providers/CertificateValidationProvider.java
index 9216ce38..7e2af78e 100644
--- a/src/main/java/xades4j/providers/CertificateValidationProvider.java
+++ b/src/main/java/xades4j/providers/CertificateValidationProvider.java
@@ -16,6 +16,7 @@
*/
package xades4j.providers;
+import java.security.cert.X509CRL;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.Collection;
@@ -46,4 +47,33 @@ ValidationData validate(
X509CertSelector certSelector,
Date validationDate,
Collection otherCerts) throws CertificateValidationException, UnexpectedJCAException;
+
+ /**
+ * adds CRLs to certificate stores of this validation provider, later to be used to
+ * validate certificates
+ *
+ * CRLs are validated whatever they have been signed by a trusted CA using trustworthy
+ * algorithms at time {@code now}.
+ *
+ *
+ * invalid CRLs are ignored
+ *
+ * @param crls set of CRLs to add
+ * @param now date at which the CRL has to be valid (isn't published after this date,
+ * CA that issued this CRL links to a valid trust anchor and used algorithms have
+ * been safe at this point in time)
+ */
+ void addCRLs(Collection crls, Date now);
+
+ /**
+ * adds intermediate and end-entity certificates used for creating cert paths
+ *
+ * Certificates are validated whatever they have been issued by a valid trust anchor
+ * at time {@code now} and using algorithms that have been safe at this point in time
+ *
invalid Certificates are ignored, certificates are not validated
+ * using CRLs or OCSP
+ * @param otherCerts set of certificates to add
+ * @param now time of validation for added certificates
+ */
+ void addCertificates(Collection otherCerts, Date now);
}
diff --git a/src/main/java/xades4j/providers/TSACertificateValidationProvider.java b/src/main/java/xades4j/providers/TSACertificateValidationProvider.java
new file mode 100644
index 00000000..3de6988a
--- /dev/null
+++ b/src/main/java/xades4j/providers/TSACertificateValidationProvider.java
@@ -0,0 +1,34 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario -QBS.
+ *
+ * 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.providers;
+
+/**
+ * {@link CertificateValidationProvider} made specifically for validating certificates
+ * used by Time Stamping Authorities.
+ *
+ * verify() method should gracefully handle certificates with time stamping extended
+ * critical key usage extension.
+ *
+ * interface made specifically to differentiate verifiers used for signature
+ * verification and used for attribute verification (TimeStamps)
+ * @author Hubert Kario
+ *
+ */
+public interface TSACertificateValidationProvider extends
+ CertificateValidationProvider
+{
+}
diff --git a/src/main/java/xades4j/providers/TimeStampVerificationData.java b/src/main/java/xades4j/providers/TimeStampVerificationData.java
new file mode 100644
index 00000000..b829794a
--- /dev/null
+++ b/src/main/java/xades4j/providers/TimeStampVerificationData.java
@@ -0,0 +1,55 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.providers;
+
+import java.util.Date;
+
+/**
+ * Container for validation data and verification result of a time stamp.
+ *
+ * Contains both all certificate and CRLs used for verification of time stamp (in
+ * {@code ValidationData} object), as well as the time inside the token.
+ *
+ * @author Hubert Kario
+ *
+ */
+public class TimeStampVerificationData
+{
+ private final ValidationData validationData;
+ private final Date timeStampDate;
+
+ public TimeStampVerificationData(
+ ValidationData validationData,
+ Date timeFromTimeStampToken)
+ {
+ if (validationData == null || timeFromTimeStampToken == null)
+ throw new NullPointerException("Neither ValidationData nor " +
+ "timeFromTimeStampToken parameters can be null");
+ this.validationData = validationData;
+ this.timeStampDate = timeFromTimeStampToken;
+ }
+
+ public ValidationData getValidationData()
+ {
+ return validationData;
+ }
+
+ public Date getTimeStampTokenTime()
+ {
+ return timeStampDate;
+ }
+}
diff --git a/src/main/java/xades4j/providers/TimeStampVerificationProvider.java b/src/main/java/xades4j/providers/TimeStampVerificationProvider.java
index 247e246b..9ddfe803 100644
--- a/src/main/java/xades4j/providers/TimeStampVerificationProvider.java
+++ b/src/main/java/xades4j/providers/TimeStampVerificationProvider.java
@@ -16,8 +16,8 @@
*/
package xades4j.providers;
-import java.util.Date;
-
+import xades4j.verification.QualifyingPropertyVerificationContext;
+
/**
* Provides verification of time-stamp tokens. This is used whenever a time-stamp
* property needs to be verified.
@@ -33,7 +33,9 @@ public interface TimeStampVerificationProvider
* @return the time-stamp
* @throws TimeStampTokenVerificationException if the token cannot be validated (see subclasses of the exception)
*/
- public Date verifyToken(
+ public TimeStampVerificationData verifyToken(
byte[] timeStampToken,
- byte[] tsDigestInput) throws TimeStampTokenVerificationException;
+ byte[] tsDigestInput,
+ QualifyingPropertyVerificationContext ctx)
+ throws TimeStampTokenVerificationException;
}
diff --git a/src/main/java/xades4j/providers/ValidationData.java b/src/main/java/xades4j/providers/ValidationData.java
index dad94b39..014df973 100644
--- a/src/main/java/xades4j/providers/ValidationData.java
+++ b/src/main/java/xades4j/providers/ValidationData.java
@@ -26,7 +26,8 @@
* Container of validation data (certificates and corresponding CRLs).
*
* Contains the full certification chain, starting with the signing certificate
- * and endind with the trust-anchor.
+ * and ending with the trust-anchor. Depending on verification profile, it may or may not
+ * contain CRLs used for checking the revocation information of certificates.
* @author Luís
*/
public class ValidationData
diff --git a/src/main/java/xades4j/providers/impl/DefaultTimeStampVerificationProvider.java b/src/main/java/xades4j/providers/impl/DefaultTimeStampVerificationProvider.java
index 7294fd26..16a52554 100644
--- a/src/main/java/xades4j/providers/impl/DefaultTimeStampVerificationProvider.java
+++ b/src/main/java/xades4j/providers/impl/DefaultTimeStampVerificationProvider.java
@@ -44,15 +44,17 @@
import org.bouncycastle.util.Selector;
import xades4j.UnsupportedAlgorithmException;
import xades4j.XAdES4jException;
-import xades4j.providers.CertificateValidationProvider;
import xades4j.providers.MessageDigestEngineProvider;
+import xades4j.providers.TSACertificateValidationProvider;
import xades4j.providers.TimeStampTokenDigestException;
import xades4j.providers.TimeStampTokenSignatureException;
import xades4j.providers.TimeStampTokenStructureException;
import xades4j.providers.TimeStampTokenTSACertException;
import xades4j.providers.TimeStampTokenVerificationException;
+import xades4j.providers.TimeStampVerificationData;
import xades4j.providers.TimeStampVerificationProvider;
import xades4j.providers.ValidationData;
+import xades4j.verification.QualifyingPropertyVerificationContext;
/**
* Default implementation of {@code TimeStampVerificationProvider}. It verifies
@@ -82,7 +84,7 @@ private static String uriForDigest(ASN1ObjectIdentifier digestalgOid)
{
return digestOidToUriMappings.get(digestalgOid);
}
- private final CertificateValidationProvider certificateValidationProvider;
+ private final TSACertificateValidationProvider tsaCertificateValidationProvider;
private final MessageDigestEngineProvider messageDigestProvider;
private final JcaSimpleSignerInfoVerifierBuilder signerInfoVerifierBuilder;
private final JcaX509CertificateConverter x509CertificateConverter;
@@ -90,10 +92,10 @@ private static String uriForDigest(ASN1ObjectIdentifier digestalgOid)
@Inject
public DefaultTimeStampVerificationProvider(
- CertificateValidationProvider certificateValidationProvider,
+ TSACertificateValidationProvider certificateValidationProvider,
MessageDigestEngineProvider messageDigestProvider)
{
- this.certificateValidationProvider = certificateValidationProvider;
+ this.tsaCertificateValidationProvider = certificateValidationProvider;
this.messageDigestProvider = messageDigestProvider;
Provider bcProv = new BouncyCastleProvider();
@@ -103,7 +105,9 @@ public DefaultTimeStampVerificationProvider(
}
@Override
- public Date verifyToken(byte[] timeStampToken, byte[] tsDigestInput) throws TimeStampTokenVerificationException
+ public TimeStampVerificationData verifyToken(byte[] timeStampToken, byte[] tsDigestInput,
+ QualifyingPropertyVerificationContext ctx)
+ throws TimeStampTokenVerificationException
{
TimeStampToken tsToken;
try
@@ -121,6 +125,7 @@ public Date verifyToken(byte[] timeStampToken, byte[] tsDigestInput) throws Time
}
X509Certificate tsaCert = null;
+ ValidationData vData = null;
try
{
/* Validate the TSA certificate */
@@ -129,10 +134,19 @@ public Date verifyToken(byte[] timeStampToken, byte[] tsDigestInput) throws Time
{
certs.add(this.x509CertificateConverter.getCertificate((X509CertificateHolder) certHolder));
}
+ if (ctx != null)
+ {
+ // add only certificates and CRLs that use currently secure algorithms
+ // and are signed by currently valid certificate authorities
+ tsaCertificateValidationProvider.addCertificates(
+ ctx.getAttributeCertificates(), ctx.getCurrentTime());
+ tsaCertificateValidationProvider.addCRLs(
+ ctx.getAttributeCRLs(), ctx.getCurrentTime());
+ }
- ValidationData vData = this.certificateValidationProvider.validate(
+ vData = this.tsaCertificateValidationProvider.validate(
x509CertSelectorConverter.getCertSelector(tsToken.getSID()),
- tsToken.getTimeStampInfo().getGenTime(),
+ (ctx == null) ? null : ctx.getCurrentTime(), // unit tests provision
certs);
tsaCert = vData.getCerts().get(0);
@@ -176,7 +190,12 @@ public Date verifyToken(byte[] timeStampToken, byte[] tsDigestInput) throws Time
throw new TimeStampTokenVerificationException("The token's digest algorithm is not supported", ex);
}
- return tsTokenInfo.getGenTime();
+ // token verified successfully, remember the validation data used for its
+ // verification
+ if (ctx != null)
+ ctx.addAttributeValidationData(vData);
+
+ return new TimeStampVerificationData(vData, tsTokenInfo.getGenTime());
}
/** Selector selecting all certificates. */
diff --git a/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProvider.java b/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProvider.java
index be297e3a..c0596daf 100644
--- a/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProvider.java
+++ b/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProvider.java
@@ -1,6 +1,6 @@
/*
* XAdES4j - A Java library for generation and verification of XAdES signatures.
- * Copyright (C) 2010 Luis Goncalves.
+ * Copyright (C) 2012 Hubert Kario - QBS.
*
* 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
@@ -16,58 +16,29 @@
*/
package xades4j.providers.impl;
-import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
-import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
-import java.security.cert.CertPathBuilder;
-import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
-import java.security.cert.PKIXCertPathBuilderResult;
-import java.security.cert.X509CRL;
-import java.security.cert.X509CRLSelector;
-import java.security.cert.X509CertSelector;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.security.auth.x500.X500Principal;
-import xades4j.providers.CannotBuildCertificationPathException;
-import xades4j.providers.CannotSelectCertificateException;
-import xades4j.providers.CertificateValidationException;
+
import xades4j.providers.CertificateValidationProvider;
-import xades4j.providers.ValidationData;
-import xades4j.verification.UnexpectedJCAException;
/**
- * Implementation of {@code CertificateValidationProvider} using a PKIX {@code CertPathBuilder}.
+ * Implementation of {@code CertificateValidationProvider} using a PKIX
+ * {@code CertPathBuilder}.
*
* Since the Java's PKIX API doesn't allow to access the CRLs used in the certification
* path validation, this is manually done. There has to be a CRL for each issuer
* in the path which is valid at the moment of validation (signature and date).
- * @author Luís
+ * @author Hubert Kario
*/
-public class PKIXCertificateValidationProvider implements CertificateValidationProvider
+public class PKIXCertificateValidationProvider
+ extends PKIXCertificateValidationProviderBase
+ implements CertificateValidationProvider
{
private static final int DEFAULT_MAX_PATH_LENGTH = 6;
- private final KeyStore trustAnchors;
- private final boolean revocationEnabled;
- private final int maxPathLength;
- private final CertStore[] intermCertsAndCrls;
- private final CertPathBuilder certPathBuilder;
- private final String signatureProvider;
-
/**
* Initializes a new instance that uses the specified JCE providers for CertPathBuilder
* and Signature.
@@ -88,19 +59,11 @@ public PKIXCertificateValidationProvider(
int maxPathLength,
String certPathBuilderProvider,
String signatureProvider,
- CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ CertStore[] intermCertsAndCrls)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (null == trustAnchors)
- {
- throw new NullPointerException("Trust anchors cannot be null");
- }
-
- this.trustAnchors = trustAnchors;
- this.revocationEnabled = revocationEnabled;
- this.maxPathLength = maxPathLength;
- this.certPathBuilder = certPathBuilderProvider == null ? CertPathBuilder.getInstance("PKIX") : CertPathBuilder.getInstance("PKIX", certPathBuilderProvider);
- this.signatureProvider = signatureProvider;
- this.intermCertsAndCrls = intermCertsAndCrls;
+ super(trustAnchors, revocationEnabled, maxPathLength, certPathBuilderProvider,
+ signatureProvider, intermCertsAndCrls);
}
/**
@@ -121,7 +84,8 @@ public PKIXCertificateValidationProvider(
boolean revocationEnabled,
String certPathBuilderProvider,
String signatureProvider,
- CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ CertStore... intermCertsAndCrls)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, certPathBuilderProvider, signatureProvider, intermCertsAndCrls);
}
@@ -211,141 +175,10 @@ public PKIXCertificateValidationProvider(
}
@Override
- public ValidationData validate(
- X509CertSelector certSelector,
- Date validationDate,
- Collection otherCerts) throws CertificateValidationException, UnexpectedJCAException
+ protected void addImplSpecificPKIXBuilderParams(PKIXBuilderParameters pkixbp)
{
- PKIXBuilderParameters builderParams;
- try
- {
- builderParams = new PKIXBuilderParameters(trustAnchors, certSelector);
- } catch (KeyStoreException ex)
- {
- throw new CannotBuildCertificationPathException(certSelector, "Trust anchors KeyStore is not initialized", ex);
- } catch (InvalidAlgorithmParameterException ex)
- {
- throw new CannotBuildCertificationPathException(certSelector, "Trust anchors KeyStore has no trusted certificate entries", ex);
- }
-
- PKIXCertPathBuilderResult builderRes;
- try
- {
- // Certificates to be used to build the certification path.
- // - The other certificates from the signature (e.g. from KeyInfo).
- if (otherCerts != null)
- {
- CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(otherCerts);
- CertStore othersCertStore = CertStore.getInstance("Collection", ccsp);
- builderParams.addCertStore(othersCertStore);
- }
- // - The external certificates/CRLs.
- for (int i = 0; i < intermCertsAndCrls.length; i++)
- {
- builderParams.addCertStore(intermCertsAndCrls[i]);
- }
-
- builderParams.setRevocationEnabled(revocationEnabled);
- builderParams.setMaxPathLength(maxPathLength);
- builderParams.setDate(validationDate);
- builderParams.setSigProvider(this.signatureProvider);
-
- builderRes = (PKIXCertPathBuilderResult) certPathBuilder.build(builderParams);
- }
- catch (CertPathBuilderException ex)
- {
- throw new CannotBuildCertificationPathException(certSelector, ex.getMessage(), ex);
- } catch (InvalidAlgorithmParameterException ex)
- {
- // SHOULD NOT be thrown due to wrong type of parameters.
- // Seems to be thrown when the CertSelector (in builderParams) criteria
- // cannot be applied.
- throw new CannotSelectCertificateException(certSelector, ex);
- } catch (NoSuchAlgorithmException ex)
- {
- // SHOULD NOT be thrown.
- throw new UnexpectedJCAException("No provider for Collection CertStore", ex);
- }
-
- // The cert path returned by the builder ends in a certificate issued by
- // the trust anchor. However, the complete path may be needed for property
- // verification.
- List certPath = (List) builderRes.getCertPath().getCertificates();
- // - Create a new list since the previous is immutable.
- certPath = new ArrayList(certPath);
- // - Add the trust anchor certificate.
- certPath.add(builderRes.getTrustAnchor().getTrustedCert());
-
- if (revocationEnabled)
- {
- return new ValidationData(certPath, getCRLsForCertPath(certPath, validationDate));
- }
- return new ValidationData(certPath);
- }
-
- private Collection getCRLsForCertPath(
- List certPath,
- Date validationDate) throws CertificateValidationException
- {
- // Map the issuers certificates in the chain. This is used to know the issuers
- // and later to verify the signatures in the CRLs.
- Map issuersCerts = new HashMap(certPath.size() - 1);
- for (int i = 0; i < certPath.size() - 1; i++)
- {
- // The issuer of one certificate is the subject of the following one.
- issuersCerts.put(certPath.get(i).getIssuerX500Principal(), certPath.get(i + 1));
- }
-
- // Select all the CRLs from the issuers involved in the certification path
- // that are valid at the moment.
- X509CRLSelector crlSelector = new X509CRLSelector();
- for (X500Principal issuer : issuersCerts.keySet())
- {
- // - "The issuer distinguished name in the X509CRL must match at least
- // one of the specified distinguished names."
- crlSelector.addIssuer(issuer);
- }
- // - "The specified date must be equal to or later than the value of the
- // thisUpdate component of the X509CRL and earlier than the value of the
- // nextUpdate component."
- crlSelector.setDateAndTime(validationDate);
-
- Set crls = new HashSet();
- try
- {
- // Get the CRLs on each CertStore.
- for (int i = 0; i < intermCertsAndCrls.length; i++)
- {
- Collection storeCRLs = intermCertsAndCrls[i].getCRLs(crlSelector);
- crls.addAll(Collections.checkedCollection(storeCRLs, X509CRL.class));
-
- }
- } catch (CertStoreException ex)
- {
- throw new CertificateValidationException(null, "Cannot get CRLs", ex);
- }
-
- // Verify the CRLs' signatures. The issuers' certificates were validated
- // as part of the cert path creation.
- for (X509CRL crl : crls)
- {
- try
- {
- X509Certificate crlIssuerCert = issuersCerts.get(crl.getIssuerX500Principal());
- if (null == this.signatureProvider)
- {
- crl.verify(crlIssuerCert.getPublicKey());
- }
- else
- {
- crl.verify(crlIssuerCert.getPublicKey(), this.signatureProvider);
- }
- }
- catch (Exception ex)
- {
- throw new CertificateValidationException(null, "Invalid CRL signature from " + crl.getIssuerX500Principal().getName(), ex);
- }
- }
- return crls;
- }
+ // no implementation specific validators
+ return;
+ }
+
}
diff --git a/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProviderBase.java b/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProviderBase.java
new file mode 100644
index 00000000..767608a6
--- /dev/null
+++ b/src/main/java/xades4j/providers/impl/PKIXCertificateValidationProviderBase.java
@@ -0,0 +1,476 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2010 Luis Goncalves.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.providers.impl;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PublicKey;
+import java.security.cert.CRL;
+import java.security.cert.CRLSelector;
+import java.security.cert.CertPathBuilder;
+import java.security.cert.CertPathBuilderException;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathBuilderResult;
+import java.security.cert.X509CRL;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import xades4j.providers.CannotBuildCertificationPathException;
+import xades4j.providers.CannotSelectCertificateException;
+import xades4j.providers.CertificateValidationException;
+import xades4j.providers.ValidationData;
+import xades4j.verification.UnexpectedJCAException;
+
+/**
+ *
+ * @author Luís
+ * @author Hubert Kario
+ *
+ */
+public abstract class PKIXCertificateValidationProviderBase
+{
+ private final KeyStore trustAnchors;
+ private final boolean revocationEnabled;
+ private final int maxPathLength;
+ private CertStore[] intermCertsAndCrls;
+ private final CertPathBuilder certPathBuilder;
+ private final String signatureProvider;
+
+ /**
+ * Initializes a new instance that uses the specified JCE providers for CertPathBuilder
+ * and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param maxPathLength the maximum length of the certification paths
+ * @param certPathBuilderProvider the CertPathBuilder provider
+ * @param signatureProvider the Signature provider
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXCertificateValidationProviderBase(
+ KeyStore trustAnchors,
+ boolean revocationEnabled,
+ int maxPathLength,
+ String certPathBuilderProvider,
+ String signatureProvider,
+ CertStore... intermCertsAndCrls)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (null == trustAnchors)
+ {
+ throw new NullPointerException("Trust anchors cannot be null");
+ }
+
+ this.trustAnchors = trustAnchors;
+ this.revocationEnabled = revocationEnabled;
+ this.maxPathLength = maxPathLength;
+ this.certPathBuilder =
+ certPathBuilderProvider == null ?
+ CertPathBuilder.getInstance("PKIX", "BC") :
+ CertPathBuilder.getInstance("PKIX", certPathBuilderProvider);
+ this.signatureProvider = signatureProvider;
+ this.intermCertsAndCrls = intermCertsAndCrls;
+ }
+
+ public ValidationData validate(
+ X509CertSelector certSelector,
+ Date validationDate,
+ Collection otherCerts)
+ throws CertificateValidationException, UnexpectedJCAException
+ {
+ PKIXBuilderParameters builderParams;
+ try
+ {
+ builderParams = new PKIXBuilderParameters(trustAnchors, certSelector);
+ } catch (KeyStoreException ex)
+ {
+ throw new CannotBuildCertificationPathException(certSelector,
+ "Trust anchors KeyStore is not initialized", ex);
+ } catch (InvalidAlgorithmParameterException ex)
+ {
+ throw new CannotBuildCertificationPathException(certSelector,
+ "Trust anchors KeyStore has no trusted certificate entries", ex);
+ }
+
+ PKIXCertPathBuilderResult builderRes;
+ try
+ {
+ // Certificates to be used to build the certification path.
+ // - The other certificates from the signature (e.g. from KeyInfo).
+ if (otherCerts != null)
+ {
+ CollectionCertStoreParameters ccsp =
+ new CollectionCertStoreParameters(otherCerts);
+ CertStore othersCertStore = CertStore.getInstance("Collection", ccsp);
+ builderParams.addCertStore(othersCertStore);
+ }
+ // - The external certificates/CRLs.
+ for (int i = 0; i < intermCertsAndCrls.length; i++)
+ {
+ builderParams.addCertStore(intermCertsAndCrls[i]);
+ }
+
+ builderParams.setRevocationEnabled(revocationEnabled);
+ builderParams.setMaxPathLength(maxPathLength);
+ builderParams.setDate(validationDate);
+ builderParams.setSigProvider(this.signatureProvider);
+ addImplSpecificPKIXBuilderParams(builderParams);
+
+ builderRes = (PKIXCertPathBuilderResult) certPathBuilder.build(builderParams);
+ }
+ catch (CertPathBuilderException ex)
+ {
+ throw new CannotBuildCertificationPathException(certSelector,
+ ex.getMessage(), ex);
+ } catch (InvalidAlgorithmParameterException ex)
+ {
+ // SHOULD NOT be thrown due to wrong type of parameters.
+ // Seems to be thrown when the CertSelector (in builderParams) criteria
+ // cannot be applied.
+ throw new CannotSelectCertificateException(certSelector, ex);
+ } catch (NoSuchAlgorithmException ex)
+ {
+ // SHOULD NOT be thrown.
+ throw new UnexpectedJCAException("No provider for Collection CertStore", ex);
+ }
+
+ // The cert path returned by the builder ends in a certificate issued by
+ // the trust anchor. However, the complete path may be needed for property
+ // verification.
+ @SuppressWarnings("unchecked")
+ List certPath =
+ (List) builderRes.getCertPath().getCertificates();
+ // - Create a new list since the previous is immutable.
+ certPath = new ArrayList(certPath);
+ // - Add the trust anchor certificate.
+ certPath.add(builderRes.getTrustAnchor().getTrustedCert());
+
+ if (revocationEnabled)
+ {
+ return new ValidationData(certPath,
+ getCRLsForCertPath(certPath, validationDate));
+ }
+ return new ValidationData(certPath);
+ }
+
+ private Collection getCRLsForCertPath(
+ List certPath,
+ Date validationDate) throws CertificateValidationException
+ {
+ // Map the issuers certificates in the chain. This is used to know the issuers
+ // and later to verify the signatures in the CRLs.
+ Map issuersCerts =
+ new HashMap(certPath.size() - 1);
+ for (int i = 0; i < certPath.size() - 1; i++)
+ {
+ // The issuer of one certificate is the subject of the following one.
+ issuersCerts.put(certPath.get(i).getIssuerX500Principal(), certPath.get(i + 1));
+ }
+
+ Set crls = new HashSet();
+ try
+ {
+ for (int i = 0; i < certPath.size() - 1; i++)
+ {
+ X509Certificate cert = certPath.get(i);
+
+ /*
+ * because the Sun X509CRLSelector is broken (won't find CRLs published
+ * in "future") we need to use our own or we won't be able to create
+ * C form from T form
+ */
+ CRLSelector crlSelector = new CustomCRLSelector(cert, validationDate);
+
+ // Get the CRLs on each CertStore.
+ for (int j = 0; j < intermCertsAndCrls.length; j++)
+ {
+ @SuppressWarnings("unchecked")
+ Collection storeCRLs =
+ (Collection) intermCertsAndCrls[j].getCRLs(crlSelector);
+ crls.addAll(Collections.checkedCollection(storeCRLs, X509CRL.class));
+ }
+ }
+ } catch (CertStoreException ex)
+ {
+ throw new CertificateValidationException(null, "Cannot get CRLs", ex);
+ }
+
+ // Verify the CRLs' signatures. The issuers' certificates were validated
+ // as part of the cert path creation.
+ for (X509CRL crl : crls)
+ {
+ try
+ {
+ X509Certificate crlIssuerCert =
+ issuersCerts.get(crl.getIssuerX500Principal());
+ if (null == this.signatureProvider)
+ {
+ crl.verify(crlIssuerCert.getPublicKey());
+ }
+ else
+ {
+ crl.verify(crlIssuerCert.getPublicKey(), this.signatureProvider);
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new CertificateValidationException(null,
+ "Invalid CRL signature from " +
+ crl.getIssuerX500Principal().getName(), ex);
+ }
+ }
+ return crls;
+ }
+
+ public void addCRLs(Collection crls, Date now)
+ {
+ if (crls == null)
+ return;
+ Collection validCRLs = new ArrayList();
+
+ for(X509CRL crl : crls)
+ {
+ // TODO check algorithms used in CRL
+
+ X509CertSelector certSel = new X509CertSelector();
+ certSel.setSubject(crl.getIssuerX500Principal());
+
+ PKIXBuilderParameters params;
+ try
+ {
+ params = new PKIXBuilderParameters(trustAnchors, certSel);
+ } catch (Exception e)
+ {
+ // parameters are invalid, ignore CRL
+ continue;
+ }
+ params.setDate(now);
+ params.setRevocationEnabled(false);
+ for (int i=0; i < intermCertsAndCrls.length; i++)
+ {
+ params.addCertStore(intermCertsAndCrls[i]);
+ }
+ addImplSpecificPKIXBuilderParams(params);
+
+ PKIXCertPathBuilderResult res;
+ try
+ {
+ res = (PKIXCertPathBuilderResult) this.certPathBuilder.build(params);
+ } catch (Exception ex)
+ {
+ // CRL is invalid, ignore
+ continue;
+ }
+
+ List extends Certificate> certs =
+ new ArrayList(res.getCertPath().getCertificates());
+ // TODO check algorithms used in this cert path
+ PublicKey crlSigningKey;
+ if (certs.size() != 0)
+ crlSigningKey = certs.get(0).getPublicKey();
+ else
+ crlSigningKey = res.getTrustAnchor().getCAPublicKey();
+ if (crlSigningKey == null)
+ crlSigningKey = res.getTrustAnchor().getTrustedCert().getPublicKey();
+
+ try
+ {
+ crl.verify(crlSigningKey);
+ } catch (Exception ex)
+ {
+ // invalid CRL, ignore
+ continue;
+ }
+
+ validCRLs.add(crl);
+ }
+
+ // don't create empty CertStores
+ if (validCRLs.size() == 0)
+ return;
+
+ CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(validCRLs);
+ CertStore crlsCertStore;
+ try
+ {
+ crlsCertStore = CertStore.getInstance("Collection", ccsp);
+ } catch (Exception e)
+ {
+ throw new RuntimeException("General crypto failure", e);
+ }
+
+ CertStore[] newIntermCertsAndCrls;
+ newIntermCertsAndCrls = Arrays.copyOf(intermCertsAndCrls, intermCertsAndCrls.length + 1);
+ newIntermCertsAndCrls[intermCertsAndCrls.length] = crlsCertStore;
+
+ intermCertsAndCrls = newIntermCertsAndCrls;
+ }
+
+ public void addCertificates(Collection otherCerts, Date now)
+ {
+ if (otherCerts == null)
+ return;
+ Collection validCerts = new ArrayList();
+
+ /*
+ * To validate certificates we need to have all issuer certificates.
+ * Needed issuer certificates can be among otherCerts.
+ *
+ * To work around this problem, we include otherCerts in PKIXBuilderParameters
+ * but add them to intermCertsAndCrls only if they validate successfully.
+ */
+ CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(otherCerts);
+ CertStore otherCertsCertStore;
+ try
+ {
+ otherCertsCertStore = CertStore.getInstance("Collection", ccsp);
+ } catch (Exception ex)
+ {
+ throw new RuntimeException("General crypto failure", ex);
+ }
+
+ // find good certificates
+ for (X509Certificate cert : otherCerts)
+ {
+ // TODO check algorithms used in certificate creation
+
+ // TODO iff certificate matches entry in TSL, add them to trustAnchors
+
+ X509CertSelector certSel = new X509CertSelector();
+ certSel.setCertificate(cert);
+
+ PKIXBuilderParameters params;
+ try {
+ params = new PKIXBuilderParameters(trustAnchors, certSel);
+ } catch (Exception e)
+ {
+ // parameters are invalid, ignore certificate
+ continue;
+ }
+ params.setDate(now);
+ params.setRevocationEnabled(false);
+ for (int i=0; i < intermCertsAndCrls.length; i++)
+ {
+ params.addCertStore(intermCertsAndCrls[i]);
+ }
+ params.addCertStore(otherCertsCertStore);
+ addImplSpecificPKIXBuilderParams(params);
+
+ PKIXCertPathBuilderResult res;
+ try
+ {
+ res = (PKIXCertPathBuilderResult)this.certPathBuilder.build(params);
+ } catch (Exception ex)
+ {
+ // certificate or certificates invalid, ignore
+ continue;
+ }
+
+ List extends Certificate> certs = res.getCertPath().getCertificates();
+ if (certs.size() == 0) // cert is a trustAnchor, we can ignore it
+ continue;
+
+ validCerts.add(cert);
+ }
+
+ ccsp = new CollectionCertStoreParameters(validCerts);
+ CertStore validCertCertStore;
+ try
+ {
+ validCertCertStore = CertStore.getInstance("Collection", ccsp);
+ } catch (Exception e)
+ {
+ throw new RuntimeException("General crypto failure", e);
+ }
+
+ CertStore[] newIntermCertsAndCrls;
+ newIntermCertsAndCrls = Arrays.copyOf(intermCertsAndCrls, intermCertsAndCrls.length + 1);
+ newIntermCertsAndCrls[intermCertsAndCrls.length] = validCertCertStore;
+
+ intermCertsAndCrls = newIntermCertsAndCrls;
+ }
+
+
+ private class CustomCRLSelector implements CRLSelector
+ {
+ private X509Certificate subjectCert;
+ private Date now;
+
+ public CustomCRLSelector(X509Certificate subjectCertificate, Date checkingDate)
+ {
+ subjectCert = subjectCertificate;
+ now = checkingDate;
+ }
+
+ public Object clone()
+ {
+ return new CustomCRLSelector(subjectCert, now);
+ }
+
+ @Override
+ public boolean match(CRL crl)
+ {
+ if (!(crl instanceof X509CRL))
+ return false;
+ X509CRL x509crl = (X509CRL) crl;
+
+ // check if issuer of CRL is the same as the issuer of the certificate
+ X500Principal principal = x509crl.getIssuerX500Principal();
+ if (!subjectCert.getIssuerX500Principal().equals(principal))
+ return false;
+
+ // CRL has to be valid for current time (but it can come from "future")
+ if (x509crl.getNextUpdate().getTime() < now.getTime())
+ return false;
+
+ // CRL must be published before certificate looses its validity
+ if (x509crl.getThisUpdate().getTime() >= subjectCert.getNotAfter().getTime())
+ return false;
+
+ return true;
+ }
+ }
+
+ /**
+ * Add usage or implementation specific handlers to CertPathBuilderParameters
+ * @param pkixbp
+ */
+ protected abstract void addImplSpecificPKIXBuilderParams(PKIXBuilderParameters pkixbp);
+}
diff --git a/src/main/java/xades4j/providers/impl/PKIXTSACertificateValidationProvider.java b/src/main/java/xades4j/providers/impl/PKIXTSACertificateValidationProvider.java
new file mode 100644
index 00000000..2863ee81
--- /dev/null
+++ b/src/main/java/xades4j/providers/impl/PKIXTSACertificateValidationProvider.java
@@ -0,0 +1,243 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.providers.impl;
+
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXCertPathChecker;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import xades4j.providers.TSACertificateValidationProvider;
+
+/**
+ * @author Luís
+ * @author Hubert Kario
+ */
+public class PKIXTSACertificateValidationProvider
+ extends PKIXCertificateValidationProviderBase
+ implements TSACertificateValidationProvider
+{
+ private static final int DEFAULT_MAX_PATH_LENGTH = 6;
+
+ /**
+ * Initializes a new instance that uses the specified JCE providers for CertPathBuilder
+ * and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param maxPathLength the maximum length of the certification paths
+ * @param certPathBuilderProvider the CertPathBuilder provider
+ * @param signatureProvider the Signature provider
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXTSACertificateValidationProvider(KeyStore trustAnchors,
+ boolean revocationEnabled, int maxPathLength,
+ String certPathBuilderProvider, String signatureProvider,
+ CertStore[] intermCertsAndCrls) throws NoSuchAlgorithmException,
+ NoSuchProviderException
+ {
+ super(trustAnchors, revocationEnabled, maxPathLength, certPathBuilderProvider,
+ signatureProvider, intermCertsAndCrls);
+ }
+
+ /**
+ * Initializes a new instance that uses the specified JCE providers for CertPathBuilder
+ * and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param certPathBuilderProvider the CertPathBuilder provider
+ * @param signatureProvider the Signature provider
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXTSACertificateValidationProvider(
+ KeyStore trustAnchors,
+ boolean revocationEnabled,
+ String certPathBuilderProvider,
+ String signatureProvider,
+ CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, certPathBuilderProvider, signatureProvider, intermCertsAndCrls);
+ }
+
+ /**
+ * Initializes a new instance that uses the specified JCE provider for both
+ * CertPathBuilder and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param maxPathLength the maximum length of the certification paths
+ * @param jceProvider the CertPathBuilder and Signature provider
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXTSACertificateValidationProvider(
+ KeyStore trustAnchors,
+ boolean revocationEnabled,
+ int maxPathLength,
+ String jceProvider,
+ CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ this(trustAnchors, revocationEnabled, maxPathLength, jceProvider, jceProvider, intermCertsAndCrls);
+ }
+
+ /**
+ * Initializes a new instance that uses the specified JCE provider for both
+ * CertPathBuilder and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param jceProvider the CertPathBuilder and Signature provider
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXTSACertificateValidationProvider(
+ KeyStore trustAnchors,
+ boolean revocationEnabled,
+ String jceProvider,
+ CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, jceProvider, intermCertsAndCrls);
+ }
+
+ /**
+ * Initializes a new instance without specifying the JCE providers for CertPathBuilder
+ * and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param maxPathLength the maximum length of the certification paths
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXTSACertificateValidationProvider(
+ KeyStore trustAnchors,
+ boolean revocationEnabled,
+ int maxPathLength,
+ CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ this(trustAnchors, revocationEnabled, maxPathLength, null, null, intermCertsAndCrls);
+ }
+
+ /**
+ * Initializes a new instance without specifying the JCE providers for CertPathBuilder
+ * and Signature.
+ * @param trustAnchors the keystore with the trust-anchors ({@code TrustedCertificateEntry})
+ * @param revocationEnabled whether revocation is enabled
+ * @param intermCertsAndCrls a set of {@code CertStore}s that contain certificates to be
+ * used in the construction of the certification path. May contain CRLs to be used
+ * if revocation is enabled
+ * @see xades4j.utils.FileSystemDirectoryCertStore
+ * @throws NoSuchAlgorithmException if there is no provider for PKIX CertPathBuilder
+ */
+ public PKIXTSACertificateValidationProvider(
+ KeyStore trustAnchors,
+ boolean revocationEnabled,
+ CertStore... intermCertsAndCrls) throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ this(trustAnchors, revocationEnabled, DEFAULT_MAX_PATH_LENGTH, null, null, intermCertsAndCrls);
+ }
+
+ @Override
+ protected void addImplSpecificPKIXBuilderParams(PKIXBuilderParameters pkixbp)
+ {
+ pkixbp.addCertPathChecker(new TimeStampingPropertyChecker());
+ }
+
+ private class TimeStampingPropertyChecker extends PKIXCertPathChecker
+ {
+ private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37";
+ private static final String TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8";
+
+ @Override
+ public void check(Certificate cert,
+ Collection unresolvedCritExts)
+ throws CertPathValidatorException
+ {
+ X509Certificate myCert = (X509Certificate) cert;
+
+ // can't do anything meaningful
+ if (!unresolvedCritExts.contains(EXTENDED_KEY_USAGE_OID))
+ return;
+
+ List extendedKeyUses;
+ try
+ {
+ extendedKeyUses = myCert.getExtendedKeyUsage();
+ } catch (CertificateParsingException e)
+ {
+ e.printStackTrace();
+ throw new CertPathValidatorException("Can't parse certificate!");
+ }
+
+ for (int i = 0; i < extendedKeyUses.size(); i++)
+ {
+ if (extendedKeyUses.get(i).equals(TIMESTAMPING_OID))
+ {
+ unresolvedCritExts.remove(EXTENDED_KEY_USAGE_OID);
+ return;
+ }
+ }
+ throw new CertPathValidatorException(
+ "Certificate does not allow for Time Stamping");
+ }
+
+ @Override
+ public Set getSupportedExtensions()
+ {
+ Set supportedExtensions = new HashSet();
+ supportedExtensions.add(TIMESTAMPING_OID);
+ return supportedExtensions;
+ }
+
+ @Override
+ public void init(boolean forward) throws CertPathValidatorException
+ {
+ if (forward)
+ throw new CertPathValidatorException(
+ "Forward Cert Path checking not supported!");
+ }
+
+ @Override
+ public boolean isForwardCheckingSupported()
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/xades4j/utils/FileSystemDirectoryCertStore.java b/src/main/java/xades4j/utils/FileSystemDirectoryCertStore.java
index 519ef249..b25d53ef 100644
--- a/src/main/java/xades4j/utils/FileSystemDirectoryCertStore.java
+++ b/src/main/java/xades4j/utils/FileSystemDirectoryCertStore.java
@@ -18,7 +18,8 @@
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -162,16 +163,30 @@ private void transverseDirToFindContent(
if (f.isDirectory())
transverseDirToFindContent(f, contentList, certsFilesExts, crlsFilesExts, cf);
else if (f.isFile())
- try
- {
- if (hasExt(f, certsFilesExts))
- contentList.add((X509Certificate)cf.generateCertificate(new FileInputStream(f)));
- else if (hasExt(f, crlsFilesExts))
- contentList.add((X509CRL)cf.generateCRL(new FileInputStream(f)));
- } catch (FileNotFoundException ex)
- {
- // The file existed right up there! If somehow it doesn't exist
- // now, nevermind.
+ if (hasExt(f, certsFilesExts)) {
+ try {
+ InputStream is = new FileInputStream(f);
+ try {
+ contentList.add((X509Certificate) cf.generateCertificate(is));
+ } finally {
+ is.close();
+ }
+ } catch (IOException e) {
+ // The file existed and somehow it doesn't exist now, or
+ // it was not possible to close is, nevermind.
+ }
+ } else if (hasExt(f, crlsFilesExts)) {
+ try {
+ InputStream is = new FileInputStream(f);
+ try {
+ contentList.add((X509CRL) cf.generateCRL(is));
+ } finally {
+ is.close();
+ }
+ } catch (IOException e) {
+ // The file existed and somehow it doesn't exist now, or
+ // it was not possible to close is, nevermind.
+ }
}
}
}
diff --git a/src/main/java/xades4j/utils/PropertiesList.java b/src/main/java/xades4j/utils/PropertiesList.java
new file mode 100644
index 00000000..2fab1d96
--- /dev/null
+++ b/src/main/java/xades4j/utils/PropertiesList.java
@@ -0,0 +1,136 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import xades4j.properties.PropertyTargetException;
+
+/**
+ * A generic bag of properties used to store properties that apply to a specific target
+ * (data object descriptions, signature properties collector.
+ *
+ * @author Hubert Kario
+ */
+public class PropertiesList
+{
+ List properties;
+ Set> classes;
+
+ /**
+ * Initializes the property bag with the given number of different initial property
+ * types.
+ *
+ * The order in which the properties are added is maintained.
+ * @param initialNPropTypes the initial number of different property types.
+ */
+ public PropertiesList(int initialNPropTypes)
+ {
+ this.properties = new ArrayList(initialNPropTypes);
+ this.classes = new HashSet>();
+ }
+
+ /**
+ * Puts a property in the bag. The put operation doesn't allow repeated property
+ * types. If a property of this type was previously added an exception is
+ * thrown.
+ *
+ * @param prop the property
+ *
+ * @throws NullPointerException if {@code prop} is {@code null}
+ * @throws PropertyTargetException if the given property type is already present in
+ * the bag
+ */
+ public void put(T prop)
+ {
+ if (prop == null)
+ throw new NullPointerException("Property cannot be null");
+
+ if(classes.contains(prop.getClass()))
+ throw new PropertyTargetException(String.format(
+ "A property of type %s was already added",
+ prop.getClass().getSimpleName()));
+
+ classes.add(prop.getClass());
+ properties.add(prop);
+ }
+
+ /**
+ * Adds a property to the bag. The add operation allows multiple properties of the
+ * same type and repeated instances.
+ *
+ * @param prop the property
+ * @throws NullPointerExceptino if {@code prop} is {@code null}
+ */
+ public void add(T prop)
+ {
+ if (prop == null)
+ throw new NullPointerException("Property cannot be null");
+
+ if (!classes.contains(prop.getClass()))
+ classes.add(prop.getClass());
+ properties.add(prop);
+ }
+
+ /**
+ * Removes a property from the bag.
+ *
+ * @param prop the property to be removed
+ * @throws NullPointerException if the property is {@code null}
+ * @throws IllegalStateException if the property is not present
+ */
+ public void remove(T prop)
+ {
+ if (prop == null)
+ throw new NullPointerException("Property cannot be null");
+
+ if (!classes.remove(prop.getClass()))
+ throw new IllegalStateException("Property not present");
+ if (!properties.remove(prop))
+ throw new IllegalStateException("Property not present");
+ }
+
+ /**
+ * Indicates whatever the bag has any properties
+ * @return {@code true} if the bag has no properties
+ */
+ public boolean isEmpty()
+ {
+ return properties.isEmpty();
+ }
+
+ /**
+ * Gets the properties in the bag
+ * @return unmodifiable list of properties
+ */
+ public List getProperties()
+ {
+ if (properties.isEmpty())
+ return Collections.emptyList();
+
+ return Collections.unmodifiableList(properties);
+ }
+
+ public int size()
+ {
+ return properties.size();
+ }
+}
diff --git a/src/main/java/xades4j/utils/PropertiesSet.java b/src/main/java/xades4j/utils/PropertiesSet.java
index 29a1f278..f99ba821 100644
--- a/src/main/java/xades4j/utils/PropertiesSet.java
+++ b/src/main/java/xades4j/utils/PropertiesSet.java
@@ -18,10 +18,10 @@
import xades4j.properties.PropertyTargetException;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -34,7 +34,7 @@
*/
public class PropertiesSet
{
- private final Map> properties;
+ private final Map, Set> properties;
/**
* Initializes the property bag with the given initial diferent property types.
@@ -42,7 +42,7 @@ public class PropertiesSet
*/
public PropertiesSet(int initialNPropTypes)
{
- this.properties = new HashMap>(initialNPropTypes);
+ this.properties = new HashMap, Set>(initialNPropTypes);
}
/**
@@ -132,12 +132,12 @@ public boolean isEmpty()
* Gets the properties in the bag.
* @return un unmodifiable collection of properties
*/
- public Collection getProperties()
+ public List getProperties()
{
if (properties.isEmpty())
return Collections.emptyList();
- Collection props = new ArrayList(properties.size() + 3);
+ List props = new ArrayList(properties.size() + 3);
for (Set propsOfType : properties.values())
{
props.addAll(propsOfType);
diff --git a/src/main/java/xades4j/utils/PropertiesUtils.java b/src/main/java/xades4j/utils/PropertiesUtils.java
index c8184a83..e0a771e2 100644
--- a/src/main/java/xades4j/utils/PropertiesUtils.java
+++ b/src/main/java/xades4j/utils/PropertiesUtils.java
@@ -16,22 +16,32 @@
*/
package xades4j.utils;
+import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+
+import xades4j.properties.AllDataObjsTimeStampProperty;
import xades4j.properties.ArchiveTimeStampProperty;
+import xades4j.properties.AttrAuthoritiesCertValuesProperty;
+import xades4j.properties.AttributeRevocationValuesProperty;
+import xades4j.properties.BaseXAdESTimeStampProperty;
import xades4j.properties.CertificateValuesProperty;
import xades4j.properties.CompleteCertificateRefsProperty;
import xades4j.properties.CompleteRevocationRefsProperty;
+import xades4j.properties.IndividualDataObjsTimeStampProperty;
import xades4j.properties.RevocationValuesProperty;
import xades4j.properties.SigAndRefsTimeStampProperty;
import xades4j.properties.SignaturePolicyBase;
import xades4j.properties.SignatureTimeStampProperty;
import xades4j.properties.SignedSignatureProperty;
+import xades4j.properties.TimeStampValidationDataProperty;
import xades4j.properties.UnsignedSignatureProperty;
import xades4j.providers.SignaturePolicyInfoProvider;
import xades4j.providers.ValidationData;
+import xades4j.verification.XAdESVerificationResult;
/**
*
@@ -39,6 +49,8 @@
*/
public class PropertiesUtils
{
+ private static final long ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
+
private PropertiesUtils()
{
}
@@ -79,10 +91,21 @@ public static void addXadesXProperties(
public static void addXadesXLProperties(
Collection usp,
- ValidationData vData)
+ ValidationData vData,
+ Collection tstValData)
{
usp.add(new CertificateValuesProperty(vData.getCerts()));
usp.add(new RevocationValuesProperty(vData.getCrls()));
+
+ Collection allTSACerts = new HashSet();
+ Collection allTSACRLs = new HashSet();
+ for (ValidationData valData : tstValData)
+ {
+ allTSACerts.addAll(valData.getCerts());
+ allTSACRLs.addAll(valData.getCrls());
+ }
+ usp.add(new AttrAuthoritiesCertValuesProperty(allTSACerts));
+ usp.add(new AttributeRevocationValuesProperty(allTSACRLs));
}
public static void addXadesAProperties(
@@ -90,4 +113,155 @@ public static void addXadesAProperties(
{
usp.add(new ArchiveTimeStampProperty());
}
+
+ public static void addXadesAVDProperties(
+ Collection usp,
+ XAdESVerificationResult res)
+ {
+ /*
+ * The problem: the only CRLs that can contribute to validation of already
+ * time stamped time stamps (SigAndRefsTimeStamp when the last time stamp is
+ * AchiveTimeStamp) are ones that have been published after the time of last
+ * time stamp. See "grace period" in XAdES standard.
+ *
+ * The problem is multiplied by the fact, that we can have multiple
+ * ArchiveTimeStamps from different TSAs created in short succession.
+ *
+ * To detect which CRLs are published after the grace period, we assume that the
+ * sum of grace period time and the difference between time of creation of
+ * ArchiveTimeStamps is no greater than 1 week.
+ * We then add only CRLs that have been published a week after
+ */
+ Collection allCertificates = new HashSet();
+ Collection crlsAfterGracePeriod = new HashSet();
+
+ Collection validationTimeStamps =
+ new ArrayList(
+ res.getPropertiesFilter().getOfType(AllDataObjsTimeStampProperty.class));
+ validationTimeStamps.addAll(
+ res.getPropertiesFilter().getOfType(IndividualDataObjsTimeStampProperty.class));
+ validationTimeStamps.addAll(
+ res.getPropertiesFilter().getOfType(SignatureTimeStampProperty.class));
+ validationTimeStamps.addAll(
+ res.getPropertiesFilter().getOfType(SigAndRefsTimeStampProperty.class));
+ validationTimeStamps.addAll(
+ res.getPropertiesFilter().getOfType(ArchiveTimeStampProperty.class));
+
+ /* get validation data that may be useful to add to TimeStampValidationData */
+ for (BaseXAdESTimeStampProperty ts : validationTimeStamps)
+ {
+ allCertificates.addAll(ts.getValidationData().getCerts());
+
+ for (X509CRL crl : ts.getValidationData().getCrls())
+ {
+ // see big comment above
+ if (ts.getTime().getTime() + ONE_WEEK < crl.getThisUpdate().getTime())
+ crlsAfterGracePeriod.add(crl);
+ }
+ }
+
+ Collection savedCertificates = new ArrayList();
+ Collection savedCRLs = new ArrayList();
+
+ // collect all CRLs already present in signature
+ Collection revValProps =
+ res.getPropertiesFilter().getOfType(RevocationValuesProperty.class);
+ Collection attrRevValProps =
+ res.getPropertiesFilter().getOfType(AttributeRevocationValuesProperty.class);
+ Collection tsValDatProps =
+ res.getPropertiesFilter().getOfType(TimeStampValidationDataProperty.class);
+ for (RevocationValuesProperty revValProp : revValProps)
+ {
+ savedCRLs.addAll(revValProp.getCrls());
+ }
+ for (AttributeRevocationValuesProperty attrRevValProp : attrRevValProps)
+ {
+ savedCRLs.addAll(attrRevValProp.getCrls());
+ }
+ for (TimeStampValidationDataProperty tsValDataProp : tsValDatProps)
+ {
+ savedCRLs.addAll(tsValDataProp.getCrls());
+ savedCertificates.addAll(tsValDataProp.getCertificates());
+ }
+
+ // collect all certificates specified in properties (there can be certificates
+ // in time stamp tokens or basic XML signature KeyInfo, but duplication of them
+ // is not an error in itself)
+ Collection certValProps =
+ res.getPropertiesFilter().getOfType(CertificateValuesProperty.class);
+ Collection attrAuthCerValProps =
+ res.getPropertiesFilter().getOfType(AttrAuthoritiesCertValuesProperty.class);
+ for (CertificateValuesProperty cvProp : certValProps)
+ {
+ savedCertificates.addAll(cvProp.getCertificates());
+ }
+ for (AttrAuthoritiesCertValuesProperty aacvProp : attrAuthCerValProps)
+ {
+ savedCertificates.addAll(aacvProp.getCertificates());
+ }
+
+ // remove already saved validation information
+ Collection certsToSave =
+ new ArrayList(allCertificates);
+ Collection crlsToSave = new ArrayList(crlsAfterGracePeriod);
+ certsToSave.removeAll(savedCertificates);
+ crlsToSave.removeAll(savedCRLs);
+
+ // don't create empty property
+ if ((!certsToSave.isEmpty()) || (!crlsToSave.isEmpty()))
+ usp.add(new TimeStampValidationDataProperty(certsToSave, crlsToSave));
+ }
+
+ /**
+ * Walk over all properties with time stamps that can appear before X-L form
+ * creation and extract Validation Data from each and every one of them.
+ */
+ public static Collection extractTTimeStampValidationData(
+ XAdESVerificationResult res)
+ {
+ Collection tTimeStampValidationData =
+ new ArrayList();
+
+ /*
+ * Collect validation data of properties previous to the last time stamp
+ * (SigAndRefsTimeStamp or RefsOnlyTimeStamp).
+ *
+ * This is done because the SigAndRefsTimeStamp must be valid using
+ * current revocation information, the previous time stamps may be invalid
+ * using currently available revocation information. In effect we save
+ * only the information that will not change in future.
+ *
+ * To reduce amount of information needed to add in the future, we add all
+ * certificates needed to verify the SigAndRefsTimeStamp too
+ */
+ Collection allDataObjTSProps =
+ res.getPropertiesFilter().getOfType(AllDataObjsTimeStampProperty.class);
+ Collection indivDataObjTSProps =
+ res.getPropertiesFilter().getOfType(IndividualDataObjsTimeStampProperty.class);
+ Collection sigTSProps =
+ res.getPropertiesFilter().getOfType(SignatureTimeStampProperty.class);
+ Collection sigAndRefsProps =
+ res.getPropertiesFilter().getOfType(SigAndRefsTimeStampProperty.class);
+
+ for (AllDataObjsTimeStampProperty tsProp : allDataObjTSProps)
+ {
+ tTimeStampValidationData.add(tsProp.getValidationData());
+ }
+ for (IndividualDataObjsTimeStampProperty tsProp : indivDataObjTSProps)
+ {
+ tTimeStampValidationData.add(tsProp.getValidationData());
+ }
+ for (SignatureTimeStampProperty tsProp : sigTSProps)
+ {
+ tTimeStampValidationData.add(tsProp.getValidationData());
+ }
+ for (SigAndRefsTimeStampProperty tsProp : sigAndRefsProps)
+ {
+ ValidationData savedValData;
+ savedValData = tsProp.getValidationData();
+ ValidationData newValData = new ValidationData(savedValData.getCerts());
+ tTimeStampValidationData.add(newValData);
+ }
+ return tTimeStampValidationData;
+ }
}
diff --git a/src/main/java/xades4j/verification/AllDataObjsTimeStampVerifier.java b/src/main/java/xades4j/verification/AllDataObjsTimeStampVerifier.java
index 1932efaa..582bd24d 100644
--- a/src/main/java/xades4j/verification/AllDataObjsTimeStampVerifier.java
+++ b/src/main/java/xades4j/verification/AllDataObjsTimeStampVerifier.java
@@ -18,7 +18,11 @@
import com.google.inject.Inject;
import java.util.Collection;
+
+import org.w3c.dom.Element;
+
import xades4j.properties.AllDataObjsTimeStampProperty;
+import xades4j.properties.BaseXAdESTimeStampProperty;
import xades4j.utils.CannotAddDataToDigestInputException;
import xades4j.properties.QualifyingProperty;
import xades4j.utils.TimeStampDigestInput;
@@ -42,7 +46,12 @@ public AllDataObjsTimeStampVerifier(
}
@Override
- protected QualifyingProperty addPropSpecificTimeStampInputAndCreateProperty(AllDataObjsTimeStampData propData, TimeStampDigestInput digestInput, QualifyingPropertyVerificationContext ctx) throws CannotAddDataToDigestInputException
+ protected BaseXAdESTimeStampProperty addPropSpecificTimeStampInputAndCreateProperty(
+ AllDataObjsTimeStampData propData,
+ Element location,
+ TimeStampDigestInput digestInput,
+ QualifyingPropertyVerificationContext ctx)
+ throws CannotAddDataToDigestInputException
{
Collection dataObjs = ctx.getSignedObjectsData().getAllDataObjects();
@@ -53,4 +62,11 @@ protected QualifyingProperty addPropSpecificTimeStampInputAndCreateProperty(AllD
return new AllDataObjsTimeStampProperty();
}
+
+ @Override
+ protected void updateContextAfterVerification(QualifyingProperty prop,
+ QualifyingPropertyVerificationContext ctx)
+ {
+ // noop
+ }
}
diff --git a/src/main/java/xades4j/verification/ArchiveTimeStampVerifier.java b/src/main/java/xades4j/verification/ArchiveTimeStampVerifier.java
new file mode 100644
index 00000000..8e32526b
--- /dev/null
+++ b/src/main/java/xades4j/verification/ArchiveTimeStampVerifier.java
@@ -0,0 +1,301 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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 org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.ObjectContainer;
+import org.apache.xml.security.signature.Reference;
+import org.apache.xml.security.signature.SignedInfo;
+import org.apache.xml.security.utils.Constants;
+import org.w3c.dom.Element;
+
+import com.google.inject.Inject;
+
+import xades4j.properties.ArchiveTimeStampProperty;
+import xades4j.properties.AttrAuthoritiesCertValuesProperty;
+import xades4j.properties.AttributeRevocationValuesProperty;
+import xades4j.properties.BaseXAdESTimeStampProperty;
+import xades4j.properties.CertificateValuesProperty;
+import xades4j.properties.CompleteCertificateRefsProperty;
+import xades4j.properties.CompleteRevocationRefsProperty;
+import xades4j.properties.CounterSignatureProperty;
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.RevocationValuesProperty;
+import xades4j.properties.SigAndRefsTimeStampProperty;
+import xades4j.properties.SignatureTimeStampProperty;
+import xades4j.properties.TimeStampValidationDataProperty;
+import xades4j.properties.data.ArchiveTimeStampData;
+import xades4j.providers.TimeStampVerificationProvider;
+import xades4j.utils.CannotAddDataToDigestInputException;
+import xades4j.utils.DOMHelper;
+import xades4j.utils.TimeStampDigestInput;
+import xades4j.utils.TimeStampDigestInputFactory;
+
+public class ArchiveTimeStampVerifier extends
+ TimeStampVerifierBase
+{
+
+ @Inject
+ public ArchiveTimeStampVerifier(
+ TimeStampVerificationProvider timeStampVerifier,
+ TimeStampDigestInputFactory timeStampDigestInputFactory)
+ {
+ super(timeStampVerifier, timeStampDigestInputFactory,
+ ArchiveTimeStampProperty.PROP_NAME);
+ }
+
+ @Override
+ protected BaseXAdESTimeStampProperty addPropSpecificTimeStampInputAndCreateProperty(
+ ArchiveTimeStampData propData, Element location,
+ TimeStampDigestInput digestInput,
+ QualifyingPropertyVerificationContext ctx)
+ throws CannotAddDataToDigestInputException,
+ TimeStampVerificationException
+ {
+ // Archive time stamp is taken over: References, SignedInfor, SignatureValue,
+ // KeyInfo and all UnsignedSignatureProperties in order of appearance
+
+ // References, processed accordingly to XML-DSIG.
+ SignedInfo signedInfo = ctx.getSignature().getSignedInfo();
+ try
+ {
+ for (int i=0; i < signedInfo.getLength(); i++)
+ {
+ Reference ref = signedInfo.item(i);
+ digestInput.addReference(ref);
+ }
+ } catch (XMLSecurityException e)
+ {
+ throw new CannotAddDataToDigestInputException(e);
+ }
+
+ // SignedInfo
+ Element e = ctx.getSignature().getSignedInfo().getElement();
+ digestInput.addNode(e);
+
+ // SignatureValue.
+ e = DOMHelper.getFirstDescendant(
+ ctx.getSignature().getElement(),
+ Constants.SignatureSpecNS, Constants._TAG_SIGNATUREVALUE);
+ digestInput.addNode(e);
+
+ // KeyInfo, if present
+ KeyInfo ki = ctx.getSignature().getKeyInfo();
+ if (ki != null)
+ digestInput.addNode(ki.getElement());
+
+ /*
+ * XAdES v1.4.2 standard, section G.2.2.16.2.4, implicit mechanism: "
+ * 1) Step 5) is performed as indicated. The verifier will take,
+ * among the unsigned properties that appear before the property that
+ * is being verified, those that appear in the following list, and in
+ * their order of appearance: SignatureTimeStamp, CounterSignature,
+ * CompleteCertificateRefs, CompleteRevocationRefs,
+ * AttributeCertificateRefs, AttributeRevocationRefs,
+ * CertificateValues, RevocationValues, SigAndRefsTimeStamp,
+ * RefsOnlyTimeStamp, xadesv141:ArchiveTimeStamp,
+ * xadesv141:TimeStampDataValidation and all the ds:Object elements
+ * different to the one containing the QualifyingProperties."
+ *
+ * section 8.2.1, item 4), requires the presence of CertificateValues and
+ * RevocationValues. If the signature contains other TimeStamps then
+ * AttrAuthoritiesCertValues and AttributeRevocationValues must be present,
+ * but only if Attribute Authorities don't share CRLs/OCSP or (sub)CAs with
+ * Signature. Because of that, we will only require presence of CertValues and
+ * RevocationValues.
+ */
+ boolean certificateValuesPresent = false;
+ boolean revocationValuesPresent = false;
+ // TODO test with document extended from T to X-L form without C and X intermediates
+
+ // requirements from SigAndRefsTimeStamp, only enforce singletonity, not presence
+ boolean completeCertRefsPresent = false;
+ boolean completeRevocRefsPresent = false;
+
+ // all previous properties in order of appearance
+ for(Element elem = DOMHelper.getFirstChildElement(location.getParentNode());
+ elem != location;
+ elem = DOMHelper.getNextSiblingElement(elem))
+ {
+ if (isElementMatchingProperty(elem,
+ SignatureTimeStampProperty.class))
+ {
+ // there are no specific requirements for SignatureTimeStamp
+ // so just add them
+ digestInput.addNode(elem);
+ // TODO check if there are no SignatureTimestamps *after*
+ // SigAndRefsTimeStamp
+ } else if (isElementMatchingProperty(elem,
+ CounterSignatureProperty.class))
+ {
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ CompleteCertificateRefsProperty.class))
+ {
+ // there must be exactly one CompleteCertificateRefs element
+ if (completeCertRefsPresent)
+ throw new CannotAddDataToDigestInputException(
+ new Exception(
+ "Duplicate CompleteCertificateRefs property"
+ + " in Signature"));
+ completeCertRefsPresent = true;
+ digestInput.addNode(elem);
+ // TODO check if there are no CompleteCertificateRefs
+ // *after* SigAndRefsTimeStamp
+ } else if (isElementMatchingProperty(elem,
+ CompleteRevocationRefsProperty.class))
+ {
+ // there must be exactly one CompleteRevocationRefs element
+ if (completeRevocRefsPresent)
+ throw new CannotAddDataToDigestInputException(
+ new Exception(
+ "Duplicate CompleteRevocationRefs property"
+ + " in Singature"));
+ completeRevocRefsPresent = true;
+ digestInput.addNode(elem);
+ // TODO check if there are no CompleteRevocationRefs *after*
+ // SigAndRefsTimeStamp
+ } else if (elem.getLocalName().equalsIgnoreCase(
+ "AttributeCertificateRefs")
+ && elem.getNamespaceURI().equalsIgnoreCase(
+ QualifyingProperty.XADES_XMLNS))
+ {
+ // TODO implement AttributeCertificateRefs support
+ throw new CannotAddDataToDigestInputException(
+ new Exception("Can't verify SigAndRefsTimeStamp: "
+ + "AttributeCertificateRefs is unsupported"));
+ } else if (elem.getLocalName().equalsIgnoreCase(
+ "AttributeRevocationRefs")
+ && elem.getNamespaceURI().equalsIgnoreCase(
+ QualifyingProperty.XADES_XMLNS))
+ {
+ // TODO implement AttributeRevocationRefs support
+ throw new CannotAddDataToDigestInputException(
+ new Exception("Can't verify SigAndRefsTimeStamp: "
+ + "AttributeRevocationRefs is unsupported"));
+ } else if (isElementMatchingProperty(elem,
+ CertificateValuesProperty.class))
+ {
+ if (certificateValuesPresent)
+ throw new CannotAddDataToDigestInputException(new Exception(
+ "Duplicate CertificateValues property in Signature"));
+
+ certificateValuesPresent = true;
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ RevocationValuesProperty.class))
+ {
+ if (revocationValuesPresent)
+ throw new CannotAddDataToDigestInputException(new Exception(
+ "Duplicate RevocationValues property in Signature"));
+ revocationValuesPresent = true;
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ SigAndRefsTimeStampProperty.class))
+ {
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ AttrAuthoritiesCertValuesProperty.class))
+ {
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ AttributeRevocationValuesProperty.class))
+ {
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ ArchiveTimeStampProperty.class))
+ {
+ digestInput.addNode(elem);
+ } else if (isElementMatchingProperty(elem,
+ TimeStampValidationDataProperty.class))
+ {
+ digestInput.addNode(elem);
+ } else {
+ // TS 101 903 V1.4.1 defined new unsigned properties making use
+ // of the extension mechanism specified in
+ // xades:UnsignedSignatureProperties, namely the element.
+ digestInput.addNode(elem);
+ }
+ }
+
+ /* take "all the ds:Object elements different to the one
+ * containing the QualifyingProperties." */
+ for (int i = 0; i < ctx.getSignature().getObjectLength(); i++)
+ {
+ ObjectContainer obj = ctx.getSignature().getObjectItem(i);
+ if (null == DOMHelper.getFirstDescendant(obj.getElement(), QualifyingProperty.XADES_XMLNS, "*"))
+ digestInput.addNode(obj.getElement());
+ }
+
+ if (certificateValuesPresent && revocationValuesPresent)
+ return new ArchiveTimeStampProperty();
+ else
+ throw new CannotAddDataToDigestInputException(new Exception(
+ "Missing mandatory properties: CertificateValues"
+ + " or RevocationValues"));
+ }
+
+
+ private boolean isElementMatchingProperty(Element elem,
+ Class extends QualifyingProperty> prop)
+ {
+ try
+ {
+ if (prop.equals(ArchiveTimeStampProperty.class) ||
+ prop.equals(TimeStampValidationDataProperty.class))
+ return elem.getLocalName().equalsIgnoreCase(
+ (String) prop.getField("PROP_NAME").get(null))
+ && elem.getNamespaceURI().equalsIgnoreCase(
+ (String) prop.getField("XADESV141_XMLNS").get(null));
+ else
+ return elem.getLocalName().equalsIgnoreCase(
+ (String) prop.getField("PROP_NAME").get(null))
+ && elem.getNamespaceURI().equalsIgnoreCase(
+ (String) prop.getField("XADES_XMLNS").get(null));
+ } catch (IllegalArgumentException e)
+ {
+ e.printStackTrace();
+ throw new InternalError("Wrong property class");
+ } catch (SecurityException e)
+ {
+ e.printStackTrace();
+ throw new InternalError("Wrong property class");
+ } catch (IllegalAccessException e)
+ {
+ e.printStackTrace();
+ throw new InternalError("Wrong property class");
+ } catch (NoSuchFieldException e)
+ {
+ e.printStackTrace();
+ throw new InternalError("Wrong property class");
+ }
+ }
+
+ @Override
+ protected void updateContextAfterVerification(QualifyingProperty prop,
+ QualifyingPropertyVerificationContext ctx)
+ {
+ if (!(prop instanceof ArchiveTimeStampProperty))
+ throw new RuntimeException("Can't update time after verification"
+ + " of ArchiveTimeStamp");
+
+ ArchiveTimeStampProperty archivTS = (ArchiveTimeStampProperty) prop;
+ ctx.setCurrentTime(archivTS.getTime());
+ }
+}
diff --git a/src/main/java/xades4j/verification/AttrAuthoritiesCertValuesVerifier.java b/src/main/java/xades4j/verification/AttrAuthoritiesCertValuesVerifier.java
new file mode 100644
index 00000000..d2eb5c92
--- /dev/null
+++ b/src/main/java/xades4j/verification/AttrAuthoritiesCertValuesVerifier.java
@@ -0,0 +1,53 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.security.cert.X509Certificate;
+import java.util.Collection;
+
+import com.google.inject.Inject;
+
+import xades4j.properties.AttrAuthoritiesCertValuesProperty;
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.data.AttrAuthoritiesCertValuesData;
+
+/**
+ *
+ * @author Hubert Kario
+ *
+ */
+public class AttrAuthoritiesCertValuesVerifier extends EncapsulatedPKIDataVerifierBase
+{
+ @Inject
+ public AttrAuthoritiesCertValuesVerifier(String propName)
+ {
+ super(propName);
+ }
+
+ @Override
+ public QualifyingProperty createProperty(Collection certs)
+ {
+ return new AttrAuthoritiesCertValuesProperty(certs);
+ }
+
+ public void addCertificatesToValidationProvider(
+ Collection certificates,
+ QualifyingPropertyVerificationContext ctx)
+ {
+ ctx.addAttributeCertificates(certificates);
+ }
+}
diff --git a/src/main/java/xades4j/verification/AttributeRevocationValuesVerifier.java b/src/main/java/xades4j/verification/AttributeRevocationValuesVerifier.java
new file mode 100644
index 00000000..60c3c144
--- /dev/null
+++ b/src/main/java/xades4j/verification/AttributeRevocationValuesVerifier.java
@@ -0,0 +1,51 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.security.cert.X509CRL;
+import java.util.Collection;
+
+import com.google.inject.Inject;
+
+import xades4j.properties.AttributeRevocationValuesProperty;
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.data.AttributeRevocationValuesData;
+import xades4j.providers.TSACertificateValidationProvider;
+
+public class AttributeRevocationValuesVerifier
+ extends EncapsulatedPKIRevocationDataVerifierBase
+{
+ @Inject
+ public AttributeRevocationValuesVerifier(String propName)
+ {
+ super(propName);
+ }
+
+ @Override
+ public QualifyingProperty createProperty(Collection crls)
+ {
+ return new AttributeRevocationValuesProperty(crls);
+ }
+
+ @Override
+ public void addCRLsToValidationProvider(
+ Collection crls,
+ QualifyingPropertyVerificationContext ctx)
+ {
+ ctx.addAttributeCRLs(crls);
+ }
+}
diff --git a/src/main/java/xades4j/verification/CertificateValuesVerifier.java b/src/main/java/xades4j/verification/CertificateValuesVerifier.java
new file mode 100644
index 00000000..67d1ec1c
--- /dev/null
+++ b/src/main/java/xades4j/verification/CertificateValuesVerifier.java
@@ -0,0 +1,58 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.security.cert.X509Certificate;
+import java.util.Collection;
+
+import org.w3c.dom.Element;
+
+import com.google.inject.Inject;
+
+import xades4j.properties.CertificateValuesProperty;
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.data.CertificateValuesData;
+import xades4j.providers.CertificateValidationProvider;
+import xades4j.providers.TSACertificateValidationProvider;
+
+/**
+ *
+ * @author Hubert Kario
+ *
+ */
+public class CertificateValuesVerifier extends EncapsulatedPKIDataVerifierBase
+{
+ @Inject
+ public CertificateValuesVerifier(String propName)
+ {
+ super(propName);
+ }
+
+ @Override
+ public QualifyingProperty createProperty(Collection certs)
+ {
+ return new CertificateValuesProperty(certs);
+ }
+
+ @Override
+ public void addCertificatesToValidationProvider(
+ Collection certificates,
+ QualifyingPropertyVerificationContext ctx)
+ {
+ ctx.addSignatureCertificates(certificates);
+ }
+}
diff --git a/src/main/java/xades4j/verification/CommitmentTypeVerifier.java b/src/main/java/xades4j/verification/CommitmentTypeVerifier.java
index 9137326b..8253b464 100644
--- a/src/main/java/xades4j/verification/CommitmentTypeVerifier.java
+++ b/src/main/java/xades4j/verification/CommitmentTypeVerifier.java
@@ -45,7 +45,7 @@ public QualifyingProperty verify(
{
// "Check that all the ObjectReference elements actually reference
// ds:Reference elements from the signature."
-
+
SignedObjectsData signedObjsData = ctx.getSignedObjectsData();
CommitmentTypeProperty commitmentTypeProperty = new CommitmentTypeProperty(uri, desc);
@@ -82,4 +82,12 @@ else if (q instanceof Element)
return property;
}
+
+ @Override
+ public QualifyingProperty verify(CommitmentTypeData propData, Element elem,
+ QualifyingPropertyVerificationContext ctx)
+ throws InvalidPropertyException
+ {
+ return verify(propData, ctx);
+ }
}
diff --git a/src/main/java/xades4j/verification/CompleteCertRefsVerifier.java b/src/main/java/xades4j/verification/CompleteCertRefsVerifier.java
index 96922f4d..9e4556a6 100644
--- a/src/main/java/xades4j/verification/CompleteCertRefsVerifier.java
+++ b/src/main/java/xades4j/verification/CompleteCertRefsVerifier.java
@@ -17,14 +17,19 @@
package xades4j.verification;
import com.google.inject.Inject;
+
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+
+import org.w3c.dom.Element;
+
import xades4j.properties.CompleteCertificateRefsProperty;
import xades4j.properties.QualifyingProperty;
import xades4j.properties.data.CertRef;
import xades4j.properties.data.CompleteCertificateRefsData;
+import xades4j.providers.CertificateValidationProvider;
import xades4j.providers.MessageDigestEngineProvider;
/**
@@ -37,7 +42,8 @@ class CompleteCertRefsVerifier implements QualifyingPropertyVerifier unkownElemsBinder = MapBinder.newMapBinder(binder(), QName.class, QualifyingPropertyVerifier.class);
unkownElemsBinder
.addBinding(new QName(QualifyingProperty.XADES_XMLNS, CounterSignatureProperty.PROP_NAME))
diff --git a/src/main/java/xades4j/verification/EncapsulatedPKIDataVerificationException.java b/src/main/java/xades4j/verification/EncapsulatedPKIDataVerificationException.java
new file mode 100644
index 00000000..601cb3bc
--- /dev/null
+++ b/src/main/java/xades4j/verification/EncapsulatedPKIDataVerificationException.java
@@ -0,0 +1,44 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.security.cert.CertificateException;
+
+public class EncapsulatedPKIDataVerificationException extends InvalidPropertyException
+{
+ private static final long serialVersionUID = 1L;
+ private final String propName;
+
+ public EncapsulatedPKIDataVerificationException(CertificateException ex, String propName)
+ {
+ super(ex);
+ this.propName = propName;
+ }
+
+ @Override
+ protected String getVerificationMessage()
+ {
+ return "Verification failure, can't parse certificates";
+ }
+
+ @Override
+ public String getPropertyName()
+ {
+ return propName;
+ }
+
+}
diff --git a/src/main/java/xades4j/verification/EncapsulatedPKIDataVerifierBase.java b/src/main/java/xades4j/verification/EncapsulatedPKIDataVerifierBase.java
new file mode 100644
index 00000000..4eaaf151
--- /dev/null
+++ b/src/main/java/xades4j/verification/EncapsulatedPKIDataVerifierBase.java
@@ -0,0 +1,88 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.data.BaseEncapsulatedPKIData;
+
+public abstract class EncapsulatedPKIDataVerifierBase
+ implements QualifyingPropertyVerifier
+{
+ private final String propName;
+
+ public EncapsulatedPKIDataVerifierBase(String propName)
+ {
+ this.propName = propName;
+ }
+
+ public QualifyingProperty verify(BaseEncapsulatedPKIData propData,
+ Element elem,
+ QualifyingPropertyVerificationContext ctx)
+ throws InvalidPropertyException
+ {
+ return verify(propData, ctx);
+ }
+
+ public QualifyingProperty verify(BaseEncapsulatedPKIData propData,
+ QualifyingPropertyVerificationContext ctx)
+ throws InvalidPropertyException
+ {
+ Collection rawCerts = propData.getData();
+ CertificateFactory certFactory;
+ try
+ {
+ certFactory = CertificateFactory.getInstance("X509");
+ } catch (CertificateException ex)
+ {
+ throw new EncapsulatedPKIDataVerificationException(ex, propName);
+ }
+
+ List certificates = new ArrayList();
+
+ for (byte[] cert : rawCerts)
+ {
+ InputStream inStream = new ByteArrayInputStream(cert);
+ try
+ {
+ certificates.add((X509Certificate) certFactory.generateCertificate(inStream));
+ } catch (CertificateException ex)
+ {
+ throw new EncapsulatedPKIDataVerificationException(ex, propName);
+ }
+ }
+
+ addCertificatesToValidationProvider(certificates, ctx);
+
+ return createProperty(certificates);
+ }
+
+ public abstract QualifyingProperty createProperty(Collection certs);
+
+ public abstract void addCertificatesToValidationProvider(Collection certificates,
+ QualifyingPropertyVerificationContext ctx);
+}
diff --git a/src/main/java/xades4j/verification/EncapsulatedPKIRevocationDataVerificationException.java b/src/main/java/xades4j/verification/EncapsulatedPKIRevocationDataVerificationException.java
new file mode 100644
index 00000000..c20a69cd
--- /dev/null
+++ b/src/main/java/xades4j/verification/EncapsulatedPKIRevocationDataVerificationException.java
@@ -0,0 +1,43 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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;
+
+public class EncapsulatedPKIRevocationDataVerificationException extends
+ InvalidPropertyException
+{
+ private static final long serialVersionUID = 1L;
+ private final String propName;
+
+ public EncapsulatedPKIRevocationDataVerificationException(Exception ex, String propName)
+ {
+ super(ex);
+ this.propName = propName;
+ }
+
+ @Override
+ protected String getVerificationMessage()
+ {
+ return "Can't verify revocation information";
+ }
+
+ @Override
+ public String getPropertyName()
+ {
+ return propName;
+ }
+
+}
diff --git a/src/main/java/xades4j/verification/EncapsulatedPKIRevocationDataVerifierBase.java b/src/main/java/xades4j/verification/EncapsulatedPKIRevocationDataVerifierBase.java
new file mode 100644
index 00000000..b03470d5
--- /dev/null
+++ b/src/main/java/xades4j/verification/EncapsulatedPKIRevocationDataVerifierBase.java
@@ -0,0 +1,90 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.data.BaseEncapsulatedPKIData;
+
+public abstract class EncapsulatedPKIRevocationDataVerifierBase
+ implements QualifyingPropertyVerifier
+{
+ private final String propName;
+
+ public EncapsulatedPKIRevocationDataVerifierBase(String propName)
+ {
+ this.propName = propName;
+ }
+
+ public QualifyingProperty verify(BaseEncapsulatedPKIData propData,
+ Element elem,
+ QualifyingPropertyVerificationContext ctx)
+ throws InvalidPropertyException
+ {
+ return verify(propData, ctx);
+ }
+
+ public QualifyingProperty verify(BaseEncapsulatedPKIData propData,
+ QualifyingPropertyVerificationContext ctx)
+ throws InvalidPropertyException
+ {
+ Collection rawRevocationData = propData.getData();
+ CertificateFactory certFactory;
+ try
+ {
+ certFactory = CertificateFactory.getInstance("X509");
+ } catch (CertificateException ex)
+ {
+ throw new EncapsulatedPKIRevocationDataVerificationException(ex, propName);
+ }
+
+ List crls = new ArrayList();
+
+ for (byte[] crl : rawRevocationData)
+ {
+ InputStream inStream = new ByteArrayInputStream(crl);
+ try
+ {
+ crls.add((X509CRL) certFactory.generateCRL(inStream));
+ } catch (CRLException ex)
+ {
+ throw new EncapsulatedPKIRevocationDataVerificationException(ex, propName);
+ }
+ }
+
+ addCRLsToValidationProvider(crls, ctx);
+
+ return createProperty(crls);
+ }
+
+ public abstract QualifyingProperty createProperty(Collection crls);
+
+ public abstract void addCRLsToValidationProvider(
+ Collection crls,
+ QualifyingPropertyVerificationContext ctx);
+}
diff --git a/src/main/java/xades4j/verification/GenericDOMDataVerifier.java b/src/main/java/xades4j/verification/GenericDOMDataVerifier.java
index efe63e3d..3f73b8d6 100644
--- a/src/main/java/xades4j/verification/GenericDOMDataVerifier.java
+++ b/src/main/java/xades4j/verification/GenericDOMDataVerifier.java
@@ -64,4 +64,12 @@ public String getPropertyName()
return propVerifier.verify(propData, ctx);
}
+
+ @Override
+ public QualifyingProperty verify(GenericDOMData propData, Element elem,
+ QualifyingPropertyVerificationContext ctx)
+ throws InvalidPropertyException
+ {
+ return verify(propData, ctx);
+ }
}
diff --git a/src/main/java/xades4j/verification/HybridQualifPropsDataCollectorImpl.java b/src/main/java/xades4j/verification/HybridQualifPropsDataCollectorImpl.java
new file mode 100644
index 00000000..cd2911f3
--- /dev/null
+++ b/src/main/java/xades4j/verification/HybridQualifPropsDataCollectorImpl.java
@@ -0,0 +1,265 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.ArrayList;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import xades4j.properties.data.AllDataObjsTimeStampData;
+import xades4j.properties.data.ArchiveTimeStampData;
+import xades4j.properties.data.AttrAuthoritiesCertValuesData;
+import xades4j.properties.data.AttributeRevocationValuesData;
+import xades4j.properties.data.CertificateValuesData;
+import xades4j.properties.data.CommitmentTypeData;
+import xades4j.properties.data.CompleteCertificateRefsData;
+import xades4j.properties.data.CompleteRevocationRefsData;
+import xades4j.properties.data.DataObjectFormatData;
+import xades4j.properties.data.GenericDOMData;
+import xades4j.properties.data.IndividualDataObjsTimeStampData;
+import xades4j.properties.data.OtherPropertyData;
+import xades4j.properties.data.PropertyDataObject;
+import xades4j.properties.data.RevocationValuesData;
+import xades4j.properties.data.SigAndRefsTimeStampData;
+import xades4j.properties.data.SignaturePolicyData;
+import xades4j.properties.data.SignatureProdPlaceData;
+import xades4j.properties.data.SignatureTimeStampData;
+import xades4j.properties.data.SignerRoleData;
+import xades4j.properties.data.SigningCertificateData;
+import xades4j.properties.data.SigningTimeData;
+import xades4j.properties.data.TimeStampValidationDataData;
+import xades4j.utils.PropertiesList;
+import xades4j.utils.PropertiesSet;
+import xades4j.xml.unmarshalling.QualifyingPropertiesDataCollector;
+
+public class HybridQualifPropsDataCollectorImpl implements
+ QualifyingPropertiesDataCollector
+{
+ private final PropertiesSet signedSigProperties;
+ private final PropertiesSet signedDataObjectProperties;
+ private final PropertiesList unsignedSigProperties;
+ private final PropertiesList unsignedDataObjectProperties;
+ private final List unsignedSigPropertiesElements;
+
+ public HybridQualifPropsDataCollectorImpl()
+ {
+ signedSigProperties = new PropertiesSet(1);
+ signedDataObjectProperties = new PropertiesSet(1);
+ unsignedSigProperties = new PropertiesList(1);
+ unsignedDataObjectProperties = new PropertiesList(1);
+ unsignedSigPropertiesElements = new ArrayList();
+ }
+
+ @Override
+ public void setSigningTime(SigningTimeData sigTimeData)
+ {
+ signedSigProperties.put(sigTimeData);
+ }
+
+ @Override
+ public void setSignatureProdPlace(SignatureProdPlaceData sigProdPlaceData)
+ {
+ signedSigProperties.put(sigProdPlaceData);
+ }
+
+ @Override
+ public void setSignerRole(SignerRoleData signerRoleData)
+ {
+ signedSigProperties.put(signerRoleData);
+ }
+
+ @Override
+ public void setSigningCertificate(SigningCertificateData signingCertData)
+ {
+ signedSigProperties.put(signingCertData);
+ }
+
+ @Override
+ public void setSignaturePolicy(SignaturePolicyData sigPolicyData)
+ {
+ signedSigProperties.put(sigPolicyData);
+ }
+
+ @Override
+ public void setCompleteCertificateRefs(
+ CompleteCertificateRefsData completeCertRefsData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.put(completeCertRefsData);
+ }
+
+ @Override
+ public void setCompleteRevocRefs(
+ CompleteRevocationRefsData completeRecovRefsData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.put(completeRecovRefsData);
+ }
+
+ @Override
+ public void addSignatureTimeStamp(SignatureTimeStampData sigTSData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.add(sigTSData);
+ }
+
+ @Override
+ public void addCommitmentType(CommitmentTypeData commitmentData)
+ {
+ signedDataObjectProperties.add(commitmentData);
+ }
+
+ @Override
+ public void addDataObjectFormat(DataObjectFormatData formatData)
+ {
+ signedDataObjectProperties.add(formatData);
+ }
+
+ @Override
+ public void addAllDataObjsTimeStamp(AllDataObjsTimeStampData objsTSData)
+ {
+ signedDataObjectProperties.add(objsTSData);
+ }
+
+ @Override
+ public void addIndividualDataObjsTimeStamp(
+ IndividualDataObjsTimeStampData objsTSData)
+ {
+ signedDataObjectProperties.add(objsTSData);
+ }
+
+ @Override
+ public void addGenericDOMData(GenericDOMData domData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.add(domData);
+ }
+
+ @Override
+ public void addOther(OtherPropertyData otherData)
+ {
+ unsignedDataObjectProperties.add(otherData);
+ }
+
+ @Override
+ public void addSigAndRefsTimeStamp(SigAndRefsTimeStampData tsData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.add(tsData);
+ }
+
+ @Override
+ public void setCertificateValues(CertificateValuesData certificateValuesData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.put(certificateValuesData);
+ }
+
+ @Override
+ public void setRevocationValues(RevocationValuesData revocationValuesData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.put(revocationValuesData);
+ }
+
+ @Override
+ public void setAttrAuthoritiesCertValues(
+ AttrAuthoritiesCertValuesData attrAuthoritiesCertValuesData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.put(attrAuthoritiesCertValuesData);
+ }
+
+ @Override
+ public void setAttributeRevocationValues(
+ AttributeRevocationValuesData attrRevocValData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.put(attrRevocValData);
+ }
+
+ @Override
+ public void addArchiveTimeStamp(ArchiveTimeStampData tsData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property!");
+
+ unsignedSigProperties.add(tsData);
+ }
+
+ @Override
+ public void addTimeStampValidationDataData(
+ TimeStampValidationDataData timeStampValidationDataData)
+ {
+ if (unsignedSigProperties.size() != unsignedSigPropertiesElements.size())
+ throw new IllegalStateException("No Element linked to previous property");
+
+ unsignedSigProperties.add(timeStampValidationDataData);
+ }
+
+ List getUnsignedPropertiesData()
+ {
+ return unsignedSigProperties.getProperties();
+ }
+
+ @Override
+ public List getPropertiesData()
+ {
+ List ret = new ArrayList();
+ ret.addAll(signedSigProperties.getProperties());
+ ret.addAll(signedDataObjectProperties.getProperties());
+ ret.addAll(unsignedSigProperties.getProperties());
+ ret.addAll(unsignedDataObjectProperties.getProperties());
+ return ret;
+ }
+
+ @Override
+ public void linkPropertyToElem(Element node)
+ {
+ unsignedSigPropertiesElements.add(node);
+ }
+
+ @Override
+ public Node getPropertyNode(PropertyDataObject pdo)
+ {
+ int index = unsignedSigProperties.getProperties().indexOf(pdo);
+ if (index == -1)
+ return null;
+
+ return unsignedSigPropertiesElements.get(index);
+ }
+}
diff --git a/src/main/java/xades4j/verification/HybridQualifyingPropertiesVerifierImpl.java b/src/main/java/xades4j/verification/HybridQualifyingPropertiesVerifierImpl.java
new file mode 100644
index 00000000..04c19208
--- /dev/null
+++ b/src/main/java/xades4j/verification/HybridQualifyingPropertiesVerifierImpl.java
@@ -0,0 +1,344 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS.
+ *
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import org.w3c.dom.Element;
+
+import com.google.inject.Inject;
+
+import xades4j.XAdES4jException;
+import xades4j.properties.AttrAuthoritiesCertValuesProperty;
+import xades4j.properties.QualifyingProperty;
+import xades4j.properties.SigAndRefsTimeStampProperty;
+import xades4j.properties.SignatureTimeStampProperty;
+import xades4j.properties.data.AllDataObjsTimeStampData;
+import xades4j.properties.data.AttrAuthoritiesCertValuesData;
+import xades4j.properties.data.AttributeRevocationValuesData;
+import xades4j.properties.data.CertificateValuesData;
+import xades4j.properties.data.CommitmentTypeData;
+import xades4j.properties.data.CompleteCertificateRefsData;
+import xades4j.properties.data.CompleteRevocationRefsData;
+import xades4j.properties.data.DataObjectFormatData;
+import xades4j.properties.data.IndividualDataObjsTimeStampData;
+import xades4j.properties.data.PropertiesDataObjectsStructureVerifier;
+import xades4j.properties.data.PropertyDataObject;
+import xades4j.properties.data.PropertyDataStructureException;
+import xades4j.properties.data.RevocationValuesData;
+import xades4j.properties.data.SignaturePolicyData;
+import xades4j.properties.data.SignatureProdPlaceData;
+import xades4j.properties.data.SignatureTimeStampData;
+import xades4j.properties.data.SignerRoleData;
+import xades4j.properties.data.SigningCertificateData;
+import xades4j.properties.data.SigningTimeData;
+import xades4j.properties.data.TimeStampValidationDataData;
+import xades4j.xml.unmarshalling.QualifyingPropertiesDataCollector;
+
+public class HybridQualifyingPropertiesVerifierImpl implements
+ QualifyingPropertiesVerifier
+{
+ private final QualifyingPropertyVerifiersMapper propertyVerifiersMapper;
+ private final PropertiesDataObjectsStructureVerifier dataObjectsStructureVerifier;
+ private final Set> sigAndRefsPropertySignedProperties;
+ private final Set> signedProperties;
+
+ @Inject
+ public HybridQualifyingPropertiesVerifierImpl(
+ QualifyingPropertyVerifiersMapper propVerMapp,
+ PropertiesDataObjectsStructureVerifier dataObjStructVerif)
+ {
+ propertyVerifiersMapper = propVerMapp;
+ dataObjectsStructureVerifier = dataObjStructVerif;
+ Set> tmp = new HashSet>();
+ // TODO tmp.add(AttributeRevocationRefsData.class);
+ // TODO tmp.add(AttributeCertificateRefsData.class);
+ tmp.add(CompleteRevocationRefsData.class);
+ tmp.add(CompleteCertificateRefsData.class);
+ tmp.add(SignatureTimeStampData.class);
+ sigAndRefsPropertySignedProperties = tmp;
+
+ tmp = new HashSet>();
+ tmp.add(IndividualDataObjsTimeStampData.class);
+ tmp.add(AllDataObjsTimeStampData.class);
+ tmp.add(CommitmentTypeData.class);
+ tmp.add(DataObjectFormatData.class);
+ tmp.add(SignerRoleData.class);
+ tmp.add(SignatureProdPlaceData.class);
+ tmp.add(SignaturePolicyData.class);
+ tmp.add(SigningCertificateData.class);
+ tmp.add(SigningTimeData.class);
+ signedProperties = tmp;
+ }
+
+ /*
+ * new invocation method (one that knows about XML structure of properties)
+ */
+ @Override
+ public List verifyProperties(
+ QualifyingPropertiesDataCollector dataCollector,
+ QualifyingPropertyVerificationContext ctx)
+ throws PropertyDataStructureException, InvalidPropertyException,
+ QualifyingPropertyVerifierNotAvailableException
+ {
+ // verify internal data structure of properties (presence of mandatory elements
+ // and sanity of all elements)
+ List unmarshalledProperties = dataCollector.getPropertiesData();
+ dataObjectsStructureVerifier.verifiyPropertiesDataStructure(unmarshalledProperties);
+
+ /*
+ * Because TSA or CA certificates may have been used in the past (in previous
+ * ArchiveTimeStamp) and included in TimeStampVerificationData or one of
+ * XAdES-X-L properties, it does not have to be present in subsequent
+ * TimeStampValidationData, we have to first go over all properties that can
+ * contain certificates other than time stamps themselves.
+ *
+ * Because the certificates have been added in chronological order, we too have
+ * to validate them in normal order
+ *
+ * TODO time stamp verifier won't use the certificates if the algorithms used
+ * to secure them are currently insecure (at the time of last validated timestamp)
+ *
+ * TODO make it work for CA certificates included in previous time stamp tokens
+ */
+ for(PropertyDataObject pdo : unmarshalledProperties)
+ {
+ if (pdo instanceof CertificateValuesData ||
+ pdo instanceof RevocationValuesData ||
+ pdo instanceof AttrAuthoritiesCertValuesData ||
+ pdo instanceof AttributeRevocationValuesData ||
+ pdo instanceof TimeStampValidationDataData)
+ {
+ QualifyingPropertyVerifier propVerifier =
+ this.propertyVerifiersMapper.getVerifier(pdo);
+
+ Element elem = (Element) dataCollector.getPropertyNode(pdo);
+
+ // the verifier adds certificates and CRLs to context (ctx)
+ propVerifier.verify(pdo, elem, ctx);
+ } // else do nothing
+ }
+
+ List props = new LinkedList();
+
+ /*
+ * go over all properties and verify them
+ * because the most recent additions to the signature are (or at least SHOULD be)
+ * last, we go in reverse order
+ */
+ ListIterator property =
+ unmarshalledProperties.listIterator(unmarshalledProperties.size());
+
+ PropertyDataObject propData;
+ do
+ {
+ propData = property.previous();
+ /*
+ * Because ArchiveTimeStamp signs everything before its location, we update
+ * the currentTime in ctx just after its successful verification.
+ * This is not so easy with SignatureTimeStamp or SigAndRefsTimeStamp, there
+ * we can update the currentTime only after we went over all those
+ * properties, that is, we found the first property that should have been
+ * signed by SigAndRefsTimeStamp.
+ *
+ * With SignatureTimeStamp similar situation occurs when there are only
+ * SignedProperties left or all properties have been handled
+ *
+ * TODO The situation is even more complex in the unsupported case of
+ * RefsOnlyTimeStamp.
+ *
+ * TODO handle gracefully multiple ArchiveTimeStamps with similar times
+ * The above described behavior may cause failure of verification for one
+ * of the ArchiveTimeStamps if there are multiple ArchiveTimeStamps present,
+ * but it won't cause failure in verification of the whole signature.
+ * If the first ArchiveTimeStamp is invalid, it won't change the time, so the
+ * second one will verify successfully.
+ */
+ try {
+ // when we encounter property that needs to be signed by
+ // sigAndRefsTimeStamp it means we should have parsed all
+ // SigAndRefsTimeStamps and can change time to the earliest one from
+ // those properties
+ if (sigAndRefsPropertySignedProperties.contains(propData.getClass()))
+ setDateFromSigAndRefsProperty(ctx, props);
+ // similar situation as with sigAndRefsTimeStamp but for SignatureTimeStamp
+ if (signedProperties.contains(propData.getClass()))
+ setDateFromSignatureTimeStamp(ctx, props);
+ // verificator of ArchiveTimeStamp changes time itself
+
+ /*
+ * To verify those three properties we need result of Signature
+ * verification, so we add place holders for them and will verify them
+ * after Signature verification
+ */
+ if (propData instanceof CompleteCertificateRefsData ||
+ propData instanceof CompleteRevocationRefsData ||
+ propData instanceof SigningCertificateData)
+ {
+ props.add(0, new PropertyInfo(propData, null));
+ continue;
+ }
+
+ QualifyingPropertyVerifier propVerifier =
+ this.propertyVerifiersMapper.getVerifier(propData);
+
+ Element elem = (Element) dataCollector.getPropertyNode(propData);
+
+ QualifyingProperty p = propVerifier.verify(propData, elem, ctx);
+ if (p == null)
+ throw new PropertyVerifierErrorException(propData
+ .getClass().getName());
+
+ // we go over properties in reverse order so we have to insert
+ // them at the beginning of the returned list to preserve order
+ props.add(0, new PropertyInfo(propData, p));
+
+ } catch (XAdES4jException e) // TODO make it less generic
+ {
+ // critical error
+ if (e instanceof SigningTimeVerificationException)
+ throw (InvalidPropertyException)e;
+
+ // failure in verification of property will only cause its ommitance
+ // in returned property list
+ System.out.println("Error when verifying " + propData.getClass()
+ + ", stack trace follows: ");
+ e.printStackTrace();
+ continue;
+ }
+
+ } while (property.hasPrevious());
+
+ // SignedProperties are not mandatory so we have to try changing the time after
+ // parsing all properties
+ setDateFromSignatureTimeStamp(ctx, props);
+
+ return Collections.unmodifiableList(props);
+ }
+
+ private void setDateFromSignatureTimeStamp(
+ QualifyingPropertyVerificationContext ctx,
+ List props)
+ {
+ Date oldest = null;
+ for (PropertyInfo propInfo : props)
+ {
+ QualifyingProperty p = propInfo.getProperty();
+ if (p instanceof SignatureTimeStampProperty)
+ {
+ SignatureTimeStampProperty sigTimeStamp = (SignatureTimeStampProperty) p;
+ if (oldest == null)
+ oldest = sigTimeStamp.getTime();
+ else if (oldest.getTime() > sigTimeStamp.getTime().getTime())
+ oldest = sigTimeStamp.getTime();
+ }
+ }
+ if (oldest != null && oldest.getTime() != ctx.getCurrentTime().getTime())
+ ctx.setCurrentTime(oldest);
+ }
+
+ private void setDateFromSigAndRefsProperty(
+ QualifyingPropertyVerificationContext ctx,
+ List props)
+ {
+ Date oldest = null;
+ for (PropertyInfo propInfo : props)
+ {
+ QualifyingProperty p = propInfo.getProperty();
+ if (p instanceof SigAndRefsTimeStampProperty)
+ {
+ SigAndRefsTimeStampProperty sigAndRefs = (SigAndRefsTimeStampProperty) p;
+ if (oldest == null)
+ oldest = sigAndRefs.getTime();
+ else if (oldest.getTime() > sigAndRefs.getTime().getTime())
+ oldest = sigAndRefs.getTime();
+ }
+ }
+
+ if (oldest != null && oldest.getTime() != ctx.getCurrentTime().getTime())
+ ctx.setCurrentTime(oldest);
+ }
+
+ @Deprecated
+ @Override
+ public Collection verifyProperties(
+ List unmarshalledProperties,
+ QualifyingPropertyVerificationContext ctx)
+ throws PropertyDataStructureException, InvalidPropertyException,
+ QualifyingPropertyVerifierNotAvailableException
+ {
+ // old invocation method so use old implementation
+ QualifyingPropertiesVerifier qpv = new QualifyingPropertiesVerifierImpl(
+ propertyVerifiersMapper,
+ dataObjectsStructureVerifier);
+
+ return qpv.verifyProperties(unmarshalledProperties, ctx);
+ }
+
+ @Override
+ public List verifyProperties(
+ HybridQualifPropsDataCollectorImpl propsDataCollector,
+ QualifyingPropertyVerificationContext ctx,
+ List props)
+ {
+ // now we have full revocation information about Signature, go and verify
+ // *Refs and SignatureCertificate properties
+
+ List newProps = new ArrayList(props.size());
+ for (PropertyInfo p : props)
+ {
+ if (p.getProperty() == null)
+ {
+ PropertyDataObject propData = p.getPropertyData();
+ try {
+
+ QualifyingPropertyVerifier propVerifier =
+ this.propertyVerifiersMapper.getVerifier(propData);
+
+ Element elem = (Element) propsDataCollector.getPropertyNode(propData);
+
+ QualifyingProperty qp = propVerifier.verify(propData, elem, ctx);
+ if (qp == null)
+ throw new PropertyVerifierErrorException(propData
+ .getClass().getName());
+ newProps.add(new PropertyInfo(propData, qp));
+
+ } catch (XAdES4jException e)
+ {
+ System.out.println("Error when verifying "
+ + p.getPropertyData().getClass() + ", stack trace follows: ");
+ e.printStackTrace();
+ continue;
+ }
+
+ } else {
+ newProps.add(p);
+ }
+ }
+
+ return newProps;
+ }
+
+}
diff --git a/src/main/java/xades4j/verification/IndivDataObjsTimeStampVerifier.java b/src/main/java/xades4j/verification/IndivDataObjsTimeStampVerifier.java
index c7001d02..87bfaa5c 100644
--- a/src/main/java/xades4j/verification/IndivDataObjsTimeStampVerifier.java
+++ b/src/main/java/xades4j/verification/IndivDataObjsTimeStampVerifier.java
@@ -16,8 +16,11 @@
*/
package xades4j.verification;
+import org.w3c.dom.Element;
+
import com.google.inject.Inject;
import xades4j.utils.CannotAddDataToDigestInputException;
+import xades4j.properties.BaseXAdESTimeStampProperty;
import xades4j.properties.IndividualDataObjsTimeStampProperty;
import xades4j.properties.QualifyingProperty;
import xades4j.utils.TimeStampDigestInput;
@@ -41,8 +44,9 @@ public IndivDataObjsTimeStampVerifier(
}
@Override
- protected QualifyingProperty addPropSpecificTimeStampInputAndCreateProperty(
+ protected BaseXAdESTimeStampProperty addPropSpecificTimeStampInputAndCreateProperty(
IndividualDataObjsTimeStampData propData,
+ Element location,
TimeStampDigestInput digestInput,
QualifyingPropertyVerificationContext ctx) throws CannotAddDataToDigestInputException, TimeStampVerificationException
{
@@ -63,4 +67,11 @@ protected QualifyingProperty addPropSpecificTimeStampInputAndCreateProperty(
}
return prop;
}
+
+ @Override
+ protected void updateContextAfterVerification(QualifyingProperty prop,
+ QualifyingPropertyVerificationContext ctx)
+ {
+ // noop
+ }
}
diff --git a/src/main/java/xades4j/verification/QualifPropsDataCollectorImpl.java b/src/main/java/xades4j/verification/QualifPropsDataCollectorImpl.java
index 2388450e..017d7e13 100644
--- a/src/main/java/xades4j/verification/QualifPropsDataCollectorImpl.java
+++ b/src/main/java/xades4j/verification/QualifPropsDataCollectorImpl.java
@@ -16,16 +16,27 @@
*/
package xades4j.verification;
-import java.util.Collection;
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
import xades4j.properties.data.AllDataObjsTimeStampData;
+import xades4j.properties.data.ArchiveTimeStampData;
+import xades4j.properties.data.AttrAuthoritiesCertValuesData;
+import xades4j.properties.data.AttributeRevocationValuesData;
+import xades4j.properties.data.CertificateValuesData;
import xades4j.properties.data.CompleteCertificateRefsData;
import xades4j.properties.data.CompleteRevocationRefsData;
import xades4j.properties.data.GenericDOMData;
import xades4j.properties.data.IndividualDataObjsTimeStampData;
import xades4j.properties.data.OtherPropertyData;
+import xades4j.properties.data.RevocationValuesData;
+import xades4j.properties.data.SigAndRefsTimeStampData;
import xades4j.properties.data.SignaturePolicyData;
import xades4j.properties.data.SignatureTimeStampData;
import xades4j.properties.data.SignerRoleData;
+import xades4j.properties.data.TimeStampValidationDataData;
import xades4j.utils.PropertiesSet;
import xades4j.properties.data.CommitmentTypeData;
import xades4j.properties.data.DataObjectFormatData;
@@ -99,6 +110,36 @@ public void addSignatureTimeStamp(SignatureTimeStampData sigTSData)
}
@Override
+ public void addSigAndRefsTimeStamp(SigAndRefsTimeStampData tsData)
+ {
+ propsData.add(tsData);
+ }
+
+ @Override
+ public void setCertificateValues(CertificateValuesData certificateValuesData)
+ {
+ propsData.add(certificateValuesData);
+ }
+
+ @Override
+ public void setAttrAuthoritiesCertValues(AttrAuthoritiesCertValuesData attrAuthoritiesCertValuesData)
+ {
+ propsData.add(attrAuthoritiesCertValuesData);
+ }
+
+ @Override
+ public void setRevocationValues(RevocationValuesData revocationValuesData)
+ {
+ propsData.add(revocationValuesData);
+ }
+
+ @Override
+ public void setAttributeRevocationValues(AttributeRevocationValuesData attrRevocValData)
+ {
+ propsData.add(attrRevocValData);
+ }
+
+ @Override
public void addCommitmentType(CommitmentTypeData commitmentData)
{
propsData.add(commitmentData);
@@ -136,8 +177,34 @@ public void addOther(OtherPropertyData otherData)
}
/**/
- Collection getPropertiesData()
+ public List getPropertiesData()
{
return propsData.getProperties();
}
+
+ @Override
+ public void linkPropertyToElem(Element node)
+ {
+ //noop
+ }
+
+ @Override
+ public Node getPropertyNode(PropertyDataObject pdo)
+ {
+ throw new UnsupportedOperationException("QualifPropsDataCollectorImpl does not"+
+ " support getPropertyNode() method. Use HybridQualifPropsDataCollectorImpl.");
+ }
+
+ @Override
+ public void addArchiveTimeStamp(ArchiveTimeStampData tsData)
+ {
+ propsData.add(tsData);
+ }
+
+ @Override
+ public void addTimeStampValidationDataData(
+ TimeStampValidationDataData timeStampValidationDataData)
+ {
+ propsData.add(timeStampValidationDataData);
+ }
}
diff --git a/src/main/java/xades4j/verification/QualifyingPropertiesVerifier.java b/src/main/java/xades4j/verification/QualifyingPropertiesVerifier.java
index 896f966c..524ba8ac 100644
--- a/src/main/java/xades4j/verification/QualifyingPropertiesVerifier.java
+++ b/src/main/java/xades4j/verification/QualifyingPropertiesVerifier.java
@@ -17,8 +17,14 @@
package xades4j.verification;
import java.util.Collection;
+import java.util.List;
+
+import xades4j.properties.data.CompleteCertificateRefsData;
+import xades4j.properties.data.CompleteRevocationRefsData;
import xades4j.properties.data.PropertyDataObject;
import xades4j.properties.data.PropertyDataStructureException;
+import xades4j.properties.data.SigningCertificateData;
+import xades4j.xml.unmarshalling.QualifyingPropertiesDataCollector;
/**
*
@@ -29,7 +35,32 @@ interface QualifyingPropertiesVerifier
/**
* Verifies the data objects' structure and the XAdES rules.
*/
- Collection verifyProperties(
- Collection unmarshalledProperties,
+ List verifyProperties(
+ QualifyingPropertiesDataCollector unmarshalledProperties,
QualifyingPropertyVerificationContext ctx) throws PropertyDataStructureException, InvalidPropertyException, QualifyingPropertyVerifierNotAvailableException;
+
+ /**
+ * Verifies the data objects' structure and the XAdES rules.
+ * Use {@link QualifyingPropertiesVerifier#verifyProperties(QualifyingPropertiesDataCollector, QualifyingPropertyVerificationContext)}
+ * TODO left because legacy parts of verifiers need to verify only some properties,
+ * for example just SignatureTimeStamp
+ */
+ @Deprecated
+ Collection verifyProperties(
+ List unmarshalledProperties,
+ QualifyingPropertyVerificationContext ctx) throws PropertyDataStructureException, InvalidPropertyException, QualifyingPropertyVerifierNotAvailableException;
+
+ /**
+ * Verifies properties that can be verified only after Signature has been verified,
+ * namely {@link CompleteCertificateRefsData}, {@link CompleteRevocationRefsData} and
+ * {@link SigningCertificateData}.
+ * @param propsDataCollector
+ * @param qPropsCtx
+ * @param props
+ * @return
+ */
+ List verifyProperties(
+ HybridQualifPropsDataCollectorImpl propsDataCollector,
+ QualifyingPropertyVerificationContext qPropsCtx,
+ List props);
}
diff --git a/src/main/java/xades4j/verification/QualifyingPropertiesVerifierImpl.java b/src/main/java/xades4j/verification/QualifyingPropertiesVerifierImpl.java
index 29686e2c..20a61d5c 100644
--- a/src/main/java/xades4j/verification/QualifyingPropertiesVerifierImpl.java
+++ b/src/main/java/xades4j/verification/QualifyingPropertiesVerifierImpl.java
@@ -20,10 +20,13 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
+
import xades4j.properties.QualifyingProperty;
import xades4j.properties.data.PropertiesDataObjectsStructureVerifier;
import xades4j.properties.data.PropertyDataObject;
import xades4j.properties.data.PropertyDataStructureException;
+import xades4j.xml.unmarshalling.QualifyingPropertiesDataCollector;
/**
*
@@ -44,14 +47,25 @@ class QualifyingPropertiesVerifierImpl implements QualifyingPropertiesVerifier
}
@Override
- public Collection verifyProperties(
- Collection unmarshalledProperties,
+ public List verifyProperties(
+ QualifyingPropertiesDataCollector dataCollector,
QualifyingPropertyVerificationContext ctx) throws PropertyDataStructureException, InvalidPropertyException, QualifyingPropertyVerifierNotAvailableException
+ {
+ List unmarshalledProperties = dataCollector.getPropertiesData();
+ return verifyProperties(unmarshalledProperties, ctx);
+ }
+
+ @Override
+ public List verifyProperties(
+ List unmarshalledProperties,
+ QualifyingPropertyVerificationContext ctx)
+ throws PropertyDataStructureException, InvalidPropertyException,
+ QualifyingPropertyVerifierNotAvailableException
{
dataObjectsStructureVerifier.verifiyPropertiesDataStructure(unmarshalledProperties);
- Collection props = new ArrayList(unmarshalledProperties.size());
-
+ List props = new ArrayList(unmarshalledProperties.size());
+
for (PropertyDataObject propData : unmarshalledProperties)
{
QualifyingPropertyVerifier propVerifier = this.propertyVerifiersMapper.getVerifier(propData);
@@ -63,6 +77,15 @@ public Collection verifyProperties(
props.add(new PropertyInfo(propData, p));
}
- return Collections.unmodifiableCollection(props);
+ return Collections.unmodifiableList(props);
+ }
+
+ @Override
+ public List verifyProperties(
+ HybridQualifPropsDataCollectorImpl propsDataCollector,
+ QualifyingPropertyVerificationContext qPropsCtx,
+ List props)
+ {
+ throw new UnsupportedOperationException("Use HybridQualifyingPropertiesVerifierImpl");
}
}
diff --git a/src/main/java/xades4j/verification/QualifyingPropertyVerificationContext.java b/src/main/java/xades4j/verification/QualifyingPropertyVerificationContext.java
index 143a1901..312d9190 100644
--- a/src/main/java/xades4j/verification/QualifyingPropertyVerificationContext.java
+++ b/src/main/java/xades4j/verification/QualifyingPropertyVerificationContext.java
@@ -19,11 +19,17 @@
import java.math.BigInteger;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+
import javax.security.auth.x500.X500Principal;
import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
import org.apache.xml.security.signature.ObjectContainer;
@@ -36,6 +42,9 @@
import org.w3c.dom.Element;
import org.w3c.dom.Node;
+import xades4j.providers.ValidationData;
+import xades4j.verification.SignatureUtils.KeyInfoRes;
+
/**
* The context available during the verification of the qualifying properties.
* @see QualifyingPropertyVerifier
@@ -44,17 +53,102 @@
public class QualifyingPropertyVerificationContext
{
private final XMLSignature signature;
- private final CertificationChainData certChainData;
+ private CertificationChainData certChainData;
private final SignedObjectsData signedObjectsData;
+ private final KeyInfoRes keyInfoRes;
+ // validation data collected during verification of attributes (trusted)
+ private Collection attributeValidationData;
+ // validation data collected during verification of signature (trusted)
+ private Collection signatureValidationData;
+ private final Set untrustedAttributeCertificates;
+ private final Set untrustedAttributeCRLs;
+ private final Set untrustedSignatureCertificates;
+ private final Set untrustedSignatureCRLs;
+
+ private Date currentTime;
QualifyingPropertyVerificationContext(
XMLSignature signature,
CertificationChainData certChainData,
- SignedObjectsData signedObjectsData)
+ SignedObjectsData signedObjectsData,
+ Date currentTime)
{
this.signature = signature;
this.certChainData = certChainData;
this.signedObjectsData = signedObjectsData;
+ attributeValidationData = new ArrayList();
+ signatureValidationData = new ArrayList();
+ this.keyInfoRes = null;
+ this.currentTime = currentTime;
+ untrustedAttributeCertificates = new HashSet();
+ untrustedAttributeCRLs = new HashSet();
+ untrustedSignatureCertificates = new HashSet();
+ untrustedSignatureCRLs = new HashSet();
+ }
+
+ public QualifyingPropertyVerificationContext(
+ XMLSignature signature,
+ KeyInfoRes keyInfoRes,
+ SignedObjectsData signedObjectsData,
+ Date currentTime)
+ {
+ this.signature = signature;
+ this.signedObjectsData = signedObjectsData;
+ this.certChainData = null;
+ this.keyInfoRes = keyInfoRes;
+ attributeValidationData = new ArrayList();
+ signatureValidationData = new ArrayList();
+ this.currentTime = currentTime;
+ untrustedAttributeCertificates = new HashSet();
+ untrustedAttributeCRLs = new HashSet();
+ untrustedSignatureCertificates = new HashSet();
+ untrustedSignatureCRLs = new HashSet();
+ }
+
+ public Collection getAttributeValidationData()
+ {
+ return attributeValidationData;
+ }
+
+ public void addAttributeValidationData(ValidationData validationData)
+ {
+ attributeValidationData.add(validationData);
+ }
+
+ public Collection getSignatureValidationData()
+ {
+ return signatureValidationData;
+ }
+
+ public void addSignatureValidationData(ValidationData validationData)
+ {
+ signatureValidationData.add(validationData);
+ }
+
+ /**
+ * Changes the time at which subsequent verifications take place, used to ensure
+ * monotonicity of time in time stamps.
+ *
+ * @param currentTime new time at which subsequent verifications should happen
+ * @throws IllegalArgumentException when currentTime is later (in future)
+ * than time saved in this context
+ * ({@code currentTime.getTime() > this.currentTime.getTime()})
+ */
+ public void setCurrentTime(Date currentTime)
+ throws IllegalArgumentException
+ {
+ if (this.currentTime.getTime() < currentTime.getTime()) {
+ final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+ throw new IllegalArgumentException(String.format("New time from TimeStamp is in the future %s < %s",
+ formatter.format(this.currentTime.getTime()), formatter.format(currentTime.getTime())));
+ }
+
+ this.currentTime = new Date(currentTime.getTime());
+ }
+
+ public Date getCurrentTime()
+ {
+ return currentTime;
}
public XMLSignature getSignature()
@@ -72,6 +166,11 @@ public SignedObjectsData getSignedObjectsData()
return signedObjectsData;
}
+ public KeyInfoRes getKeyInfoRes()
+ {
+ return keyInfoRes;
+ }
+
/**
*
*/
@@ -208,4 +307,77 @@ private TObj getReferencedElement(
}
}
}
+
+ public void setCertificationChainData(
+ CertificationChainData certificationChainData)
+ {
+ this.certChainData = certificationChainData;
+ }
+
+ /**
+ * Remember the untrusted certificates found in properties.
+ * The same certificate can be provided multiple times and it will be saved only once.
+ * @param certificates found properties
+ */
+ public void addAttributeCertificates(Collection certificates)
+ {
+ untrustedAttributeCertificates.addAll(certificates);
+ }
+
+ /**
+ * Remember the untrusted attribute certificates found in properties.
+ * The same CRL can be provided multiple times and it will be saved only once.
+ * @param crls found crls
+ */
+ public void addAttributeCRLs(Collection crls)
+ {
+ untrustedAttributeCRLs.addAll(crls);
+ }
+
+ /**
+ * @return list of untrusted CRLs read from properties
+ */
+ public Collection getAttributeCRLs()
+ {
+ return untrustedAttributeCRLs;
+ }
+
+ /**
+ * @return list of untrusted certificates read from properties
+ */
+ public Collection getAttributeCertificates()
+ {
+ return untrustedAttributeCertificates;
+ }
+
+ /**
+ * Remember the untrusted signature certificates found in properties.
+ * The same certificates can be provided multiple times and it will be saved only
+ * once.
+ * @param certificates certificates to save
+ */
+ public void addSignatureCertificates(Collection certificates)
+ {
+ untrustedSignatureCertificates.addAll(certificates);
+ }
+
+ /**
+ * Remember the untrusted signature revocation data (CRLs) found in properties.
+ * The same CRL can be provided multiple times and it will be save only one.
+ * @param crls CRLs to save
+ */
+ public void addSignatureCRLs(Collection crls)
+ {
+ untrustedSignatureCRLs.addAll(crls);
+ }
+
+ public Collection getSignatureCRLs()
+ {
+ return untrustedSignatureCRLs;
+ }
+
+ public Collection getSignatureCertificates()
+ {
+ return untrustedSignatureCertificates;
+ }
}
diff --git a/src/main/java/xades4j/verification/QualifyingPropertyVerifier.java b/src/main/java/xades4j/verification/QualifyingPropertyVerifier.java
index 46628981..768de456 100644
--- a/src/main/java/xades4j/verification/QualifyingPropertyVerifier.java
+++ b/src/main/java/xades4j/verification/QualifyingPropertyVerifier.java
@@ -16,6 +16,8 @@
*/
package xades4j.verification;
+import org.w3c.dom.Element;
+
import xades4j.properties.QualifyingProperty;
import xades4j.properties.data.PropertyDataObject;
@@ -43,4 +45,22 @@ public interface QualifyingPropertyVerifier
public QualifyingProperty verify(
TData propData,
QualifyingPropertyVerificationContext ctx) throws InvalidPropertyException;
+
+ /**
+ * Verifies the property data and return the corresponding 'high-level'
+ * property instance. In case of failure, an exception should be thrown. This
+ * is done in order to prevent a failure to be undetected by erroneous code.
+ * Furthermore, the data structures resulting for the verification process
+ * become simpler.
+ *
+ * @param propData the property data
+ * @param elem the XML element from which the property data originated from
+ * @param ctx the context with data for validation
+ * @return the verified QualifyingProperty (never {@code null})
+ * @throws InvalidPropertyException (or subclasses) if the property validation fails
+ */
+ public QualifyingProperty verify(
+ TData propData,
+ Element elem,
+ QualifyingPropertyVerificationContext ctx) throws InvalidPropertyException;
}
diff --git a/src/main/java/xades4j/verification/RevocationValuesVerifier.java b/src/main/java/xades4j/verification/RevocationValuesVerifier.java
new file mode 100644
index 00000000..7626ae26
--- /dev/null
+++ b/src/main/java/xades4j/verification/RevocationValuesVerifier.java
@@ -0,0 +1,56 @@
+/*
+ * XAdES4j - A Java library for generation and verification of XAdES signatures.
+ * Copyright (C) 2012 Hubert Kario - QBS
+ *
+ * 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