Add support for remote key material

This commit is contained in:
Andy Miller (IMS) 2022-11-10 15:24:24 -08:00
parent 4eb82c819b
commit 84a7f82c5f

View File

@ -2,6 +2,7 @@ package org.oneedtech.inspect.vc.probe;
import java.io.StringReader; import java.io.StringReader;
import java.net.URI; import java.net.URI;
import java.util.Optional;
import org.oneedtech.inspect.core.probe.Probe; import org.oneedtech.inspect.core.probe.Probe;
import org.oneedtech.inspect.core.probe.RunContext; import org.oneedtech.inspect.core.probe.RunContext;
@ -9,6 +10,9 @@ import org.oneedtech.inspect.core.report.ReportItems;
import org.oneedtech.inspect.vc.Credential; import org.oneedtech.inspect.vc.Credential;
import org.oneedtech.inspect.vc.util.CachingDocumentLoader; import org.oneedtech.inspect.vc.util.CachingDocumentLoader;
import com.apicatalog.jsonld.StringUtils;
import com.apicatalog.jsonld.document.Document;
import com.apicatalog.jsonld.loader.DocumentLoaderOptions;
import com.apicatalog.ld.DocumentError; import com.apicatalog.ld.DocumentError;
import com.apicatalog.multibase.Multibase; import com.apicatalog.multibase.Multibase;
import com.apicatalog.multicodec.Multicodec; import com.apicatalog.multicodec.Multicodec;
@ -16,10 +20,14 @@ import com.apicatalog.multicodec.Multicodec.Codec;
import com.apicatalog.vc.processor.StatusVerifier; import com.apicatalog.vc.processor.StatusVerifier;
import com.danubetech.verifiablecredentials.VerifiableCredential; import com.danubetech.verifiablecredentials.VerifiableCredential;
import foundation.identity.jsonld.ConfigurableDocumentLoader;
import info.weboftrust.ldsignatures.verifier.Ed25519Signature2020LdVerifier; import info.weboftrust.ldsignatures.verifier.Ed25519Signature2020LdVerifier;
import jakarta.json.JsonObject;
import jakarta.json.JsonStructure;
/** /**
* A Probe that verifies a credential's embedded proof. * A Probe that verifies a credential's embedded proof.
*
* @author mgylling * @author mgylling
*/ */
public class EmbeddedProofProbe extends Probe<Credential> { public class EmbeddedProofProbe extends Probe<Credential> {
@ -28,14 +36,15 @@ public class EmbeddedProofProbe extends Probe<Credential> {
super(ID); super(ID);
} }
/* /*
* Using verifiable-credentials-java (https://github.com/danubetech/verifiable-credentials-java) * Using verifiable-credentials-java
* (https://github.com/danubetech/verifiable-credentials-java)
*/ */
@Override @Override
public ReportItems run(Credential crd, RunContext ctx) throws Exception { public ReportItems run(Credential crd, RunContext ctx) throws Exception {
//TODO check that proof is Ed25519 - issue error if not ("type": "Ed25519Signature2020", // TODO check that proof is Ed25519 - issue error if not ("type":
// "Ed25519Signature2020",
// TODO check value "proofPurpose": "assertionMethod", if not error // TODO check value "proofPurpose": "assertionMethod", if not error
VerifiableCredential vc = VerifiableCredential.fromJson(new StringReader(crd.getJson().toString())); VerifiableCredential vc = VerifiableCredential.fromJson(new StringReader(crd.getJson().toString()));
@ -47,7 +56,8 @@ public class EmbeddedProofProbe extends Probe<Credential> {
// Danubetech's Ed25519Signature2020LdVerifier expects the decoded public key // Danubetech's Ed25519Signature2020LdVerifier expects the decoded public key
// from the Ed25519VerificationKey2020 (32 bytes). // from the Ed25519VerificationKey2020 (32 bytes).
String publicKeyMultibase = ""; String publicKeyMultibase;
String controller;
// Formats accepted: // Formats accepted:
// //
@ -55,8 +65,10 @@ public class EmbeddedProofProbe extends Probe<Credential> {
// did:key:[publicKeyMultibase] // did:key:[publicKeyMultibase]
// [publicKeyMultibase] // [publicKeyMultibase]
// TODO fourth format that we don't support yet: a URL that returns a Ed25519VerificationKey2020 // TODO fourth format that we don't support yet: a URL that returns a
// if starts with http and does not have hashcode, try fetch and see if returns Ed25519VerificationKey2020 // Ed25519VerificationKey2020
// if starts with http and does not have hashcode, try fetch and see if returns
// Ed25519VerificationKey2020
// property is publicKeyMultibase // property is publicKeyMultibase
publicKeyMultibase = method.toString(); publicKeyMultibase = method.toString();
@ -71,7 +83,31 @@ public class EmbeddedProofProbe extends Probe<Credential> {
return error("Unknown verification method: " + method, ctx); return error("Unknown verification method: " + method, ctx);
} }
} else if (method.getScheme().equals("http") || method.getScheme().equals("https")) { } else if (method.getScheme().equals("http") || method.getScheme().equals("https")) {
return error("Cannot parse http verification key yet", ctx); ConfigurableDocumentLoader documentLoader = new ConfigurableDocumentLoader();
documentLoader.setEnableHttp(true);
documentLoader.setEnableHttps(true);
// The verificationMethod URI must resolve to a Ed25519VerificationKey2020 as described here:
// https://w3c-ccg.github.io/di-eddsa-2020/#ed25519verificationkey2020
Document keyDocument = documentLoader.loadDocument(method, new DocumentLoaderOptions());
Optional<JsonStructure> keyStructure = keyDocument.getJsonContent();
if (keyStructure.isEmpty()) {
return error("Key document not found at " + method, ctx);
}
// First look for a plain key object
controller = keyStructure.get().asJsonObject().getString("controller");
if (StringUtils.isBlank(controller)) {
// Then look for a controller document (e.g. DID Document)
JsonObject keyVerificationMethod = keyStructure.get().asJsonObject()
.getJsonObject("verificationMethod");
if (keyVerificationMethod.isEmpty()) {
return error("Cannot parse key document from " + method, ctx);
}
controller = keyVerificationMethod.getString("controller");
publicKeyMultibase = keyVerificationMethod.getString("publicKeyMultibase");
} else {
publicKeyMultibase = keyStructure.get().asJsonObject().getString("publicKeyMultibase");
}
} }
} }
@ -95,7 +131,8 @@ public class EmbeddedProofProbe extends Probe<Credential> {
// TODO find out whether we also should check that controller matches issuer ID: // TODO find out whether we also should check that controller matches issuer ID:
// if [controller]#[publicKeyMultibase] format - check [controller] segment // if [controller]#[publicKeyMultibase] format - check [controller] segment
// if did:key:[publicKeyMultibase] format: issuer ID must match the entire URI // if did:key:[publicKeyMultibase] format: issuer ID must match the entire URI
// if [publicKeyMultibase] -- don't check issuer ID. Maybe we should warn about this syntax. // if [publicKeyMultibase] -- don't check issuer ID. Maybe we should warn about
// this syntax.
try { try {
boolean verify = verifier.verify(vc); boolean verify = verifier.verify(vc);
@ -109,8 +146,6 @@ public class EmbeddedProofProbe extends Probe<Credential> {
return success(ctx); return success(ctx);
} }
/* /*
* Note: if using com.apicatalog Iron, we get a generic VC verifier that * Note: if using com.apicatalog Iron, we get a generic VC verifier that
* will test other stuff than the Proof. So sometimes it may be that * will test other stuff than the Proof. So sometimes it may be that
@ -121,11 +156,13 @@ public class EmbeddedProofProbe extends Probe<Credential> {
*/ */
// /* // /*
// * Using iron-verifiable-credentials (https://github.com/filip26/iron-verifiable-credentials) // * Using iron-verifiable-credentials
// (https://github.com/filip26/iron-verifiable-credentials)
// */ // */
// @Override // @Override
// public ReportItems run(Credential crd, RunContext ctx) throws Exception { // public ReportItems run(Credential crd, RunContext ctx) throws Exception {
// JsonDocument jsonDoc = JsonDocument.of(new StringReader(crd.getJson().toString())); // JsonDocument jsonDoc = JsonDocument.of(new
// StringReader(crd.getJson().toString()));
// JsonObject json = jsonDoc.getJsonContent().get().asJsonObject(); // JsonObject json = jsonDoc.getJsonContent().get().asJsonObject();
// try { // try {
// Vc.verify(json) // Vc.verify(json)