Search code examples
javaxmlverifyerrorxades4j

Xades4j - XML Signature Verification error - SignaturePolicyNotAvailableException


I receive XML Invoice with Xades EPES signature and I have to control it. So I try to do that with Xades4j. I have fixed lot of error But I stuck on the error:

errxades4j.verification.SignaturePolicyNotAvailableException: Verification failed for property 'SignaturePolicyIdentifier': signature policy document is not available
    at xades4j.verification.SignaturePolicyVerifier.verify(SignaturePolicyVerifier.java:67)
    at xades4j.verification.SignaturePolicyVerifier.verify(SignaturePolicyVerifier.java:38)
    at xades4j.verification.QualifyingPropertiesVerifierImpl.verifyProperties(QualifyingPropertiesVerifierImpl.java:58)
    at xades4j.verification.XadesVerifierImpl.verify(XadesVerifierImpl.java:202)

Java code use to verify signature :

FileInputStream fis = new FileInputStream("keystore.jks");
KeyStore trustAnchors = KeyStore.getInstance("jks");
trustAnchors.load(fis,"password".toCharArray());
fis.close();

CertificateValidationProvider certValidator = new PKIXCertificateValidationProvider(trustAnchors, false);
XadesVerificationProfile p = new XadesVerificationProfile(certValidator);
XadesVerifier v = p.newVerifier();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db =  dbf.newDocumentBuilder();
FileInputStream is = new FileInputStream(filename);
Document doc = db.parse(is);

Element sigElem = (Element)doc.getElementsByTagNameNS(Constants.SignatureSpecNS, Constants._TAG_SIGNATURE).item(0);
XAdESVerificationResult r = null;
r = v.verify(sigElem,null);

If necessary I can post an extract of kind of XML file I try to verify after anonymization.

Thanks. I have looked and tried all i have found (on the net, xades4j example, xades4j junit class...) but nothing seems to resolve my error.


Solution

  • You need to specify your own policy document provider like this: p.withPolicyDocumentProvider(). And you have to implement your own policy provider which implements the interfaces SignaturePolicyInfoProvider and SignaturePolicyDocumentProvider. (at least I did it that way)

    Edit to your comment:

    You need to implement SignaturePolicyInfoProvider.getSignaturePolicyDocumentStream(), which returns an InputStream. This can be a FileInputStream

    Example:

    public class FilebasedSignaturePolicyProvider implements  SignaturePolicyDocumentProvider {
    
        @Override
        public InputStream getSignaturePolicyDocumentStream(ObjectIdentifier sigPolicyId) {
            String oid = sigPolicyId.getIdentifier();
    
            try {
                return new FileInputStream("directory-to-my-policy-files/" + oid);
            } catch (FileNotFoundException e) {
                // handle error
            }
        }
    }