diff --git a/pom.xml b/pom.xml
index ef68e43..8a33ecd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -208,11 +208,38 @@
jsonld-common-java
1.14.0
+
+ decentralized-identity
+ uni-resolver-local
+ 0.30.0
+ true
+
+
+ commons-logging
+ commons-logging
+
+
+
com.danubetech
data-integrity-java
1.17.0
+
+ com.danubetech
+ danubetech-common-java
+ 1.29.0
+
+
+ com.danubetech
+ notarization-service-client
+ 0.1.0
+
+
+ com.danubetech
+ revocation-service-client
+ 0.2.0
+
com.nimbusds
nimbus-jose-jwt
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/VerifyingException.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/VerifyingException.java
new file mode 100644
index 0000000..8f98af7
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/VerifyingException.java
@@ -0,0 +1,33 @@
+package com.danubetech.verifiablecredentials.verifier;
+
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+
+public class VerifyingException extends Exception {
+
+ private VerifyResult verifyResult;
+
+ public VerifyingException(String message) {
+ super(message);
+ }
+
+ public VerifyingException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ public VerifyingException(VerifyResult verifyResult) {
+ this(verifyResult.getErrorMessage() == null ? "(unknown error)" : verifyResult.getErrorMessage());
+ this.verifyResult = verifyResult;
+ }
+
+ /*
+ * Getters and setters
+ */
+
+ public VerifyResult getVerifyResult() {
+ return verifyResult;
+ }
+
+ public void setVerifyResult(VerifyResult verifyResult) {
+ this.verifyResult = verifyResult;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/AbstractChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/AbstractChecker.java
new file mode 100644
index 0000000..ebdc430
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/AbstractChecker.java
@@ -0,0 +1,77 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public abstract class AbstractChecker implements Checker {
+
+ private static Logger log = LoggerFactory.getLogger(AbstractChecker.class);
+
+ private final String checkName;
+
+ protected AbstractChecker(String checkName) {
+ this.checkName = checkName;
+ }
+
+ protected abstract R checkInternal(I i, VerifyResult verifyResult) throws VerifyingException;
+
+ @Override
+ public final R check(I i, VerifyResult verifyResult) {
+
+ try {
+
+ R r = this.checkInternal(i, verifyResult);
+ if (log.isDebugEnabled()) log.debug("Result for " + this.getClass().getSimpleName() + ": " + (r == null ? null : r.getClass().getSimpleName()));
+ if (r != null) this.getCheckMetadata(verifyResult);
+ return r;
+ } catch (VerifyingException ex) {
+
+ String message = ex.getMessage() != null ? ex.getMessage() : ex.getClass().getSimpleName();
+ if (log.isWarnEnabled()) log.warn("Verifying exception for " + this.getClass().getSimpleName() + ": " + message, ex);
+ this.getCheckMetadata(verifyResult);
+ this.addProblem(verifyResult, message);
+ return null;
+ } catch (Exception ex) {
+
+ String message = ex.getMessage() != null ? ex.getMessage() : ex.getClass().getSimpleName();
+ if (log.isWarnEnabled()) log.warn("Exception for " + this.getClass().getSimpleName() + ": " + message, ex);
+ this.getCheckMetadata(verifyResult);
+ this.addProblem(verifyResult, message);
+ return null;
+ }
+ }
+
+ protected final Map getCheckMetadata(VerifyResult verifyResult) {
+ return verifyResult.getCheckMetadata(this.getCheckName());
+ }
+
+ protected final void addProblem(VerifyResult verifyResult, String message, Map problemMetadata) {
+ if (problemMetadata == null) problemMetadata = new LinkedHashMap<>();
+ problemMetadata.put("check", this.getCheckName());
+ verifyResult.addProblem(message, problemMetadata);
+ }
+
+ protected final void addProblem(VerifyResult verifyResult, String message) {
+ this.addProblem(verifyResult, message, null);
+ }
+
+ protected final void addWarning(VerifyResult verifyResult, String message, Map warningMetadata) {
+ if (warningMetadata == null) warningMetadata = new LinkedHashMap<>();
+ warningMetadata.put("check", this.getCheckName());
+ verifyResult.addWarning(message, warningMetadata);
+ }
+
+ protected final void addWarning(VerifyResult verifyResult, String message) {
+ this.addWarning(verifyResult, message, null);
+ }
+
+ @Override
+ public String getCheckName() {
+ return this.checkName;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/Checker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/Checker.java
new file mode 100644
index 0000000..58804e8
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/Checker.java
@@ -0,0 +1,9 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+
+public interface Checker {
+
+ public R check(I i, VerifyResult verifyResult);
+ public String getCheckName();
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/ExpirationDateChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/ExpirationDateChecker.java
new file mode 100644
index 0000000..0ced526
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/ExpirationDateChecker.java
@@ -0,0 +1,33 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.verifiablecredentials.VerifiableCredential;
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+public class ExpirationDateChecker extends AbstractChecker implements Checker {
+
+ private static Logger log = LoggerFactory.getLogger(ExpirationDateChecker.class);
+
+ public ExpirationDateChecker() {
+ super("expiration-date");
+ }
+
+ @Override
+ public Void checkInternal(VerifiableCredential verifiableCredential, VerifyResult verifyResult) throws VerifyingException {
+
+ if (verifiableCredential.getExpirationDate() == null) return null;
+
+ // check issuance date
+
+ if (verifiableCredential.getExpirationDate().before(new Date())) throw new VerifyingException("Expiration date is in the past.");
+ this.getCheckMetadata(verifyResult).put("verified", Boolean.TRUE);
+
+ // done
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/IssuanceDateChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/IssuanceDateChecker.java
new file mode 100644
index 0000000..aeafc1e
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/IssuanceDateChecker.java
@@ -0,0 +1,33 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.verifiablecredentials.VerifiableCredential;
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+public class IssuanceDateChecker extends AbstractChecker implements Checker {
+
+ private static Logger log = LoggerFactory.getLogger(IssuanceDateChecker.class);
+
+ public IssuanceDateChecker() {
+ super("issuance-date");
+ }
+
+ @Override
+ public Void checkInternal(VerifiableCredential verifiableCredential, VerifyResult verifyResult) throws VerifyingException {
+
+ if (verifiableCredential.getIssuanceDate() == null) return null;
+
+ // check issuance date
+
+ if (verifiableCredential.getIssuanceDate().after(new Date())) throw new VerifyingException("Issuance date is in the future.");
+ this.getCheckMetadata(verifyResult).put("verified", Boolean.TRUE);
+
+ // done
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/JsonLDChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/JsonLDChecker.java
new file mode 100644
index 0000000..2c2b378
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/JsonLDChecker.java
@@ -0,0 +1,24 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import foundation.identity.jsonld.JsonLDObject;
+import foundation.identity.jsonld.validation.Validation;
+
+public class JsonLDChecker extends AbstractChecker implements Checker {
+
+ public JsonLDChecker() {
+
+ super("jsonld");
+ }
+
+ @Override
+ public Void checkInternal(JsonLDObject jsonLdObject, VerifyResult verifyResult) throws VerifyingException {
+
+ if (jsonLdObject == null) return null;
+
+ Validation.validate(jsonLdObject);
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/NotarizationChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/NotarizationChecker.java
new file mode 100644
index 0000000..7aa959e
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/NotarizationChecker.java
@@ -0,0 +1,103 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.dataintegrity.DataIntegrityProof;
+import com.danubetech.dataintegrity.canonicalizer.RDFC10SHA256Canonicalizer;
+import com.danubetech.notarizationservice.client.ApiException;
+import com.danubetech.notarizationservice.client.NotarizationServiceClient;
+import com.danubetech.notarizationservice.client.swagger.model.BitcoinVerifyResponse;
+import com.danubetech.verifiablecredentials.VerifiableCredential;
+import com.danubetech.verifiablecredentials.proof.BlockchainHashProof2020;
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import foundation.identity.jsonld.JsonLDException;
+import foundation.identity.jsonld.JsonLDObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Map;
+
+public class NotarizationChecker extends AbstractChecker implements Checker {
+
+ private static Logger log = LoggerFactory.getLogger(NotarizationChecker.class);
+
+ private NotarizationServiceClient notarizationServiceClient;
+
+ public NotarizationChecker(NotarizationServiceClient notarizationServiceClient) {
+
+ super("notarization");
+
+ this.notarizationServiceClient = notarizationServiceClient;
+ }
+
+ @Override
+ public Void checkInternal(VerifiableCredential verifiableCredential, VerifyResult verifyResult) throws VerifyingException {
+
+ Map jsonObject = verifiableCredential.getJsonObject();
+
+ // obtain the normalizedDocument document
+
+ String normalizedDocument;
+
+ try {
+
+ JsonLDObject jsonLdDocumentWithoutProof = JsonLDObject.builder().base(verifiableCredential).build();
+ jsonLdDocumentWithoutProof.setDocumentLoader(verifiableCredential.getDocumentLoader());
+ DataIntegrityProof.removeFromJsonLdObject(jsonLdDocumentWithoutProof);
+ normalizedDocument = RDFC10SHA256Canonicalizer.getInstance().canonicalize(jsonLdDocumentWithoutProof);
+ } catch (JsonLDException | IOException ex) {
+
+ throw new VerifyingException("Normalization problem: " + ex.getMessage(), ex);
+ }
+
+ // check the notarization
+
+ BlockchainHashProof2020 ldProof = BlockchainHashProof2020.getFromJsonLDObject(verifiableCredential);
+ if (log.isDebugEnabled()) log.debug("Found proof: " + ldProof);
+ if (ldProof == null) return null;
+
+ String proofValue = ldProof.getProofValue();
+ String[] proofValueParts = proofValue.split(" ");
+ String txId = proofValueParts[0];
+ String signature = proofValueParts[1];
+
+ BitcoinVerifyResponse bitcoinVerifyResponse;
+
+ try {
+
+ bitcoinVerifyResponse = this.getNotarizationServiceClient().verifyUsingPOST("SHA-256", null, null, Boolean.FALSE, signature, txId, normalizedDocument);
+ if (log.isDebugEnabled()) log.debug("Notarization service response: " + bitcoinVerifyResponse);
+ } catch (ApiException ex) {
+
+ throw new VerifyingException("Cannot check notarization: " + ex.getCode() + " - " + ex.getResponseBody(), ex);
+ }
+
+ if (Boolean.TRUE != bitcoinVerifyResponse.getVerified()) {
+
+ throw new VerifyingException("Credential notarization cannot be verified. txId: " + bitcoinVerifyResponse.getTxId() + ", notarizationBlockHeight: " + bitcoinVerifyResponse.getNotarizationBlockHeight() + ", currentBlockHeight: " + bitcoinVerifyResponse.getCurrentBlockHeight());
+ }
+
+ // CHECK METADATA
+
+ this.getCheckMetadata(verifyResult).put("txId", bitcoinVerifyResponse.getTxId());
+ this.getCheckMetadata(verifyResult).put("notarizationBlockHeight", bitcoinVerifyResponse.getNotarizationBlockHeight());
+ this.getCheckMetadata(verifyResult).put("currentBlockHeight", bitcoinVerifyResponse.getCurrentBlockHeight());
+ this.getCheckMetadata(verifyResult).put("verified", bitcoinVerifyResponse.getVerified());
+
+ // done
+
+ return null;
+ }
+
+ /*
+ * Getters and setters
+ */
+
+ public NotarizationServiceClient getNotarizationServiceClient() {
+ return this.notarizationServiceClient;
+ }
+
+ public void setNotarizationServiceClient(NotarizationServiceClient notarizationServiceClient) {
+ this.notarizationServiceClient = notarizationServiceClient;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/ProofChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/ProofChecker.java
new file mode 100644
index 0000000..73908ab
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/ProofChecker.java
@@ -0,0 +1,198 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.dataintegrity.DataIntegrityProof;
+import com.danubetech.dataintegrity.suites.DataIntegritySuite;
+import com.danubetech.dataintegrity.suites.DataIntegritySuites;
+import com.danubetech.dataintegrity.verifier.LdVerifier;
+import com.danubetech.dataintegrity.verifier.LdVerifierRegistry;
+import com.danubetech.did.util.VerificationMethodUtil;
+import com.danubetech.keyformats.JWK_to_PublicKey;
+import com.danubetech.keyformats.crypto.PublicKeyVerifier;
+import com.danubetech.keyformats.crypto.PublicKeyVerifierFactory;
+import com.danubetech.keyformats.jose.JWK;
+import com.danubetech.keyformats.jose.KeyTypeName;
+import com.danubetech.uniresolver.local.extensions.impl.FragmentDIDExtension;
+import com.danubetech.uniresolver.local.extensions.impl.FragmentJSONExtension;
+import com.danubetech.uniresolver.local.extensions.impl.FragmentJSONLDExtension;
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import foundation.identity.did.VerificationMethod;
+import foundation.identity.did.representations.Representations;
+import foundation.identity.jsonld.JsonLDException;
+import foundation.identity.jsonld.JsonLDObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import uniresolver.DereferencingException;
+import uniresolver.ResolutionException;
+import uniresolver.UniResolver;
+import uniresolver.local.LocalUniDereferencer;
+import uniresolver.result.DereferenceResult;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.util.Map;
+
+public abstract class ProofChecker extends AbstractChecker implements Checker {
+
+ private static Logger log = LoggerFactory.getLogger(ProofChecker.class);
+
+ private UniResolver uniResolver;
+
+ public ProofChecker(String checkName, UniResolver uniResolver) {
+ super(checkName);
+ this.uniResolver = uniResolver;
+ }
+
+ @Override
+ public Void checkInternal(JsonLDObject jsonLDObject, VerifyResult verifyResult) throws VerifyingException {
+
+ // look up proof from Verifiable Credential
+
+ DataIntegrityProof dataIntegrityProof = DataIntegrityProof.getFromJsonLDObject(jsonLDObject);
+ if (dataIntegrityProof == null) throw new VerifyingException("No proof.");
+ this.getCheckMetadata(verifyResult).put("proofType", dataIntegrityProof.getType());
+
+ // look up cryptosuite
+
+ String cryptosuite = dataIntegrityProof.getCryptosuite();
+ this.getCheckMetadata(verifyResult).put("cryptosuite", cryptosuite);
+
+ // look up verification method URI
+
+ URI verificationMethodUri = dataIntegrityProof.getVerificationMethod();
+ if (verificationMethodUri == null) throw new VerifyingException("No verification method URI for proof " + dataIntegrityProof);
+ this.getCheckMetadata(verifyResult).put("verificationMethod", verificationMethodUri);
+
+ // dereference verification method
+
+ LocalUniDereferencer localUniDereferencer = new LocalUniDereferencer();
+ localUniDereferencer.setUniResolver(this.getUniResolver());
+ localUniDereferencer.getExtensions().add(new FragmentDIDExtension());
+ localUniDereferencer.getExtensions().add(new FragmentJSONLDExtension());
+ localUniDereferencer.getExtensions().add(new FragmentJSONExtension());
+
+ VerificationMethod verificationMethod = null;
+
+ try {
+ DereferenceResult dereferenceResult = localUniDereferencer.dereference(verificationMethodUri.toString(), Map.of("accept", Representations.DEFAULT_MEDIA_TYPE));
+ if (dereferenceResult.getContent() == null || dereferenceResult.getContent().length < 1) {
+ throw new VerifyingException("No dereferencing result for " + verificationMethodUri);
+ }
+
+ verificationMethod = VerificationMethod.fromJson(new InputStreamReader(new ByteArrayInputStream(dereferenceResult.getContent()), StandardCharsets.UTF_8));
+ if (log.isDebugEnabled()) log.debug("Found verification method for " + verificationMethodUri + ": " + verificationMethod.toJson());
+ this.getCheckMetadata(verifyResult).put("verificationMethodType", verificationMethod.getType());
+ } catch (ResolutionException | DereferencingException ex) {
+ throw new VerifyingException("Cannot dereference URI " + verificationMethodUri + ": " + ex.getMessage(), ex);
+ }
+
+ // prepare LD verifier
+
+ LdVerifier> ldVerifier;
+
+ KeyTypeName verificationMethodKeyTypeName = findKeyTypeNameForVerificationMethod(verificationMethod);
+ this.getCheckMetadata(verifyResult).put("verificationMethodKeyType", verificationMethodKeyTypeName);
+
+ DataIntegritySuite dataIntegritySuite = findDataIntegritySuiteByLdProof(dataIntegrityProof);
+ this.getCheckMetadata(verifyResult).put("dataIntegritySuite", dataIntegritySuite.getTerm());
+
+ String jwsAlgorithm = findJwsAlgorithmByDataIntegritySuiteAndVerificationMethodKeyTypeName(dataIntegritySuite, verificationMethodKeyTypeName, cryptosuite);
+ this.getCheckMetadata(verifyResult).put("jwsAlgorithm", jwsAlgorithm);
+
+ JWK verificationMethodJwk = findVerificationMethodJwkByVerificationMethod(verificationMethod);
+ this.getCheckMetadata(verifyResult).put("verificationMethodJwk", verificationMethodJwk.toMap());
+
+ Object publicKey = findPublicKeyByVerificationMethodJwk(verificationMethodJwk);
+
+ PublicKeyVerifier> publicKeyVerifier = findPublicKeyVerifierForVerificationMethodKeyTypeNameAndJwsAlgorithmAndPublicKey(verificationMethodKeyTypeName, jwsAlgorithm, publicKey);
+
+ ldVerifier = findLdVerifierForDataIntegritySuite(dataIntegritySuite);
+ ldVerifier.setVerifier(publicKeyVerifier);
+
+ // verify
+
+ try {
+
+ if (! ldVerifier.verify(jsonLDObject)) throw new VerifyingException("Cannot verify signature.");
+ if (log.isInfoEnabled()) log.info("Verified signature: " + dataIntegrityProof);
+ } catch (JsonLDException | IOException ex) {
+
+ throw new VerifyingException("Cannot verify signature (JSON-LD problem): " + ex.getMessage(), ex);
+ } catch (GeneralSecurityException ex) {
+
+ throw new VerifyingException("Cannot verify signature (security problem): " + ex.getMessage(), ex);
+ }
+
+ // done
+
+ return null;
+ }
+
+ /*
+ * Helper methods
+ */
+
+ public static KeyTypeName findKeyTypeNameForVerificationMethod(VerificationMethod verificationMethod) throws VerifyingException {
+ KeyTypeName verificationMethodKeyTypeName = verificationMethod == null ? null : VerificationMethodUtil.getKeyTypeName(verificationMethod);
+ if (verificationMethodKeyTypeName == null) throw new VerifyingException("No key type name for verification method " + (verificationMethod == null ? null : verificationMethod.getId()));
+ if (log.isDebugEnabled()) log.debug("For verification method " + verificationMethod.getId() + " found key type name: " + verificationMethodKeyTypeName);
+ return verificationMethodKeyTypeName;
+ }
+
+ public static DataIntegritySuite findDataIntegritySuiteByLdProof(DataIntegrityProof dataIntegrityProof) throws VerifyingException {
+ DataIntegritySuite dataIntegritySuite = dataIntegrityProof == null ? null : DataIntegritySuites.findDataIntegritySuiteByTerm(dataIntegrityProof.getType());
+ if (dataIntegritySuite == null) throw new VerifyingException("No data integrity suite for proof type " + (dataIntegrityProof == null ? null : dataIntegrityProof.getType()));
+ if (log.isDebugEnabled()) log.debug("For proof type " + dataIntegrityProof.getType() + " found data integrity suite " + dataIntegritySuite.getId());
+ return dataIntegritySuite;
+ }
+
+ public static String findJwsAlgorithmByDataIntegritySuiteAndVerificationMethodKeyTypeName(DataIntegritySuite dataIntegritySuite, KeyTypeName verificationMethodKeyTypeName, String cryptosuite) throws VerifyingException {
+ String jwsAlgorithm = dataIntegritySuite == null ? null : dataIntegritySuite.findDefaultJwsAlgorithmForKeyTypeName(verificationMethodKeyTypeName, cryptosuite);
+ if (jwsAlgorithm == null) throw new VerifyingException("No JWS algorithm for data integrity suite " + (dataIntegritySuite == null ? null : dataIntegritySuite.getId()) + " and key type name " + verificationMethodKeyTypeName);
+ if (log.isDebugEnabled()) log.debug("For data integrity suite " + (dataIntegritySuite == null ? null : dataIntegritySuite.getId()) + " and key type name " + verificationMethodKeyTypeName + " found JWS algorithm: " + jwsAlgorithm);
+ return jwsAlgorithm;
+ }
+
+ public static JWK findVerificationMethodJwkByVerificationMethod(VerificationMethod verificationMethod) throws VerifyingException {
+ JWK verificationMethodJwk = verificationMethod == null ? null : VerificationMethodUtil.getVerificationMethodJwk(verificationMethod);
+ if (verificationMethodJwk == null) throw new VerifyingException("No verification method JWK for verification method " + (verificationMethod == null ? null : verificationMethod.getId()));
+ if (log.isDebugEnabled()) log.debug("For verification method " + verificationMethod.getId() + " found verification method JWK: " + verificationMethodJwk);
+ return verificationMethodJwk;
+ }
+
+ public static Object findPublicKeyByVerificationMethodJwk(JWK verificationMethodJwk) throws VerifyingException {
+ Object publicKey = verificationMethodJwk == null ? null : JWK_to_PublicKey.JWK_to_anyPublicKey(verificationMethodJwk);
+ if (publicKey == null) throw new VerifyingException("No public key for verification method JWK " + verificationMethodJwk);
+ if (log.isDebugEnabled()) log.debug("For verification method JWK " + verificationMethodJwk + " found public key " + publicKey.getClass());
+ return publicKey;
+ }
+
+ public static PublicKeyVerifier> findPublicKeyVerifierForVerificationMethodKeyTypeNameAndJwsAlgorithmAndPublicKey(KeyTypeName verificationMethodKeyTypeName, String jwsAlgorithm, Object publicKey) {
+ PublicKeyVerifier> publicKeyVerifier = verificationMethodKeyTypeName == null ? null : PublicKeyVerifierFactory.publicKeyVerifierForKey(verificationMethodKeyTypeName, jwsAlgorithm, publicKey);
+ if (log.isDebugEnabled()) log.debug("For key type name " + verificationMethodKeyTypeName + " and JWS algorithm " + jwsAlgorithm + " and public key " + (publicKey == null ? null : publicKey.getClass()) + " found public key verifier " + (publicKeyVerifier == null ? null : publicKeyVerifier.getClass()));
+ return publicKeyVerifier;
+ }
+
+ public static LdVerifier> findLdVerifierForDataIntegritySuite(DataIntegritySuite dataIntegritySuite) throws VerifyingException {
+ LdVerifier> ldVerifier = dataIntegritySuite == null ? null : LdVerifierRegistry.getLdVerifierByDataIntegritySuite(dataIntegritySuite);
+ if (ldVerifier == null) throw new VerifyingException("No LD verifier for data integrity suite " + (dataIntegritySuite == null ? null : dataIntegritySuite.getId()));
+ if (log.isDebugEnabled()) log.debug("For data integrity suite " + dataIntegritySuite.getId() + " found LD verifier " + ldVerifier.getClass());
+ return ldVerifier;
+ }
+
+ /*
+ * Getters and setters
+ */
+
+ public UniResolver getUniResolver() {
+ return uniResolver;
+ }
+
+ public void setUniResolver(UniResolver uniResolver) {
+ this.uniResolver = uniResolver;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/RevocationChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/RevocationChecker.java
new file mode 100644
index 0000000..6c62551
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/RevocationChecker.java
@@ -0,0 +1,107 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.revocationservice.client.ApiException;
+import com.danubetech.revocationservice.client.RevocationServiceClient;
+import com.danubetech.revocationservice.client.openapi.model.CheckRequest;
+import com.danubetech.revocationservice.client.openapi.model.CheckResponse;
+import com.danubetech.verifiablecredentials.VerifiableCredential;
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RevocationChecker extends AbstractChecker implements Checker {
+
+ private static Logger log = LoggerFactory.getLogger(RevocationChecker.class);
+
+ private RevocationServiceClient revocationServiceClient;
+
+ public RevocationChecker(RevocationServiceClient revocationServiceClient) {
+ super("credential-status");
+ this.revocationServiceClient = revocationServiceClient;
+ }
+
+ @Override
+ public Void checkInternal(VerifiableCredential verifiableCredential, VerifyResult verifyResult) throws VerifyingException {
+
+ // check revocation
+
+ CheckRequest checkRequest = new CheckRequest();
+ checkRequest.setCredential(verifiableCredential);
+
+ CheckResponse checkResponse;
+
+ try {
+
+ checkResponse = this.getRevocationServiceClient().check("jsonld", checkRequest);
+ } catch (ApiException ex) {
+
+ throw new VerifyingException("Cannot check revocation: " + ex.getCode() + " - " + ex.getResponseBody(), ex);
+ }
+ if (checkResponse == null || checkResponse.getRevoked() == null) throw new VerifyingException("Revocation Check Failed: " + checkResponse );
+ if (! Boolean.FALSE.equals(checkResponse.getRevoked())) throw new VerifyingException("Credential has been revoked");
+
+ this.getCheckMetadata(verifyResult).put("revoked", checkResponse.getRevoked());
+ this.getCheckMetadata(verifyResult).put("metadata", checkResponse.getMetadata());
+
+ return null;
+
+/* // check the revocation
+
+ RevocationQuery2020Status ldCredentialStatus = RevocationQuery2020Status.getFromJsonLDObject(verifiableCredential);
+ if (log.isDebugEnabled()) log.debug("Found credential status: " + ldCredentialStatus);
+ if (ldCredentialStatus == null) return null;
+
+ String credentialReference = ldCredentialStatus.getCredentialReference();
+ String revocationService = ldCredentialStatus.getRevocationService();
+
+ Revocation revocation;
+
+ try {
+
+ String revocationServiceBasePath = revocationService.substring(0, revocationService.lastIndexOf("/"));
+ if (log.isDebugEnabled()) log.debug("Revocation service base path: " + revocationServiceBasePath);
+ RevocationServiceClient revocationServiceClient = RevocationServiceClient.create(revocationServiceBasePath);
+
+ revocation = revocationServiceClient.getRevocation(UUID.fromString(credentialReference));
+ if (log.isDebugEnabled()) log.debug("Revocation service response: " + revocation);
+ } catch (ApiException ex) {
+
+ if (ex.getCode() == 404) {
+
+ revocation = null;
+ } else {
+
+ String exMessage = ex.getCode() + ": " + ex.getMessage();
+ throw new VerifyingException("Revocation problem: " + exMessage, ex);
+ }
+ }
+
+ if (revocation != null) {
+
+ throw new VerifyingException("Credential has been revoked. timestamp: " + revocation.getTimestamp() + ", reason: " + revocation.getReason());
+ }
+
+ // CHECK METADATA
+
+ this.getCheckMetadata().put("credentialReference", credentialReference);
+
+ // done
+
+ return null;*/
+ }
+
+ /*
+ * Getters and setters
+ */
+
+ public RevocationServiceClient getRevocationServiceClient() {
+
+ return this.revocationServiceClient;
+ }
+
+ public void setRevocationServiceClient(RevocationServiceClient revocationServiceClient) {
+
+ this.revocationServiceClient = revocationServiceClient;
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/VerifiableCredentialProofChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/VerifiableCredentialProofChecker.java
new file mode 100644
index 0000000..f35ea95
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/VerifiableCredentialProofChecker.java
@@ -0,0 +1,11 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.danubetech.verifiablecredentials.VerifiableCredential;
+import uniresolver.UniResolver;
+
+public class VerifiableCredentialProofChecker extends ProofChecker {
+
+ public VerifiableCredentialProofChecker(UniResolver uniResolver) {
+ super("credential-proof", uniResolver);
+ }
+}
diff --git a/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/VerifiableCredentialValidationChecker.java b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/VerifiableCredentialValidationChecker.java
new file mode 100644
index 0000000..666e714
--- /dev/null
+++ b/src/main/java/com/danubetech/verifiablecredentials/verifier/checker/VerifiableCredentialValidationChecker.java
@@ -0,0 +1,35 @@
+package com.danubetech.verifiablecredentials.verifier.checker;
+
+import com.apicatalog.jsonld.loader.DocumentLoader;
+import com.danubetech.verifiablecredentials.VerifiableCredential;
+import com.danubetech.verifiablecredentials.validation.Validation;
+import com.danubetech.verifiablecredentials.verifier.VerifyingException;
+import com.danubetech.verifiablecredentials.verifier.result.VerifyResult;
+
+import java.util.Map;
+
+public class VerifiableCredentialValidationChecker extends AbstractChecker