commit
08d74d287d
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.1edtech</groupId>
|
||||
<artifactId>vc-public-validator</artifactId>
|
||||
<version>1.0.4</version>
|
||||
<version>1.0.5</version>
|
||||
</parent>
|
||||
<artifactId>inspector-vc-web</artifactId>
|
||||
<properties>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.1edtech</groupId>
|
||||
<artifactId>vc-public-validator</artifactId>
|
||||
<version>1.0.4</version>
|
||||
<version>1.0.5</version>
|
||||
</parent>
|
||||
<artifactId>inspector-vc</artifactId>
|
||||
<dependencies>
|
||||
|
@ -5,162 +5,235 @@ import static org.oneedtech.inspect.vc.VerifiableCredential.Type.ClrCredential;
|
||||
import static org.oneedtech.inspect.vc.VerifiableCredential.Type.EndorsementCredential;
|
||||
import static org.oneedtech.inspect.vc.VerifiableCredential.Type.VerifiablePresentation;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.oneedtech.inspect.schema.Catalog;
|
||||
import org.oneedtech.inspect.schema.SchemaKey;
|
||||
import org.oneedtech.inspect.util.resource.MimeType;
|
||||
import org.oneedtech.inspect.util.resource.Resource;
|
||||
import org.oneedtech.inspect.vc.util.JsonNodeUtil;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* A wrapper object for a verifiable credential. This contains e.g. the origin resource
|
||||
* and the extracted JSON data plus any other stuff Probes need.
|
||||
* A wrapper object for a verifiable credential. This contains e.g. the origin resource and the
|
||||
* extracted JSON data plus any other stuff Probes need.
|
||||
*
|
||||
* @author mgylling
|
||||
*/
|
||||
public class VerifiableCredential extends Credential {
|
||||
final VerifiableCredential.Type credentialType;
|
||||
public class VerifiableCredential extends Credential {
|
||||
final VerifiableCredential.Type credentialType;
|
||||
final VCVersion version;
|
||||
|
||||
protected VerifiableCredential(Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas, String issuedOnPropertyName, String expiresAtPropertyName) {
|
||||
super(ID, resource, data, jwt, schemas, issuedOnPropertyName, expiresAtPropertyName);
|
||||
protected VerifiableCredential(
|
||||
Resource resource,
|
||||
JsonNode data,
|
||||
String jwt,
|
||||
Map<CredentialEnum, SchemaKey> schemas,
|
||||
VCVersion version) {
|
||||
super(ID, resource, data, jwt, schemas, version.issuanceDateField, version.expirationDateField);
|
||||
|
||||
JsonNode typeNode = jsonData.get("type");
|
||||
this.credentialType = VerifiableCredential.Type.valueOf(typeNode);
|
||||
JsonNode typeNode = jsonData.get("type");
|
||||
this.credentialType = VerifiableCredential.Type.valueOf(typeNode);
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public CredentialEnum getCredentialType() {
|
||||
return credentialType;
|
||||
}
|
||||
|
||||
public ProofType getProofType() {
|
||||
return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL;
|
||||
}
|
||||
|
||||
public VCVersion getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
private static final Map<CredentialEnum, SchemaKey> schemas =
|
||||
new ImmutableMap.Builder<CredentialEnum, SchemaKey>()
|
||||
.put(AchievementCredential, Catalog.OB_30_ANY_ACHIEVEMENTCREDENTIAL_JSON)
|
||||
.put(ClrCredential, Catalog.CLR_20_ANY_CLRCREDENTIAL_JSON)
|
||||
.put(VerifiablePresentation, Catalog.CLR_20_ANY_CLRCREDENTIAL_JSON)
|
||||
.put(EndorsementCredential, Catalog.OB_30_ANY_ENDORSEMENTCREDENTIAL_JSON)
|
||||
.build();
|
||||
|
||||
public static final String JSONLD_CONTEXT_W3C_CREDENTIALS_V2 = "https://www.w3.org/ns/credentials/v2";
|
||||
|
||||
private static final Map<Set<VerifiableCredential.Type>, List<String>> contextMap =
|
||||
new ImmutableMap.Builder<Set<VerifiableCredential.Type>, List<String>>()
|
||||
.put(
|
||||
Set.of(Type.OpenBadgeCredential, AchievementCredential, EndorsementCredential),
|
||||
List.of(
|
||||
JSONLD_CONTEXT_W3C_CREDENTIALS_V2,
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"))
|
||||
.put(
|
||||
Set.of(ClrCredential),
|
||||
List.of(
|
||||
JSONLD_CONTEXT_W3C_CREDENTIALS_V2,
|
||||
"https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"))
|
||||
.build();
|
||||
|
||||
private static final Map<String, List<String>> contextAliasesMap =
|
||||
new ImmutableMap.Builder<String, List<String>>()
|
||||
.put(
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
|
||||
List.of(
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context/ob_v3p0.jsonld",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json"))
|
||||
.put(
|
||||
"https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json",
|
||||
List.of("https://purl.imsglobal.org/spec/clr/v2p0/context.json"))
|
||||
.put(
|
||||
JSONLD_CONTEXT_W3C_CREDENTIALS_V2,
|
||||
List.of("https://www.w3.org/2018/credentials/v1"))
|
||||
.build();
|
||||
|
||||
private static final Map<String, List<String>> contextVersioningPatternMap =
|
||||
new ImmutableMap.Builder<String, List<String>>()
|
||||
.put(
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
|
||||
List.of(
|
||||
"https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/ob\\/v3p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json"))
|
||||
.put(
|
||||
"https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json",
|
||||
List.of(
|
||||
"https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/clr\\/v2p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json"))
|
||||
.build();
|
||||
|
||||
public enum Type implements CredentialEnum {
|
||||
AchievementCredential(Collections.emptyList()),
|
||||
OpenBadgeCredential(
|
||||
List.of(
|
||||
"OpenBadgeCredential",
|
||||
"AchievementCredential")), // treated as an alias of AchievementCredential
|
||||
ClrCredential(List.of("ClrCredential")),
|
||||
EndorsementCredential(List.of("EndorsementCredential")),
|
||||
VerifiablePresentation(Collections.emptyList()),
|
||||
VerifiableCredential(
|
||||
List.of("VerifiableCredential")), // this is an underspecifier in our context
|
||||
Unknown(Collections.emptyList());
|
||||
|
||||
private final List<String> allowedTypeValues;
|
||||
|
||||
Type(List<String> allowedTypeValues) {
|
||||
this.allowedTypeValues = allowedTypeValues;
|
||||
}
|
||||
|
||||
public CredentialEnum getCredentialType() {
|
||||
return credentialType;
|
||||
}
|
||||
|
||||
public ProofType getProofType() {
|
||||
return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL;
|
||||
}
|
||||
|
||||
private static final Map<CredentialEnum, SchemaKey> schemas = new ImmutableMap.Builder<CredentialEnum, SchemaKey>()
|
||||
.put(AchievementCredential, Catalog.OB_30_ACHIEVEMENTCREDENTIAL_JSON)
|
||||
.put(ClrCredential, Catalog.CLR_20_CLRCREDENTIAL_JSON)
|
||||
.put(VerifiablePresentation, Catalog.CLR_20_CLRCREDENTIAL_JSON)
|
||||
.put(EndorsementCredential, Catalog.OB_30_ENDORSEMENTCREDENTIAL_JSON)
|
||||
.build();
|
||||
|
||||
private static final Map<Set<VerifiableCredential.Type>, List<String>> contextMap = new ImmutableMap.Builder<Set<VerifiableCredential.Type>, List<String>>()
|
||||
.put(Set.of(Type.OpenBadgeCredential, AchievementCredential, EndorsementCredential),
|
||||
List.of("https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json"))
|
||||
.put(Set.of(ClrCredential),
|
||||
List.of("https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/clr/v2p0/context.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json"))
|
||||
|
||||
.build();
|
||||
|
||||
private static final Map<String, List<String>> contextAliasesMap = new ImmutableMap.Builder<String, List<String>>()
|
||||
.put("https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
List.of("https://purl.imsglobal.org/spec/ob/v3p0/context/ob_v3p0.jsonld"))
|
||||
.build();
|
||||
|
||||
private static final Map<String, List<String>> contextVersioningPatternMap = new ImmutableMap.Builder<String, List<String>>()
|
||||
.put("https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
List.of("https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/ob\\/v3p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json"))
|
||||
.put("https://purl.imsglobal.org/spec/clr/v2p0/context.json",
|
||||
List.of("https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/clr\\/v2p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json"))
|
||||
.build();
|
||||
|
||||
public enum Type implements CredentialEnum {
|
||||
AchievementCredential(Collections.emptyList()),
|
||||
OpenBadgeCredential(List.of("OpenBadgeCredential", "AchievementCredential")), //treated as an alias of AchievementCredential
|
||||
ClrCredential(List.of("ClrCredential")),
|
||||
EndorsementCredential(List.of("EndorsementCredential")),
|
||||
VerifiablePresentation(Collections.emptyList()),
|
||||
VerifiableCredential(List.of("VerifiableCredential")), //this is an underspecifier in our context
|
||||
Unknown(Collections.emptyList());
|
||||
|
||||
private final List<String> allowedTypeValues;
|
||||
|
||||
Type(List<String> allowedTypeValues) {
|
||||
this.allowedTypeValues = allowedTypeValues;
|
||||
}
|
||||
|
||||
public static VerifiableCredential.Type valueOf (JsonNode typeNode) {
|
||||
if(typeNode != null) {
|
||||
List<String> values = JsonNodeUtil.asStringList(typeNode);
|
||||
for (String value : values) {
|
||||
if(value.equals("AchievementCredential") || value.equals("OpenBadgeCredential")) {
|
||||
return AchievementCredential;
|
||||
} else if(value.equals("ClrCredential")) {
|
||||
return ClrCredential;
|
||||
} else if(value.equals("VerifiablePresentation")) {
|
||||
return VerifiablePresentation;
|
||||
} else if(value.equals("EndorsementCredential")) {
|
||||
return EndorsementCredential;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredTypeValues() {
|
||||
return List.of("VerifiableCredential");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllowedTypeValues() {
|
||||
return allowedTypeValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedTypeValuesRequired() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public List<String> getContextUris() {
|
||||
return contextMap.get(contextMap.keySet()
|
||||
.stream()
|
||||
.filter(s->s.contains(this))
|
||||
.findFirst()
|
||||
.orElseThrow(()-> new IllegalArgumentException(this.name() + " not recognized")));
|
||||
}
|
||||
@Override
|
||||
public Map<String, List<String>> getContextAliases() {
|
||||
return contextAliasesMap;
|
||||
}
|
||||
@Override
|
||||
public Map<String, List<String>> getContextVersionPatterns() {
|
||||
return contextVersioningPatternMap;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ProofType {
|
||||
EXTERNAL,
|
||||
EMBEDDED
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("super", super.toString())
|
||||
.add("credentialType", credentialType)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static class Builder extends Credential.Builder<VerifiableCredential> {
|
||||
@Override
|
||||
public VerifiableCredential build() {
|
||||
return new VerifiableCredential(getResource(), getJsonData(), getJwt(), schemas, ISSUED_ON_PROPERTY_NAME, EXPIRES_AT_PROPERTY_NAME);
|
||||
public static VerifiableCredential.Type valueOf(JsonNode typeNode) {
|
||||
if (typeNode != null) {
|
||||
List<String> values = JsonNodeUtil.asStringList(typeNode);
|
||||
for (String value : values) {
|
||||
if (value.equals("AchievementCredential") || value.equals("OpenBadgeCredential")) {
|
||||
return AchievementCredential;
|
||||
} else if (value.equals("ClrCredential")) {
|
||||
return ClrCredential;
|
||||
} else if (value.equals("VerifiablePresentation")) {
|
||||
return VerifiablePresentation;
|
||||
} else if (value.equals("EndorsementCredential")) {
|
||||
return EndorsementCredential;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
public static final String ID = VerifiableCredential.class.getCanonicalName();
|
||||
private static final String ISSUED_ON_PROPERTY_NAME = "issuanceDate";
|
||||
private static final String EXPIRES_AT_PROPERTY_NAME = "expirationDate";
|
||||
public static final String JWT_NODE_NAME = "vc";
|
||||
public static final List<MimeType> REFRESH_SERVICE_MIME_TYPES = List.of(MimeType.JSON, MimeType.JSON_LD, MimeType.TEXT_PLAIN);
|
||||
@Override
|
||||
public List<String> getRequiredTypeValues() {
|
||||
return List.of("VerifiableCredential");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllowedTypeValues() {
|
||||
return allowedTypeValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAllowedTypeValuesRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getContextUris() {
|
||||
return contextMap.get(
|
||||
contextMap.keySet().stream()
|
||||
.filter(s -> s.contains(this))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException(this.name() + " not recognized")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getContextAliases() {
|
||||
return contextAliasesMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getContextVersionPatterns() {
|
||||
return contextVersioningPatternMap;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ProofType {
|
||||
EXTERNAL,
|
||||
EMBEDDED
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("super", super.toString())
|
||||
.add("credentialType", credentialType)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static enum VCVersion {
|
||||
VCDMv2p0(ISSUED_ON_PROPERTY_NAME_V20, EXPIRES_AT_PROPERTY_NAME_V20),
|
||||
VCDMv1p1(ISSUED_ON_PROPERTY_NAME_V11, EXPIRES_AT_PROPERTY_NAME_V11);
|
||||
|
||||
final String issuanceDateField;
|
||||
final String expirationDateField;
|
||||
|
||||
VCVersion(String issuanceDateField, String expirationDateField) {
|
||||
this.issuanceDateField = issuanceDateField;
|
||||
this.expirationDateField = expirationDateField;
|
||||
}
|
||||
|
||||
static VCVersion of(JsonNode context) {
|
||||
if (JsonNodeUtil.asNodeList(context)
|
||||
.stream()
|
||||
.anyMatch(node -> node.isTextual() && node.asText().equals(JSONLD_CONTEXT_W3C_CREDENTIALS_V2)) )
|
||||
return VCDMv2p0;
|
||||
|
||||
return VCDMv1p1;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder extends Credential.Builder<VerifiableCredential> {
|
||||
@Override
|
||||
public VerifiableCredential build() {
|
||||
VCVersion version = VCVersion.of(getJsonData().get("@context"));
|
||||
|
||||
return new VerifiableCredential(
|
||||
getResource(),
|
||||
getJsonData(),
|
||||
getJwt(),
|
||||
schemas,
|
||||
version);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String ID = VerifiableCredential.class.getCanonicalName();
|
||||
private static final String ISSUED_ON_PROPERTY_NAME_V11 = "issuanceDate";
|
||||
private static final String ISSUED_ON_PROPERTY_NAME_V20 = "validFrom";
|
||||
private static final String EXPIRES_AT_PROPERTY_NAME_V11 = "expirationDate";
|
||||
private static final String EXPIRES_AT_PROPERTY_NAME_V20 = "validUntil";
|
||||
public static final String JWT_NODE_NAME = "vc";
|
||||
public static final List<MimeType> REFRESH_SERVICE_MIME_TYPES =
|
||||
List.of(MimeType.JSON, MimeType.JSON_LD, MimeType.TEXT_PLAIN);
|
||||
}
|
||||
|
@ -1,23 +1,33 @@
|
||||
package org.oneedtech.inspect.vc;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
|
||||
import org.oneedtech.inspect.vc.jsonld.JsonLDObjectUtils;
|
||||
import org.oneedtech.inspect.vc.util.CachingDocumentLoader;
|
||||
|
||||
import com.danubetech.verifiablecredentials.VerifiableCredential;
|
||||
|
||||
import info.weboftrust.ldsignatures.LdProof;
|
||||
|
||||
/**
|
||||
* Holder for W3C's Verifiable Credential
|
||||
*/
|
||||
public class W3CVCHolder {
|
||||
private VerifiableCredential credential;
|
||||
private com.danubetech.verifiablecredentials.VerifiableCredential credential;
|
||||
|
||||
public W3CVCHolder(VerifiableCredential credential) {
|
||||
this.credential = credential;
|
||||
credential.setDocumentLoader(new CachingDocumentLoader());
|
||||
switch (credential.version) {
|
||||
case VCDMv1p1:
|
||||
this.credential = com.danubetech.verifiablecredentials.VerifiableCredential
|
||||
.fromJson(new StringReader(credential.getJson().toString()));
|
||||
break;
|
||||
case VCDMv2p0:
|
||||
this.credential = W3CVerifiableCredentialDM2
|
||||
.fromJson(new StringReader(credential.getJson().toString()));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported version: " + credential.version);
|
||||
}
|
||||
this.credential.setDocumentLoader(new CachingDocumentLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,7 +40,7 @@ public class W3CVCHolder {
|
||||
return JsonLDObjectUtils.getListFromJsonLDObject(LdProof.class, credential);
|
||||
}
|
||||
|
||||
public VerifiableCredential getCredential() {
|
||||
public com.danubetech.verifiablecredentials.VerifiableCredential getCredential() {
|
||||
return credential;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package org.oneedtech.inspect.vc;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
|
||||
import foundation.identity.jsonld.JsonLDUtils;
|
||||
|
||||
public class W3CVerifiableCredentialDM2 extends com.danubetech.verifiablecredentials.VerifiableCredential {
|
||||
public static final URI[] DEFAULT_JSONLD_CONTEXTS = { URI.create(VerifiableCredential.JSONLD_CONTEXT_W3C_CREDENTIALS_V2) };
|
||||
|
||||
public Date getValidFrom() {
|
||||
return JsonLDUtils.stringToDate(JsonLDUtils.jsonLdGetString(this.getJsonObject(), JSONLD_TERM_VALIDFROM));
|
||||
}
|
||||
|
||||
public Date getValidUntil() {
|
||||
return JsonLDUtils.stringToDate(JsonLDUtils.jsonLdGetString(this.getJsonObject(), JSONLD_TERM_VALIDUNTIL));
|
||||
}
|
||||
|
||||
private static final String JSONLD_TERM_VALIDFROM = "validFrom";
|
||||
private static final String JSONLD_TERM_VALIDUNTIL = "validUntil";
|
||||
|
||||
}
|
@ -2,6 +2,7 @@ package org.oneedtech.inspect.vc.probe;
|
||||
|
||||
import static org.oneedtech.inspect.util.code.Defensives.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.oneedtech.inspect.core.probe.RunContext;
|
||||
@ -35,12 +36,20 @@ public class ContextPropertyProbe extends StringValuePropertyProbe {
|
||||
checkNotNull(contextUris);
|
||||
|
||||
int pos = 0;
|
||||
List<ReportItems> warnings = new ArrayList<>();
|
||||
for (String uri : contextUris) {
|
||||
if ((nodeValues.size() < pos + 1) || !contains(uri, nodeValues.get(pos))) {
|
||||
return error("missing required @context uri " + uri + " at position " + (pos + 1), ctx);
|
||||
}
|
||||
if (!nodeValues.get(pos).equals(uri)) {
|
||||
warnings.add(warning("expected @context uri " + uri + " at position " + (pos + 1) + ", gotten " + nodeValues.get(pos).toString() + " instead", ctx));
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
if (!warnings.isEmpty()) {
|
||||
return new ReportItems(warnings);
|
||||
}
|
||||
}
|
||||
|
||||
return success(ctx);
|
||||
|
@ -1,34 +1,30 @@
|
||||
package org.oneedtech.inspect.vc.probe;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.oneedtech.inspect.core.probe.Probe;
|
||||
import org.oneedtech.inspect.core.probe.RunContext;
|
||||
import org.oneedtech.inspect.core.report.ReportItems;
|
||||
import org.oneedtech.inspect.vc.VerifiableCredential;
|
||||
import org.oneedtech.inspect.vc.W3CVCHolder;
|
||||
import org.oneedtech.inspect.vc.verification.Ed25519Signature2022LdVerifier;
|
||||
|
||||
import com.apicatalog.jsonld.StringUtils;
|
||||
import com.apicatalog.jsonld.document.Document;
|
||||
import com.apicatalog.jsonld.loader.DocumentLoaderOptions;
|
||||
import com.apicatalog.multibase.Multibase;
|
||||
import com.apicatalog.multicodec.Multicodec;
|
||||
import com.apicatalog.multicodec.Multicodec.Codec;
|
||||
|
||||
import info.weboftrust.ldsignatures.LdProof;
|
||||
import info.weboftrust.ldsignatures.verifier.Ed25519Signature2020LdVerifier;
|
||||
import info.weboftrust.ldsignatures.verifier.LdVerifier;
|
||||
import jakarta.json.JsonArray;
|
||||
import jakarta.json.JsonObject;
|
||||
import jakarta.json.JsonString;
|
||||
import jakarta.json.JsonStructure;
|
||||
import jakarta.json.JsonValue;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.oneedtech.inspect.core.probe.Probe;
|
||||
import org.oneedtech.inspect.core.probe.RunContext;
|
||||
import org.oneedtech.inspect.core.report.ReportItems;
|
||||
import org.oneedtech.inspect.vc.VerifiableCredential;
|
||||
import org.oneedtech.inspect.vc.W3CVCHolder;
|
||||
import org.oneedtech.inspect.vc.verification.Ed25519Signature2022LdVerifier;
|
||||
import org.oneedtech.inspect.vc.verification.Ed25519Signature2022VCDM20LdVerifier;
|
||||
|
||||
/**
|
||||
* A Probe that verifies a credential's embedded proof.
|
||||
@ -37,244 +33,275 @@ import jakarta.json.JsonValue;
|
||||
*/
|
||||
public class EmbeddedProofProbe extends Probe<VerifiableCredential> {
|
||||
|
||||
private final static List<String> ALLOWED_CRYPTOSUITES = List.of("eddsa-2022", "eddsa-rdfc-2022");
|
||||
private static final List<String> ALLOWED_CRYPTOSUITES = List.of("eddsa-2022", "eddsa-rdfc-2022");
|
||||
|
||||
public EmbeddedProofProbe() {
|
||||
super(ID);
|
||||
}
|
||||
public EmbeddedProofProbe() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Using verifiable-credentials-java from Danubetech
|
||||
* (https://github.com/danubetech/verifiable-credentials-java)
|
||||
*/
|
||||
@Override
|
||||
public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception {
|
||||
/*
|
||||
* Using verifiable-credentials-java from Danubetech
|
||||
* (https://github.com/danubetech/verifiable-credentials-java)
|
||||
*/
|
||||
@Override
|
||||
public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception {
|
||||
|
||||
W3CVCHolder credentialHolder = new W3CVCHolder(com.danubetech.verifiablecredentials.VerifiableCredential
|
||||
.fromJson(new StringReader(crd.getJson().toString())));
|
||||
W3CVCHolder credentialHolder = new W3CVCHolder(crd);
|
||||
|
||||
List<LdProof> proofs = credentialHolder.getProofs();
|
||||
if (proofs == null || proofs.size() == 0) {
|
||||
return error("The verifiable credential is missing a proof.", ctx);
|
||||
}
|
||||
List<LdProof> proofs = credentialHolder.getProofs();
|
||||
if (proofs == null || proofs.size() == 0) {
|
||||
return error("The verifiable credential is missing a proof.", ctx);
|
||||
}
|
||||
|
||||
// get proof of standard type and purpose
|
||||
Optional<LdProof> selectedProof = proofs.stream()
|
||||
.filter(proof -> proof.getProofPurpose().equals("assertionMethod"))
|
||||
.filter(proof -> proof.isType("Ed25519Signature2020") ||
|
||||
(proof.isType("DataIntegrityProof") && proof.getJsonObject().containsKey("cryptosuite") && ALLOWED_CRYPTOSUITES.contains(proof.getJsonObject().get("cryptosuite"))))
|
||||
.findFirst();
|
||||
// get proof of standard type and purpose
|
||||
Optional<LdProof> selectedProof =
|
||||
proofs.stream()
|
||||
.filter(proof -> proof.getProofPurpose().equals("assertionMethod"))
|
||||
.filter(
|
||||
proof ->
|
||||
proof.isType("Ed25519Signature2020")
|
||||
|| (proof.isType("DataIntegrityProof")
|
||||
&& proof.getJsonObject().containsKey("cryptosuite")
|
||||
&& ALLOWED_CRYPTOSUITES.contains(
|
||||
proof.getJsonObject().get("cryptosuite"))))
|
||||
.findFirst();
|
||||
|
||||
if (!selectedProof.isPresent()) {
|
||||
return error("No proof with type any of (\"Ed25519Signature2020\", \"DataIntegrityProof\" with cryptosuite attr of \"eddsa-rdfc-2022\" or \"eddsa-2022\") or proof purpose \"assertionMethod\" found", ctx);
|
||||
}
|
||||
if (!selectedProof.isPresent()) {
|
||||
return error(
|
||||
"No proof with type any of (\"Ed25519Signature2020\", \"DataIntegrityProof\" with"
|
||||
+ " cryptosuite attr of \"eddsa-rdfc-2022\" or \"eddsa-2022\") or proof purpose"
|
||||
+ " \"assertionMethod\" found",
|
||||
ctx);
|
||||
}
|
||||
|
||||
LdProof proof = selectedProof.get();
|
||||
LdProof proof = selectedProof.get();
|
||||
|
||||
URI method = proof.getVerificationMethod();
|
||||
URI method = proof.getVerificationMethod();
|
||||
|
||||
// The verification method must dereference to an Ed25519VerificationKey2020.
|
||||
// Danubetech's Ed25519Signature2020LdVerifier expects the decoded public key
|
||||
// from the Ed25519VerificationKey2020 (32 bytes).
|
||||
//
|
||||
// Formats accepted:
|
||||
//
|
||||
// [controller]#[publicKeyMultibase]
|
||||
// did:key:[publicKeyMultibase]
|
||||
// did:web:[url-encoded domain-name][:path]*
|
||||
// http/s://[location of a Ed25519VerificationKey2020 document]
|
||||
// http/s://[location of a controller document with a 'verificationMethod' with
|
||||
// a Ed25519VerificationKey2020]
|
||||
// The verification method must dereference to an Ed25519VerificationKey2020.
|
||||
// Danubetech's Ed25519Signature2020LdVerifier expects the decoded public key
|
||||
// from the Ed25519VerificationKey2020 (32 bytes).
|
||||
//
|
||||
// Formats accepted:
|
||||
//
|
||||
// [controller]#[publicKeyMultibase]
|
||||
// did:key:[publicKeyMultibase]
|
||||
// did:web:[url-encoded domain-name][:path]*
|
||||
// http/s://[location of a Ed25519VerificationKey2020 document]
|
||||
// http/s://[location of a controller document with a 'verificationMethod' with
|
||||
// a Ed25519VerificationKey2020]
|
||||
|
||||
String publicKeyMultibase;
|
||||
String controller = null;
|
||||
String publicKeyMultibase;
|
||||
String controller = null;
|
||||
|
||||
publicKeyMultibase = method.toString();
|
||||
publicKeyMultibase = method.toString();
|
||||
|
||||
if (method.getFragment() != null && IsValidPublicKeyMultibase(method.getFragment())) {
|
||||
publicKeyMultibase = method.getFragment();
|
||||
controller = method.toString().substring(0, method.toString().indexOf("#"));
|
||||
} else {
|
||||
if (StringUtils.isBlank(method.getScheme())) {
|
||||
return error("The verification method must be a valid URI (missing scheme)", ctx);
|
||||
} else if (method.getScheme().equals("did")) {
|
||||
if (method.getSchemeSpecificPart().startsWith("key:")) {
|
||||
publicKeyMultibase = method.getSchemeSpecificPart().substring("key:".length());
|
||||
} else if (method.getSchemeSpecificPart().startsWith("web:")) {
|
||||
String methodSpecificId = method.getRawSchemeSpecificPart().substring("web:".length());
|
||||
if (method.getFragment() != null && IsValidPublicKeyMultibase(method.getFragment())) {
|
||||
publicKeyMultibase = method.getFragment();
|
||||
controller = method.toString().substring(0, method.toString().indexOf("#"));
|
||||
} else {
|
||||
if (StringUtils.isBlank(method.getScheme())) {
|
||||
return error("The verification method must be a valid URI (missing scheme)", ctx);
|
||||
} else if (method.getScheme().equals("did")) {
|
||||
if (method.getSchemeSpecificPart().startsWith("key:")) {
|
||||
publicKeyMultibase = method.getSchemeSpecificPart().substring("key:".length());
|
||||
} else if (method.getSchemeSpecificPart().startsWith("web:")) {
|
||||
String methodSpecificId = method.getRawSchemeSpecificPart().substring("web:".length());
|
||||
|
||||
// read algorithm at https://w3c-ccg.github.io/did-method-web/#read-resolve.
|
||||
// Steps in comments
|
||||
// read algorithm at https://w3c-ccg.github.io/did-method-web/#read-resolve.
|
||||
// Steps in comments
|
||||
|
||||
// 1. Replace ":" with "/" in the method specific identifier to obtain the fully
|
||||
// qualified domain name and optional path.
|
||||
methodSpecificId = methodSpecificId.replaceAll(":", "/");
|
||||
// 1. Replace ":" with "/" in the method specific identifier to obtain the fully
|
||||
// qualified domain name and optional path.
|
||||
methodSpecificId = methodSpecificId.replaceAll(":", "/");
|
||||
|
||||
// 2. If the domain contains a port percent decode the colon.
|
||||
String portPercentEncoded = URLEncoder.encode(":", Charset.forName("UTF-8"));
|
||||
int index = methodSpecificId.indexOf(portPercentEncoded);
|
||||
if (index >= 0 && index < methodSpecificId.indexOf("/")) {
|
||||
methodSpecificId = methodSpecificId.replace(portPercentEncoded, ":");
|
||||
}
|
||||
// 2. If the domain contains a port percent decode the colon.
|
||||
String portPercentEncoded = URLEncoder.encode(":", Charset.forName("UTF-8"));
|
||||
int index = methodSpecificId.indexOf(portPercentEncoded);
|
||||
if (index >= 0 && index < methodSpecificId.indexOf("/")) {
|
||||
methodSpecificId = methodSpecificId.replace(portPercentEncoded, ":");
|
||||
}
|
||||
|
||||
// 3. Generate an HTTPS URL to the expected location of the DID document by
|
||||
// prepending https://.
|
||||
URI uri = new URI("https://" + methodSpecificId);
|
||||
// 3. Generate an HTTPS URL to the expected location of the DID document by
|
||||
// prepending https://.
|
||||
URI uri = new URI("https://" + methodSpecificId);
|
||||
|
||||
// 4. If no path has been specified in the URL, append /.well-known.
|
||||
if (uri.getPath() == null) {
|
||||
uri = uri.resolve("/well-known");
|
||||
}
|
||||
// 4. If no path has been specified in the URL, append /.well-known.
|
||||
if (uri.getPath() == null) {
|
||||
uri = uri.resolve("/well-known");
|
||||
}
|
||||
|
||||
// 5. Append /did.json to complete the URL.
|
||||
uri = uri.resolve(uri.getPath() + "/did.json");
|
||||
// 5. Append /did.json to complete the URL.
|
||||
uri = uri.resolve(uri.getPath() + "/did.json");
|
||||
|
||||
// 6. Perform an HTTP GET request to the URL using an agent that can
|
||||
// successfully negotiate a secure HTTPS connection, which enforces the security
|
||||
// requirements as described in 2.6 Security and privacy considerations.
|
||||
// 7. When performing the DNS resolution during the HTTP GET request, the client
|
||||
// SHOULD utilize [RFC8484] in order to prevent tracking of the identity being
|
||||
// resolved.
|
||||
Optional<JsonStructure> keyStructure;
|
||||
try {
|
||||
Document keyDocument = credentialHolder.getCredential().getDocumentLoader().loadDocument(uri,
|
||||
new DocumentLoaderOptions());
|
||||
keyStructure = keyDocument.getJsonContent();
|
||||
} catch (Exception e) {
|
||||
return error("Key document not found at " + method + ". URI: " + uri
|
||||
+ " doesn't return a valid document. Reason: " + e.getMessage() + " ", ctx);
|
||||
}
|
||||
if (keyStructure.isEmpty()) {
|
||||
return error("Key document not found at " + method + ". URI: " + uri
|
||||
+ " doesn't return a valid document. Reason: The document is empty.", ctx);
|
||||
}
|
||||
// 6. Perform an HTTP GET request to the URL using an agent that can
|
||||
// successfully negotiate a secure HTTPS connection, which enforces the security
|
||||
// requirements as described in 2.6 Security and privacy considerations.
|
||||
// 7. When performing the DNS resolution during the HTTP GET request, the client
|
||||
// SHOULD utilize [RFC8484] in order to prevent tracking of the identity being
|
||||
// resolved.
|
||||
Optional<JsonStructure> keyStructure;
|
||||
try {
|
||||
Document keyDocument =
|
||||
credentialHolder
|
||||
.getCredential()
|
||||
.getDocumentLoader()
|
||||
.loadDocument(uri, new DocumentLoaderOptions());
|
||||
keyStructure = keyDocument.getJsonContent();
|
||||
} catch (Exception e) {
|
||||
return error(
|
||||
"Key document not found at "
|
||||
+ method
|
||||
+ ". URI: "
|
||||
+ uri
|
||||
+ " doesn't return a valid document. Reason: "
|
||||
+ e.getMessage()
|
||||
+ " ",
|
||||
ctx);
|
||||
}
|
||||
if (keyStructure.isEmpty()) {
|
||||
return error(
|
||||
"Key document not found at "
|
||||
+ method
|
||||
+ ". URI: "
|
||||
+ uri
|
||||
+ " doesn't return a valid document. Reason: The document is empty.",
|
||||
ctx);
|
||||
}
|
||||
|
||||
// check did in "assertionMethod"
|
||||
JsonArray assertionMethod = keyStructure.get().asJsonObject()
|
||||
.getJsonArray("assertionMethod");
|
||||
if (assertionMethod == null) {
|
||||
return error("Document doesn't have a list of assertion methods at URI: " + uri, ctx);
|
||||
} else {
|
||||
Boolean anyMatch = false;
|
||||
for(int i = 0; i < assertionMethod.size(); i++) {
|
||||
String assertionMethodValue = assertionMethod.getString(i);
|
||||
if (assertionMethodValue.equals(method.toString())) {
|
||||
anyMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!anyMatch) {
|
||||
return error("Assertion method " + method + " not found in DID document.", ctx);
|
||||
}
|
||||
}
|
||||
// check did in "assertionMethod"
|
||||
JsonArray assertionMethod =
|
||||
keyStructure.get().asJsonObject().getJsonArray("assertionMethod");
|
||||
if (assertionMethod == null) {
|
||||
return error("Document doesn't have a list of assertion methods at URI: " + uri, ctx);
|
||||
} else {
|
||||
Boolean anyMatch = false;
|
||||
for (int i = 0; i < assertionMethod.size(); i++) {
|
||||
String assertionMethodValue = assertionMethod.getString(i);
|
||||
if (assertionMethodValue.equals(method.toString())) {
|
||||
anyMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!anyMatch) {
|
||||
return error("Assertion method " + method + " not found in DID document.", ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// get keys from "verificationMethod"
|
||||
JsonArray keyVerificationMethod = keyStructure.get().asJsonObject()
|
||||
.getJsonArray("verificationMethod");
|
||||
if (keyVerificationMethod == null) {
|
||||
return error("Document doesn't have a list of verification methods at URI: " + uri, ctx);
|
||||
}
|
||||
Optional<JsonValue> verificationMethodMaybe = keyVerificationMethod.stream()
|
||||
.filter(n -> n.asJsonObject().getString("id").equals(method.toString()))
|
||||
.findFirst();
|
||||
if (verificationMethodMaybe.isEmpty()) {
|
||||
return error("Verification method " + method + " not found in DID document.", ctx);
|
||||
}
|
||||
JsonObject verificationMethod = verificationMethodMaybe.get().asJsonObject();
|
||||
// assuming a Ed25519VerificationKey2020 document
|
||||
controller = verificationMethod.getString("controller");
|
||||
publicKeyMultibase = verificationMethod.getString("publicKeyMultibase");
|
||||
// get keys from "verificationMethod"
|
||||
JsonArray keyVerificationMethod =
|
||||
keyStructure.get().asJsonObject().getJsonArray("verificationMethod");
|
||||
if (keyVerificationMethod == null) {
|
||||
return error(
|
||||
"Document doesn't have a list of verification methods at URI: " + uri, ctx);
|
||||
}
|
||||
Optional<JsonValue> verificationMethodMaybe =
|
||||
keyVerificationMethod.stream()
|
||||
.filter(n -> n.asJsonObject().getString("id").equals(method.toString()))
|
||||
.findFirst();
|
||||
if (verificationMethodMaybe.isEmpty()) {
|
||||
return error("Verification method " + method + " not found in DID document.", ctx);
|
||||
}
|
||||
JsonObject verificationMethod = verificationMethodMaybe.get().asJsonObject();
|
||||
// assuming a Ed25519VerificationKey2020 document
|
||||
controller = verificationMethod.getString("controller");
|
||||
publicKeyMultibase = verificationMethod.getString("publicKeyMultibase");
|
||||
|
||||
} else {
|
||||
return error("Unknown verification method: " + method, ctx);
|
||||
}
|
||||
} else if (method.getScheme().equals("http") || method.getScheme().equals("https")) {
|
||||
try {
|
||||
Document keyDocument = credentialHolder.getCredential().getDocumentLoader().loadDocument(method,
|
||||
new DocumentLoaderOptions());
|
||||
Optional<JsonStructure> keyStructure = keyDocument.getJsonContent();
|
||||
if (keyStructure.isEmpty()) {
|
||||
return error("Key document not found at " + method, ctx);
|
||||
}
|
||||
} else {
|
||||
return error("Unknown verification method: " + method, ctx);
|
||||
}
|
||||
} else if (method.getScheme().equals("http") || method.getScheme().equals("https")) {
|
||||
try {
|
||||
Document keyDocument =
|
||||
credentialHolder
|
||||
.getCredential()
|
||||
.getDocumentLoader()
|
||||
.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 Ed25519VerificationKey2020 document
|
||||
controller = keyStructure.get().asJsonObject().getString("controller");
|
||||
if (StringUtils.isBlank(controller)) {
|
||||
// Then look for a controller document (e.g. DID Document) with a
|
||||
// 'verificationMethod'
|
||||
// that is a Ed25519VerificationKey2020 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");
|
||||
}
|
||||
// First look for a Ed25519VerificationKey2020 document
|
||||
controller = keyStructure.get().asJsonObject().getString("controller");
|
||||
if (StringUtils.isBlank(controller)) {
|
||||
// Then look for a controller document (e.g. DID Document) with a
|
||||
// 'verificationMethod'
|
||||
// that is a Ed25519VerificationKey2020 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");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return error("Invalid verification key URL: " + e.getMessage(), ctx);
|
||||
}
|
||||
} else {
|
||||
return error("Unknown verification method scheme: " + method.getScheme(), ctx);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return error("Invalid verification key URL: " + e.getMessage(), ctx);
|
||||
}
|
||||
} else {
|
||||
return error("Unknown verification method scheme: " + method.getScheme(), ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the Multibase to Multicodec and check that it is an Ed25519 public key
|
||||
// https://w3c-ccg.github.io/di-eddsa-2020/#ed25519verificationkey2020
|
||||
byte[] publicKeyMulticodec;
|
||||
try {
|
||||
publicKeyMulticodec = Multibase.decode(publicKeyMultibase);
|
||||
if (publicKeyMulticodec[0] != (byte) 0xed || publicKeyMulticodec[1] != (byte) 0x01) {
|
||||
return error("Verification method does not contain an Ed25519 public key", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return error("Invalid public key: " + e.getMessage(), ctx);
|
||||
}
|
||||
// Decode the Multibase to Multicodec and check that it is an Ed25519 public key
|
||||
// https://w3c-ccg.github.io/di-eddsa-2020/#ed25519verificationkey2020
|
||||
byte[] publicKeyMulticodec;
|
||||
try {
|
||||
publicKeyMulticodec = Multibase.decode(publicKeyMultibase);
|
||||
if (publicKeyMulticodec[0] != (byte) 0xed || publicKeyMulticodec[1] != (byte) 0x01) {
|
||||
return error("Verification method does not contain an Ed25519 public key", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return error("Invalid public key: " + e.getMessage(), ctx);
|
||||
}
|
||||
|
||||
if (controller != null) {
|
||||
if (!controller.equals(credentialHolder.getCredential().getIssuer().toString())) {
|
||||
return error("Key controller does not match issuer: " + credentialHolder.getCredential().getIssuer(),
|
||||
ctx);
|
||||
}
|
||||
}
|
||||
if (controller != null && credentialHolder.getCredential().getIssuer() != null) {
|
||||
if (!controller.equals(credentialHolder.getCredential().getIssuer().toString())) {
|
||||
return error(
|
||||
"Key controller does not match issuer: " + credentialHolder.getCredential().getIssuer(),
|
||||
ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the publicKey bytes from the Multicodec
|
||||
byte[] publicKey = Multicodec.decode(Codec.Ed25519PublicKey, publicKeyMulticodec);
|
||||
// Extract the publicKey bytes from the Multicodec
|
||||
byte[] publicKey = Multicodec.decode(Codec.Ed25519PublicKey, publicKeyMulticodec);
|
||||
|
||||
// choose verifier
|
||||
LdVerifier<?> verifier = getVerifier(proof, publicKey);
|
||||
// choose verifier
|
||||
LdVerifier<?> verifier = getVerifier(proof, publicKey, crd);
|
||||
|
||||
try {
|
||||
boolean verify = verifier.verify(credentialHolder.getCredential(), proof);
|
||||
if (!verify) {
|
||||
return error("Embedded proof verification failed.", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return fatal("Embedded proof verification failed: " + e.getMessage(), ctx);
|
||||
}
|
||||
try {
|
||||
boolean verify = verifier.verify(credentialHolder.getCredential(), proof);
|
||||
if (!verify) {
|
||||
return error("Embedded proof verification failed.", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return fatal("Embedded proof verification failed: " + e.getMessage(), ctx);
|
||||
}
|
||||
|
||||
return success(ctx);
|
||||
}
|
||||
return success(ctx);
|
||||
}
|
||||
|
||||
private LdVerifier<?> getVerifier(LdProof proof, byte[] publicKey) {
|
||||
return proof.isType("Ed25519Signature2020")
|
||||
? new Ed25519Signature2020LdVerifier(publicKey)
|
||||
: new Ed25519Signature2022LdVerifier(publicKey);
|
||||
}
|
||||
private LdVerifier<?> getVerifier(LdProof proof, byte[] publicKey, VerifiableCredential crd) {
|
||||
return proof.isType("Ed25519Signature2020")
|
||||
? new Ed25519Signature2020LdVerifier(publicKey)
|
||||
: crd.getVersion() == VerifiableCredential.VCVersion.VCDMv1p1
|
||||
? new Ed25519Signature2022LdVerifier(publicKey)
|
||||
: new Ed25519Signature2022VCDM20LdVerifier(publicKey);
|
||||
}
|
||||
|
||||
private Boolean IsValidPublicKeyMultibase(String publicKeyMultibase) {
|
||||
try {
|
||||
byte[] publicKeyMulticodec = Multibase.decode(publicKeyMultibase);
|
||||
byte[] publicKey = Multicodec.decode(Codec.Ed25519PublicKey, publicKeyMulticodec);
|
||||
return publicKey.length == 32;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
private Boolean IsValidPublicKeyMultibase(String publicKeyMultibase) {
|
||||
try {
|
||||
byte[] publicKeyMulticodec = Multibase.decode(publicKeyMultibase);
|
||||
byte[] publicKey = Multicodec.decode(Codec.Ed25519PublicKey, publicKeyMulticodec);
|
||||
return publicKey.length == 32;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final String ID = EmbeddedProofProbe.class.getSimpleName();
|
||||
public static final String ID = EmbeddedProofProbe.class.getSimpleName();
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class ExpirationProbe extends Probe<Credential> {
|
||||
@Override
|
||||
public ReportItems run(Credential crd, RunContext ctx) throws Exception {
|
||||
/*
|
||||
* If the AchievementCredential or EndorsementCredential has an “expirationDate” property
|
||||
* If the AchievementCredential or EndorsementCredential has an “expirationDate” or "validUntil" property
|
||||
* and the expiration date is prior to the current date, the credential has expired.
|
||||
*/
|
||||
JsonNode node = crd.getJson().get(crd.getExpiresAtPropertyName());
|
||||
@ -30,10 +30,10 @@ public class ExpirationProbe extends Probe<Credential> {
|
||||
try {
|
||||
ZonedDateTime expirationDate = ZonedDateTime.parse(node.textValue());
|
||||
if (ZonedDateTime.now().isAfter(expirationDate)) {
|
||||
return fatal("The credential has expired (expiration date was " + node.asText() + ").", ctx);
|
||||
return fatal("The credential has expired (expiration date or validUntil was " + node.asText() + ").", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return exception("Error while checking expirationDate: " + e.getMessage(), ctx.getResource());
|
||||
return exception("Error while checking expirationDate or validUntil: " + e.getMessage(), ctx.getResource());
|
||||
}
|
||||
}
|
||||
return success(ctx);
|
||||
|
@ -22,7 +22,7 @@ public class IssuanceProbe extends Probe<Credential> {
|
||||
@Override
|
||||
public ReportItems run(Credential crd, RunContext ctx) throws Exception {
|
||||
/*
|
||||
* If the AchievementCredential or EndorsementCredential “issuanceDate”
|
||||
* If the AchievementCredential or EndorsementCredential “issuanceDate” or "validFrom"
|
||||
* property after the current date, the credential is not yet valid.
|
||||
*/
|
||||
JsonNode node = crd.getJson().get(crd.getIssuedOnPropertyName());
|
||||
@ -30,10 +30,10 @@ public class IssuanceProbe extends Probe<Credential> {
|
||||
try {
|
||||
ZonedDateTime issuanceDate = ZonedDateTime.parse(node.textValue());
|
||||
if (issuanceDate.isAfter(ZonedDateTime.now())) {
|
||||
return fatal("The credential is not yet issued (issuance date is " + node.asText() + ").", ctx);
|
||||
return fatal("The credential is not yet issued or valid (issuance date or validFrom is " + node.asText() + ").", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return exception("Error while checking issuanceDate: " + e.getMessage(), ctx.getResource());
|
||||
return exception("Error while checking issuanceDate or ValidFrom: " + e.getMessage(), ctx.getResource());
|
||||
}
|
||||
}
|
||||
return success(ctx);
|
||||
|
@ -120,6 +120,7 @@ public class CachingDocumentLoader extends ConfigurableDocumentLoader {
|
||||
.put("https://w3id.org/security/suites/ed25519-2020/v1",Resources.getResource("contexts/security-suites-ed25519-2020-v1.jsonld"))
|
||||
.put("https://w3id.org/security/data-integrity/v1",Resources.getResource("contexts/data-integrity-v1.jsonld"))
|
||||
.put("https://www.w3.org/2018/credentials/v1", Resources.getResource("contexts/2018-credentials-v1.jsonld"))
|
||||
.put("https://www.w3.org/ns/credentials/v2", Resources.getResource("contexts/credentials-v2.jsonld"))
|
||||
.put("https://w3id.org/security/v1", Resources.getResource("contexts/security-v1.jsonld"))
|
||||
.put("https://w3id.org/security/v2", Resources.getResource("contexts/security-v2.jsonld"))
|
||||
.put("https://w3id.org/security/v3", Resources.getResource("contexts/security-v3-unstable.jsonld"))
|
||||
|
@ -13,7 +13,7 @@ public class Ed25519Signature2022LdVerifier extends LdVerifier<Ed25519Signature2
|
||||
|
||||
public Ed25519Signature2022LdVerifier(ByteVerifier verifier) {
|
||||
|
||||
super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer());
|
||||
super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer(Eddsa2022LdProof.builder()));
|
||||
}
|
||||
|
||||
public Ed25519Signature2022LdVerifier(byte[] publicKey) {
|
||||
|
@ -0,0 +1,53 @@
|
||||
package org.oneedtech.inspect.vc.verification;
|
||||
|
||||
import com.danubetech.keyformats.crypto.ByteVerifier;
|
||||
import com.danubetech.keyformats.crypto.impl.Ed25519_EdDSA_PublicKeyVerifier;
|
||||
import com.danubetech.keyformats.jose.JWSAlgorithm;
|
||||
import info.weboftrust.ldsignatures.LdProof;
|
||||
import info.weboftrust.ldsignatures.verifier.LdVerifier;
|
||||
import io.ipfs.multibase.Multibase;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
public class Ed25519Signature2022VCDM20LdVerifier extends LdVerifier<Ed25519Signature2022SignatureSuite> {
|
||||
|
||||
public Ed25519Signature2022VCDM20LdVerifier(ByteVerifier verifier) {
|
||||
|
||||
super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer(Eddsa2022v2LdProof.builder()));
|
||||
}
|
||||
|
||||
public Ed25519Signature2022VCDM20LdVerifier(byte[] publicKey) {
|
||||
|
||||
this(new Ed25519_EdDSA_PublicKeyVerifier(publicKey));
|
||||
}
|
||||
|
||||
public Ed25519Signature2022VCDM20LdVerifier() {
|
||||
|
||||
this((ByteVerifier) null);
|
||||
}
|
||||
|
||||
public static boolean verify(byte[] signingInput, LdProof ldProof, ByteVerifier verifier) throws GeneralSecurityException {
|
||||
|
||||
// verify
|
||||
|
||||
String proofValue = ldProof.getProofValue();
|
||||
if (proofValue == null) throw new GeneralSecurityException("No 'proofValue' in proof.");
|
||||
|
||||
boolean verify;
|
||||
|
||||
byte[] bytes = Multibase.decode(proofValue);
|
||||
verify = verifier.verify(signingInput, bytes, JWSAlgorithm.EdDSA);
|
||||
|
||||
// done
|
||||
|
||||
return verify;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(byte[] signingInput, LdProof ldProof) throws GeneralSecurityException {
|
||||
|
||||
return verify(signingInput, ldProof, this.getVerifier());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package org.oneedtech.inspect.vc.verification;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import com.apicatalog.jsonld.loader.DocumentLoader;
|
||||
|
||||
import foundation.identity.jsonld.JsonLDObject;
|
||||
import foundation.identity.jsonld.JsonLDUtils;
|
||||
import info.weboftrust.ldsignatures.LdProof;
|
||||
|
||||
public class Eddsa2022v2LdProof extends LdProof {
|
||||
public static final URI[] DEFAULT_JSONLD_CONTEXTS = { LDSecurityContexts.JSONLD_CONTEXT_W3ID_VC_V2 };
|
||||
public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = LDSecurityContexts.DOCUMENT_LOADER;
|
||||
|
||||
public static Builder<? extends Builder<?>> builder() {
|
||||
return new Builder(new Eddsa2022v2LdProof());
|
||||
}
|
||||
|
||||
/*
|
||||
* Factory methods
|
||||
*/
|
||||
|
||||
public static class Builder<B extends Builder<B>> extends LdProof.Builder<B> {
|
||||
|
||||
private boolean addCryptosuite = true;
|
||||
|
||||
public Builder(LdProof jsonLdObject) {
|
||||
super(jsonLdObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public B base(JsonLDObject base) {
|
||||
addCryptosuite = false;
|
||||
return super.base(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LdProof build() {
|
||||
super.build();
|
||||
|
||||
if (addCryptosuite) {
|
||||
JsonLDUtils.jsonLdAdd(this.jsonLdObject, "cryptosuite", "eddsa-rdfc-2022");
|
||||
}
|
||||
|
||||
return (LdProof) this.jsonLdObject;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import foundation.identity.jsonld.ConfigurableDocumentLoader;
|
||||
|
||||
public class LDSecurityContexts {
|
||||
public static final URI JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1 = URI.create("https://w3id.org/security/data-integrity/v1");
|
||||
public static final URI JSONLD_CONTEXT_W3ID_VC_V2 = URI.create("https://www.w3.org/ns/credentials/v2");
|
||||
|
||||
public static final Map<URI, JsonDocument> CONTEXTS;
|
||||
public static final DocumentLoader DOCUMENT_LOADER;
|
||||
@ -29,6 +30,8 @@ public class LDSecurityContexts {
|
||||
|
||||
CONTEXTS.put(JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1,
|
||||
JsonDocument.of(MediaType.JSON_LD, Resources.getResource("contexts/data-integrity-v1.jsonld").openStream()));
|
||||
CONTEXTS.put(JSONLD_CONTEXT_W3ID_VC_V2,
|
||||
JsonDocument.of(MediaType.JSON_LD, Resources.getResource("contexts/credentials-v2.jsonld").openStream()));
|
||||
|
||||
for (Map.Entry<URI, JsonDocument> context : CONTEXTS.entrySet()) {
|
||||
context.getValue().setDocumentUrl(context.getKey());
|
||||
|
@ -1,28 +1,29 @@
|
||||
package org.oneedtech.inspect.vc.verification;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.List;
|
||||
|
||||
import foundation.identity.jsonld.JsonLDException;
|
||||
import foundation.identity.jsonld.JsonLDObject;
|
||||
import info.weboftrust.ldsignatures.LdProof;
|
||||
import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer;
|
||||
import info.weboftrust.ldsignatures.util.SHAUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.List;
|
||||
|
||||
public class URDNA2015Canonicalizer extends Canonicalizer {
|
||||
|
||||
public URDNA2015Canonicalizer() {
|
||||
private LdProof.Builder<?> proofBuilder;
|
||||
|
||||
public URDNA2015Canonicalizer(LdProof.Builder<?> proofBuilder) {
|
||||
super(List.of("urdna2015"));
|
||||
this.proofBuilder = proofBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] canonicalize(LdProof ldProof, JsonLDObject jsonLdObject) throws IOException, GeneralSecurityException, JsonLDException {
|
||||
|
||||
// construct the LD proof without proof values
|
||||
|
||||
LdProof ldProofWithoutProofValues = Eddsa2022LdProof.builder()
|
||||
LdProof ldProofWithoutProofValues = proofBuilder
|
||||
.base(ldProof)
|
||||
.defaultContexts(true)
|
||||
.build();
|
||||
|
290
inspector-vc/src/main/resources/contexts/credentials-v2.jsonld
Normal file
290
inspector-vc/src/main/resources/contexts/credentials-v2.jsonld
Normal file
@ -0,0 +1,290 @@
|
||||
{
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"@vocab": "https://www.w3.org/ns/credentials/issuer-dependent#",
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"kid": {
|
||||
"@id": "https://www.iana.org/assignments/jose#kid",
|
||||
"@type": "@id"
|
||||
},
|
||||
"iss": {
|
||||
"@id": "https://www.iana.org/assignments/jose#iss",
|
||||
"@type": "@id"
|
||||
},
|
||||
"sub": {
|
||||
"@id": "https://www.iana.org/assignments/jose#sub",
|
||||
"@type": "@id"
|
||||
},
|
||||
"jku": {
|
||||
"@id": "https://www.iana.org/assignments/jose#jku",
|
||||
"@type": "@id"
|
||||
},
|
||||
"x5u": {
|
||||
"@id": "https://www.iana.org/assignments/jose#x5u",
|
||||
"@type": "@id"
|
||||
},
|
||||
"aud": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#aud",
|
||||
"@type": "@id"
|
||||
},
|
||||
"exp": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#exp",
|
||||
"@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger"
|
||||
},
|
||||
"nbf": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#nbf",
|
||||
"@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger"
|
||||
},
|
||||
"iat": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#iat",
|
||||
"@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger"
|
||||
},
|
||||
"cnf": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#cnf",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"kid": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#kid",
|
||||
"@type": "@id"
|
||||
},
|
||||
"jwk": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#jwk",
|
||||
"@type": "@json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_sd_alg": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#_sd_alg"
|
||||
},
|
||||
"_sd": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#_sd"
|
||||
},
|
||||
"...": {
|
||||
"@id": "https://www.iana.org/assignments/jwt#..."
|
||||
},
|
||||
"digestSRI": {
|
||||
"@id": "https://www.w3.org/2018/credentials#digestSRI",
|
||||
"@type": "https://www.w3.org/2018/credentials#sriString"
|
||||
},
|
||||
"digestMultibase": {
|
||||
"@id": "https://w3id.org/security#digestMultibase",
|
||||
"@type": "https://w3id.org/security#multibase"
|
||||
},
|
||||
"mediaType": {
|
||||
"@id": "https://schema.org/encodingFormat"
|
||||
},
|
||||
"description": "https://schema.org/description",
|
||||
"name": "https://schema.org/name",
|
||||
"EnvelopedVerifiableCredential": "https://www.w3.org/2018/credentials#EnvelopedVerifiableCredential",
|
||||
"VerifiableCredential": {
|
||||
"@id": "https://www.w3.org/2018/credentials#VerifiableCredential",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"credentialSchema": {
|
||||
"@id": "https://www.w3.org/2018/credentials#credentialSchema",
|
||||
"@type": "@id"
|
||||
},
|
||||
"credentialStatus": {
|
||||
"@id": "https://www.w3.org/2018/credentials#credentialStatus",
|
||||
"@type": "@id"
|
||||
},
|
||||
"credentialSubject": {
|
||||
"@id": "https://www.w3.org/2018/credentials#credentialSubject",
|
||||
"@type": "@id"
|
||||
},
|
||||
"description": "https://schema.org/description",
|
||||
"evidence": {
|
||||
"@id": "https://www.w3.org/2018/credentials#evidence",
|
||||
"@type": "@id"
|
||||
},
|
||||
"validFrom": {
|
||||
"@id": "https://www.w3.org/2018/credentials#validFrom",
|
||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
|
||||
},
|
||||
"validUntil": {
|
||||
"@id": "https://www.w3.org/2018/credentials#validUntil",
|
||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
|
||||
},
|
||||
"issuer": {
|
||||
"@id": "https://www.w3.org/2018/credentials#issuer",
|
||||
"@type": "@id"
|
||||
},
|
||||
"name": "https://schema.org/name",
|
||||
"proof": {
|
||||
"@id": "https://w3id.org/security#proof",
|
||||
"@type": "@id",
|
||||
"@container": "@graph"
|
||||
},
|
||||
"refreshService": {
|
||||
"@id": "https://www.w3.org/2018/credentials#refreshService",
|
||||
"@type": "@id"
|
||||
},
|
||||
"termsOfUse": {
|
||||
"@id": "https://www.w3.org/2018/credentials#termsOfUse",
|
||||
"@type": "@id"
|
||||
},
|
||||
"confidenceMethod": {
|
||||
"@id": "https://www.w3.org/2018/credentials#confidenceMethod",
|
||||
"@type": "@id"
|
||||
},
|
||||
"relatedResource": {
|
||||
"@id": "https://www.w3.org/2018/credentials#relatedResource",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"VerifiablePresentation": {
|
||||
"@id": "https://www.w3.org/2018/credentials#VerifiablePresentation",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"holder": {
|
||||
"@id": "https://www.w3.org/2018/credentials#holder",
|
||||
"@type": "@id"
|
||||
},
|
||||
"proof": {
|
||||
"@id": "https://w3id.org/security#proof",
|
||||
"@type": "@id",
|
||||
"@container": "@graph"
|
||||
},
|
||||
"verifiableCredential": {
|
||||
"@id": "https://www.w3.org/2018/credentials#verifiableCredential",
|
||||
"@type": "@id",
|
||||
"@container": "@graph",
|
||||
"@context": null
|
||||
},
|
||||
"termsOfUse": {
|
||||
"@id": "https://www.w3.org/2018/credentials#termsOfUse",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"JsonSchemaCredential": "https://www.w3.org/2018/credentials#JsonSchemaCredential",
|
||||
"JsonSchema": {
|
||||
"@id": "https://www.w3.org/2018/credentials#JsonSchema",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"jsonSchema": {
|
||||
"@id": "https://w3.org/2018/credentials#jsonSchema",
|
||||
"@type": "@json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"BitstringStatusListCredential": "https://www.w3.org/ns/credentials/status#BitstringStatusListCredential",
|
||||
"BitstringStatusList": {
|
||||
"@id": "https://www.w3.org/ns/credentials/status#BitstringStatusList",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"statusPurpose": "https://www.w3.org/ns/credentials/status#statusPurpose",
|
||||
"encodedList": {
|
||||
"@id": "https://www.w3.org/ns/credentials/status#encodedList",
|
||||
"@type": "https://w3id.org/security#multibase"
|
||||
},
|
||||
"ttl": "https://www.w3.org/ns/credentials/status#ttl",
|
||||
"statusReference": "https://www.w3.org/ns/credentials/status#statusReference",
|
||||
"statusSize": "https://www.w3.org/ns/credentials/status#statusSize",
|
||||
"statusMessage": {
|
||||
"@id": "https://www.w3.org/ns/credentials/status#statusMessage",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"status": "https://www.w3.org/ns/credentials/status#status",
|
||||
"message": "https://www.w3.org/ns/credentials/status#message"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"BitstringStatusListEntry": {
|
||||
"@id": "https://www.w3.org/ns/credentials/status#BitstringStatusListEntry",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"statusPurpose": "https://www.w3.org/ns/credentials/status#statusPurpose",
|
||||
"statusListIndex": "https://www.w3.org/ns/credentials/status#statusListIndex",
|
||||
"statusListCredential": {
|
||||
"@id": "https://www.w3.org/ns/credentials/status#statusListCredential",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DataIntegrityProof": {
|
||||
"@id": "https://w3id.org/security#DataIntegrityProof",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"challenge": "https://w3id.org/security#challenge",
|
||||
"created": {
|
||||
"@id": "http://purl.org/dc/terms/created",
|
||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
|
||||
},
|
||||
"domain": "https://w3id.org/security#domain",
|
||||
"expires": {
|
||||
"@id": "https://w3id.org/security#expiration",
|
||||
"@type": "http://www.w3.org/2001/XMLSchema#dateTime"
|
||||
},
|
||||
"nonce": "https://w3id.org/security#nonce",
|
||||
"previousProof": {
|
||||
"@id": "https://w3id.org/security#previousProof",
|
||||
"@type": "@id"
|
||||
},
|
||||
"proofPurpose": {
|
||||
"@id": "https://w3id.org/security#proofPurpose",
|
||||
"@type": "@vocab",
|
||||
"@context": {
|
||||
"@protected": true,
|
||||
"id": "@id",
|
||||
"type": "@type",
|
||||
"assertionMethod": {
|
||||
"@id": "https://w3id.org/security#assertionMethod",
|
||||
"@type": "@id",
|
||||
"@container": "@set"
|
||||
},
|
||||
"authentication": {
|
||||
"@id": "https://w3id.org/security#authenticationMethod",
|
||||
"@type": "@id",
|
||||
"@container": "@set"
|
||||
},
|
||||
"capabilityInvocation": {
|
||||
"@id": "https://w3id.org/security#capabilityInvocationMethod",
|
||||
"@type": "@id",
|
||||
"@container": "@set"
|
||||
},
|
||||
"capabilityDelegation": {
|
||||
"@id": "https://w3id.org/security#capabilityDelegationMethod",
|
||||
"@type": "@id",
|
||||
"@container": "@set"
|
||||
},
|
||||
"keyAgreement": {
|
||||
"@id": "https://w3id.org/security#keyAgreementMethod",
|
||||
"@type": "@id",
|
||||
"@container": "@set"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cryptosuite": {
|
||||
"@id": "https://w3id.org/security#cryptosuite",
|
||||
"@type": "https://w3id.org/security#cryptosuiteString"
|
||||
},
|
||||
"proofValue": {
|
||||
"@id": "https://w3id.org/security#proofValue",
|
||||
"@type": "https://w3id.org/security#multibase"
|
||||
},
|
||||
"verificationMethod": {
|
||||
"@id": "https://w3id.org/security#verificationMethod",
|
||||
"@type": "@id"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -44,6 +44,15 @@ public class OB30Tests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleV1JsonValid() {
|
||||
assertDoesNotThrow(()->{
|
||||
Report report = validator.run(Samples.OB30.JSON.SIMPLE_V1_JSON.asFileResource());
|
||||
if(verbose) PrintHelper.print(report, true);
|
||||
assertWarning(report);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleDidKeyMethodJsonValid() {
|
||||
assertDoesNotThrow(()->{
|
||||
@ -219,7 +228,7 @@ public class OB30Tests {
|
||||
assertDoesNotThrow(()->{
|
||||
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_VERSION_CONTEXT.asFileResource());
|
||||
if(verbose) PrintHelper.print(report, true);
|
||||
assertHasValidProbeID(report, ContextPropertyProbe.ID);
|
||||
assertHasProbeID(report, ContextPropertyProbe.ID, true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -342,7 +351,6 @@ public class OB30Tests {
|
||||
});
|
||||
}
|
||||
|
||||
@Disabled //TODO IssuanceVerifierProbe is not run because FATAL: InvalidSignature terminates
|
||||
@Test
|
||||
void testSimpleJsonNotIssued() {
|
||||
//"issuanceDate": "2040-01-01T00:00:00Z",
|
||||
@ -382,11 +390,11 @@ public class OB30Tests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEddsa2022Valid() {
|
||||
void testEddsa2022Warning() {
|
||||
assertDoesNotThrow(()->{
|
||||
Report report = validator.run(Samples.OB30.JSON.SIMPLE_EDDSA_20222_JSON.asFileResource());
|
||||
if(verbose) PrintHelper.print(report, true);
|
||||
assertValid(report);
|
||||
assertWarning(report);
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ public class Samples {
|
||||
public static final class JSON {
|
||||
public final static Sample COMPLETE_JSON = new Sample("ob30/complete.json", false);
|
||||
public final static Sample SIMPLE_JSON = new Sample("ob30/simple.json", true);
|
||||
public final static Sample SIMPLE_V1_JSON = new Sample("ob30/simple_v1.json", true);
|
||||
public final static Sample SIMPLE_EDDSA_20222_JSON = new Sample("ob30/simple-eddsa-2022.json", true);
|
||||
public final static Sample SIMPLE_DID_KEY_METHOD_JSON = new Sample("ob30/simple-did-key-method.json", true);
|
||||
public final static Sample SIMPLE_DID_WEB_METHOD_JSON = new Sample("ob30/simple-did-web-method.json", true);
|
||||
|
@ -1,39 +1,43 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
],
|
||||
"id": "http://1edtech.edu/endorsementcredential/3732",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json"
|
||||
],
|
||||
"id": "http://1edtech.edu/endorsementcredential/3732",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"EndorsementCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://state.gov/issuers/565049",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"EndorsementCredential"
|
||||
"Profile"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://state.gov/issuers/565049",
|
||||
"type": ["Profile"],
|
||||
"name": "State Department of Education"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"expirationDate": "2030-01-01T00:00:00Z",
|
||||
"name": "Example endorsement",
|
||||
"credentialSubject": {
|
||||
"id": "https://1edtech.edu/issuers/565049",
|
||||
"type": ["EndorsementSubject"],
|
||||
"endorsementComment": "1EdTech University is in good standing"
|
||||
},
|
||||
"credentialSchema": [
|
||||
{
|
||||
"id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_endorsementcredential_schema.json",
|
||||
"type": "1EdTechJsonSchemaValidator2019"
|
||||
}
|
||||
"name": "State Department of Education"
|
||||
},
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"validUntil": "2030-01-01T00:00:00Z",
|
||||
"name": "Example endorsement",
|
||||
"credentialSubject": {
|
||||
"id": "https://1edtech.edu/issuers/565049",
|
||||
"type": [
|
||||
"EndorsementSubject"
|
||||
],
|
||||
"proof": [{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://state.gov/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z347N8ntbL3usCGshtUZiyrBeGBhYVAqyi4HUhz4fBmU1zVwk5eRfPZJvKoendfyGaeSbJcAfQEVNpvcHLzVhDtQC"
|
||||
}]
|
||||
}
|
||||
"endorsementComment": "1EdTech University is in good standing"
|
||||
},
|
||||
"credentialSchema": [
|
||||
{
|
||||
"id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_endorsementcredential_schema.json",
|
||||
"type": "1EdTechJsonSchemaValidator2019"
|
||||
}
|
||||
],
|
||||
"proof": [{
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://state.gov/issuers/565049#z6MkoMGF38Ck9xkdqrbZt4h9eHb1qc3GhAAkoSWa4Vy3SHRN",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z4DKZeDFKKvz5dDVPEky9NU8Zk3J8tH62Vtnm7drwwvPhDKwd6wL6td8skZkbyqw17y5zNJxfjT42dKpQc3Mgx1x6"
|
||||
}]
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context/ob_v3p0.jsonld",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
@ -35,13 +34,13 @@
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"validFrom": "2024-03-21T14:56:35Z",
|
||||
"proof": [{
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z56yYTVAJxcTduuDvdCfnmEcYsRwHS7aBxHTgqYQUWYuXQxTyEswJTs4ynNeB8yjdoLcspTYL4z6mscwC47fJ8bBN"
|
||||
}]
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.1.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.2.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
@ -16,7 +15,7 @@
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -35,13 +34,12 @@
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"proof": [{
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "zD8RrkKVSVEPYspwCe9T1a68NAVt2GyV566uR6QLdxCMdkg2b4rdUf9w1BC8ZEyhGdEz13kzkBwkjTTvoYAYsy15"
|
||||
}]
|
||||
}
|
@ -1,33 +1,47 @@
|
||||
{
|
||||
"@context" : [ "https://www.w3.org/2018/credentials/v1", "https://purl.imsglobal.org/spec/ob/v3p0/context.json", "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json", "https://w3id.org/security/suites/ed25519-2020/v1" ],
|
||||
"id" : "urn:uuid:280c19b6-9680-4a37-ba84-e38b1a4e4584",
|
||||
"type" : [ "VerifiableCredential", "AchievementCredential" ],
|
||||
"issuer" : {
|
||||
"type" : [ "Profile" ],
|
||||
"name" : "Andy F. Miller",
|
||||
"id" : "urn:uuid:6f2e33e5-7a29-4155-840a-59483ba10164"
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json"
|
||||
],
|
||||
"id": "urn:uuid:280c19b6-9680-4a37-ba84-e38b1a4e4584",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"AchievementCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Andy F. Miller",
|
||||
"id": "urn:uuid:6f2e33e5-7a29-4155-840a-59483ba10164"
|
||||
},
|
||||
"issuanceDate" : "2022-11-10T07:38:00-08:00",
|
||||
"name" : "test 1",
|
||||
"credentialSubject" : {
|
||||
"id" : "urn:uuid:6f2e33e5-7a29-4155-840a-59483ba10164",
|
||||
"type" : [ "AchievementSubject" ],
|
||||
"achievement" : {
|
||||
"id" : "urn:uuid:35258e6f-4c05-4215-8ada-38a5a5b80510",
|
||||
"type" : [ "Achievement" ],
|
||||
"achievementType" : "Achievement",
|
||||
"name" : "test 1",
|
||||
"description" : "This is a test achievement",
|
||||
"criteria" : {
|
||||
"narrative" : "There is no criteria"
|
||||
"validFrom": "2022-11-10T07:38:00-08:00",
|
||||
"name": "test 1",
|
||||
"credentialSubject": {
|
||||
"id": "urn:uuid:6f2e33e5-7a29-4155-840a-59483ba10164",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "urn:uuid:35258e6f-4c05-4215-8ada-38a5a5b80510",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"achievementType": "Achievement",
|
||||
"name": "test 1",
|
||||
"description": "This is a test achievement",
|
||||
"criteria": {
|
||||
"narrative": "There is no criteria"
|
||||
}
|
||||
}
|
||||
},
|
||||
"proof" : [ {
|
||||
"type" : "Ed25519Signature2020",
|
||||
"created" : "2022-11-16T20:39:53Z",
|
||||
"proofPurpose" : "assertionMethod",
|
||||
"verificationMethod" : "did:key:z6MkwAQmEfso8UjHJZTQajRtqR5hDxAD95iJD4z53XnKCFms",
|
||||
"proofValue" : "z361ueyGzREPvsWdnWUfkzTKXEd6u2DPPu2kDw3pDERJmzDFCqsuaPneqcRgz2hk9ycaNDYmC4Fy9c6S6BDDt5fVB"
|
||||
} ]
|
||||
}
|
||||
"proof": [{
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "did:key:z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5v2mkEWTLxzJ4VCxvUx5dRoy54Hp81GpyABUk7NswQECwDH6Ecwv5F3Mqso7t18UY6WScm5Qszo6nqiiqmevRWHc"
|
||||
}]
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.1.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/credential/d002b4e9-6fd9-4af0-b1f7-faa9237b46ca",
|
||||
"type": [
|
||||
@ -12,22 +10,30 @@
|
||||
],
|
||||
"issuer": {
|
||||
"id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c",
|
||||
"type": ["Profile"],
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"address": {
|
||||
"type": ["Address"],
|
||||
"type": [
|
||||
"Address"
|
||||
],
|
||||
"addressCountry": "Japan"
|
||||
},
|
||||
"name": "1EdTech Testing"
|
||||
},
|
||||
"awardedDate": "2023-05-22T14:09:00Z",
|
||||
"issuanceDate": "2023-05-23T01:07:22Z",
|
||||
"validFrom": "2023-05-23T01:07:22Z",
|
||||
"name": "ob3-simple-did-web-method.json",
|
||||
"credentialSubject": {
|
||||
"id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:learner:6896f98f-6b42-4c75-98ec-8befd0dc0b29",
|
||||
"type": ["AchievementSubject"],
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/achievement/66457db3-fb3d-4ae3-8f32-bc8c79c9f0db",
|
||||
"type": ["Achievement"],
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"achievementType": "Achievement",
|
||||
"criteria": {
|
||||
"narrative": "Passes tests"
|
||||
@ -37,9 +43,13 @@
|
||||
},
|
||||
"source": {
|
||||
"id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c",
|
||||
"type": ["Profile"],
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"address": {
|
||||
"type": ["Address"],
|
||||
"type": [
|
||||
"Address"
|
||||
],
|
||||
"addressCountry": "Japan"
|
||||
},
|
||||
"name": "1EdTech Testing"
|
||||
@ -54,10 +64,11 @@
|
||||
"type": "1EdTechCredentialRefresh"
|
||||
},
|
||||
"proof": [{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2023-05-23T01:07:22Z",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c#key-0",
|
||||
"proofValue": "z5tVhex5rV9aTxTrGh26uyVdC6BWXG8dQCkzNjgkPWtwAjGzMyYXzrQYJ2XrKUsNpYE3fTXsgUSBwDCY11vbyGBw7"
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z54xk5KNnchymcgxxaTECoREb3n9t8AeUU7AV5mNXhF56D82KPBtoXrPrR9DuEDL5oJtDxL3Cdv42Bt5QCJYcG4gc"
|
||||
}]
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"type": [
|
||||
@ -25,11 +24,12 @@
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-06-28T16:28:36Z",
|
||||
"verificationMethod": "did:key:z6MkkUD3J14nkYzn46QeuaVSnp7dF85QJKwKvJvfsjx79aXj",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2024-03-20T14:53:19Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3MUt2ZuU8Byqivxh6GphEM65AFYyNaGYibm97xLTafM7uGufZQLKvJR8itZwxKskvtFM3CUty46v26DZidMNoQnM"
|
||||
"proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,188 +1,186 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork",
|
||||
"resultDescription": [
|
||||
{
|
||||
"id": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"type": "ResultDescription",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project"
|
||||
}
|
||||
],
|
||||
"allowedValue": [
|
||||
"D",
|
||||
"C",
|
||||
"B",
|
||||
"A"
|
||||
],
|
||||
"name": "Final Project Grade",
|
||||
"requiredValue": "C",
|
||||
"resultType": "LetterGrade"
|
||||
},
|
||||
{
|
||||
"id": "urn:uuid:a70ddc6a-4c4a-4bd8-8277-cb97c79f40c5",
|
||||
"type": "ResultDescription",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project"
|
||||
}
|
||||
],
|
||||
"allowedValue": [
|
||||
"D",
|
||||
"C",
|
||||
"B",
|
||||
"A"
|
||||
],
|
||||
"name": "Final Project Grade",
|
||||
"requiredLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"resultType": "RubricCriterionLevel",
|
||||
"rubricCriterionLevel": [
|
||||
{
|
||||
"id": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"type": "RubricCriterionLevel",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFRubricCriterionLevel",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/rubric/levels/mastered"
|
||||
}
|
||||
],
|
||||
"description": "The author demonstrated...",
|
||||
"level": "Mastered",
|
||||
"name": "Mastery",
|
||||
"points": "4"
|
||||
},
|
||||
{
|
||||
"id": "urn:uuid:6b84b429-31ee-4dac-9d20-e5c55881f80e",
|
||||
"type": "RubricCriterionLevel",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFRubricCriterionLevel",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/rubric/levels/basic"
|
||||
}
|
||||
],
|
||||
"description": "The author demonstrated...",
|
||||
"level": "Basic",
|
||||
"name": "Basic",
|
||||
"points": "4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "urn:uuid:b07c0387-f2d6-4b65-a3f4-f4e4302ea8f7",
|
||||
"type": "InvalidResultDescription",
|
||||
"name": "Project Status",
|
||||
"resultType": "Status"
|
||||
}
|
||||
]
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"result": [
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork",
|
||||
"resultDescription": [
|
||||
{
|
||||
"id": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"type": "ResultDescription",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project"
|
||||
}
|
||||
],
|
||||
"allowedValue": [
|
||||
"D",
|
||||
"C",
|
||||
"B",
|
||||
"A"
|
||||
],
|
||||
"name": "Final Project Grade",
|
||||
"requiredValue": "C",
|
||||
"resultType": "LetterGrade"
|
||||
},
|
||||
{
|
||||
"id": "urn:uuid:a70ddc6a-4c4a-4bd8-8277-cb97c79f40c5",
|
||||
"type": "ResultDescription",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project"
|
||||
}
|
||||
],
|
||||
"allowedValue": [
|
||||
"D",
|
||||
"C",
|
||||
"B",
|
||||
"A"
|
||||
],
|
||||
"name": "Final Project Grade",
|
||||
"requiredLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"resultType": "RubricCriterionLevel",
|
||||
"rubricCriterionLevel": [
|
||||
{
|
||||
"id": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"type": "RubricCriterionLevel",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFRubricCriterionLevel",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/rubric/levels/mastered"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"achievedLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"description": "The author demonstrated...",
|
||||
"level": "Mastered",
|
||||
"name": "Mastery",
|
||||
"points": "4"
|
||||
},
|
||||
{
|
||||
"id": "urn:uuid:6b84b429-31ee-4dac-9d20-e5c55881f80e",
|
||||
"type": "RubricCriterionLevel",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFRubricCriterionLevel",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/rubric/levels/basic"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"status": "Completed"
|
||||
}
|
||||
"description": "The author demonstrated...",
|
||||
"level": "Basic",
|
||||
"name": "Basic",
|
||||
"points": "4"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "urn:uuid:b07c0387-f2d6-4b65-a3f4-f4e4302ea8f7",
|
||||
"type": "InvalidResultDescription",
|
||||
"name": "Project Status",
|
||||
"resultType": "Status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"proof": [
|
||||
},
|
||||
"result": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"achievedLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"status": "Completed"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "zW2X3KbSiPJ4zmN1GD641owCgz87NjsFpcRpjAdDoPhW7pWvyJUEap3iDKUWovRM43r15Wru6cv8qBVvVgnJxhuH"
|
||||
}
|
||||
}
|
@ -1,52 +1,52 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"Profile"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"identifier": [{
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"identifier": [
|
||||
{
|
||||
"type": "InvalidIdentityObject",
|
||||
"hashed": true,
|
||||
"identityHash": "asdjhsadas",
|
||||
"identityType": "lisSourcedId"
|
||||
}],
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5M8kUcxhKZ8niHpZt1LUBLrJGeLMnYaCmwrdR7MrcGzyiGz65zkk59212f7xpd7odxGVDp4e6MvNABsQ8YGn7U98"
|
||||
}
|
||||
}
|
@ -1,52 +1,50 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"source": {
|
||||
"id": "https://school.edu/issuers/201234",
|
||||
"type": "InvalidProfile",
|
||||
"name": "1EdTech College of Arts"
|
||||
}
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
},
|
||||
"source": {
|
||||
"id": "https://school.edu/issuers/201234",
|
||||
"type": "InvalidProfile",
|
||||
"name": "1EdTech College of Arts"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5kJkNSdserQduikVPAfEZ3qMPQRkyvcB7tTaNuxjqNZioQmijmWouvBqSGnAeKKoXAavTk4cxY94iuiEW9boXVyV"
|
||||
}
|
||||
}
|
@ -1,92 +1,90 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"result": [
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"InvalidResult"
|
||||
],
|
||||
"achievedLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"status": "Completed"
|
||||
}
|
||||
]
|
||||
},
|
||||
"proof": [
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
},
|
||||
"result": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"InvalidResult"
|
||||
],
|
||||
"achievedLevel": "urn:uuid:d05a0867-d0ad-4b03-bdb5-28fb5d2aab7a",
|
||||
"alignment": [
|
||||
{
|
||||
"type": "Alignment",
|
||||
"targetCode": "project",
|
||||
"targetDescription": "Project description",
|
||||
"targetName": "Final Project",
|
||||
"targetFramework": "1EdTech University Program and Course Catalog",
|
||||
"targetType": "CFItem",
|
||||
"targetUrl": "https://1edtech.edu/catalog/degree/project/result/1"
|
||||
}
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c"
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"Result"
|
||||
],
|
||||
"resultDescription": "urn:uuid:f6ab24cd-86e8-4eaf-b8c6-ded74e8fd41c",
|
||||
"status": "Completed"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5YBoPB9tjivuKpRyj9GknLKkReBcpjHxmeR4fGbAppoUpGC2GhbEC8eFdtrnk97ToRPYoQKdtFYDdixGqWXtRpsm"
|
||||
}
|
||||
}
|
@ -1,47 +1,45 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"Profile"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"InvalidAchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Profile"
|
||||
"Achievement"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"InvalidAchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z57amKtkLGz6Gs4s1R7hcgkWzrxayXt7HZ4L5Gt8VBGcM2Z4881fEDARqa8pM2N2dniqXz3U4cC6zW3UBfkQZCfN"
|
||||
}
|
||||
}
|
@ -1,66 +1,64 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"id": "https://1edtech.edu/credentials/3732/evidence/1",
|
||||
"type": "Evidence",
|
||||
"narrative": "# Final Project Report \n This project was ...",
|
||||
"name": "Final Project Report",
|
||||
"description": "This is the final project report.",
|
||||
"genre": "Research",
|
||||
"audience": "Department"
|
||||
},
|
||||
{
|
||||
"id": "https://github.com/somebody/project",
|
||||
"type": "InvalidEvidence",
|
||||
"name": "Final Project Code",
|
||||
"description": "This is the source code for the final project app.",
|
||||
"genre": "Research",
|
||||
"audience": "Department"
|
||||
}
|
||||
{
|
||||
"id": "https://1edtech.edu/credentials/3732/evidence/1",
|
||||
"type": "Evidence",
|
||||
"narrative": "# Final Project Report \n This project was ...",
|
||||
"name": "Final Project Report",
|
||||
"description": "This is the final project report.",
|
||||
"genre": "Research",
|
||||
"audience": "Department"
|
||||
},
|
||||
{
|
||||
"id": "https://github.com/somebody/project",
|
||||
"type": "InvalidEvidence",
|
||||
"name": "Final Project Code",
|
||||
"description": "This is the source code for the final project app.",
|
||||
"genre": "Research",
|
||||
"audience": "Department"
|
||||
}
|
||||
],
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "zbXsNxLTdGdCTdyfkefLRenndjs6QoXnwCYtNbXj4ZtwxrGa2xctb78XrBjuTNK8FKskysBYvMuSzvWYSzfzTXWX"
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
@ -16,8 +15,8 @@
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"expirationDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"validUntil": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -36,13 +35,12 @@
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
"proof": [{
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z2mAP6ezimojRWSHDhS1VfJgDdMCqa4oPbmJT1tCs43t5bRiwsrrhHxrmTEeAF2EBjErrzxoJj3HCKsdkyVkno11f"
|
||||
}]
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"type": [
|
||||
@ -16,8 +15,8 @@
|
||||
],
|
||||
"name": "Example University"
|
||||
},
|
||||
"issuanceDate": "2040-01-01T00:00:00Z",
|
||||
"expirationDate": "2050-01-20T00:00:00Z",
|
||||
"validFrom": "2040-01-01T00:00:00Z",
|
||||
"validUntil": "2050-01-20T00:00:00Z",
|
||||
"name": "Example University Degree",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -25,13 +24,12 @@
|
||||
"AchievementSubject"
|
||||
]
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-06-28T16:28:36Z",
|
||||
"verificationMethod": "did:key:z6MkkUD3J14nkYzn46QeuaVSnp7dF85QJKwKvJvfsjx79aXj",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3MUt2ZuU8Byqivxh6GphEM65AFYyNaGYibm97xLTafM7uGufZQLKvJR8itZwxKskvtFM3CUty46v26DZidMNoQnM"
|
||||
}
|
||||
]
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5EUB8AAu98Tdagjaf6QP7zY7MovnYTEB6vnNBgWjaCtaiNQfqNLQmEPpxvQuQPmVfQ49wcadz3DNUDk4CAt79HaF"
|
||||
}
|
||||
}
|
@ -1,59 +1,57 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp",
|
||||
"otherIdentifier": [
|
||||
{
|
||||
"type": "IdentifierEntry",
|
||||
"identifier": "12345",
|
||||
"identifierType": "sourcedId"
|
||||
},
|
||||
{
|
||||
"type": "InvalidIdentifierEntry",
|
||||
"identifier": "67890",
|
||||
"identifierType": "nationalIdentityNumber"
|
||||
}
|
||||
]
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp",
|
||||
"otherIdentifier": [
|
||||
{
|
||||
"type": "IdentifierEntry",
|
||||
"identifier": "12345",
|
||||
"identifierType": "sourcedId"
|
||||
},
|
||||
{
|
||||
"type": "InvalidIdentifierEntry",
|
||||
"identifier": "67890",
|
||||
"identifierType": "nationalIdentityNumber"
|
||||
}
|
||||
]
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3y8SeYGgaCjgeqe5vbKv9egn5zxHPoFNDYRXa9pHPxMua2P9PEinYmmjq12FqXYr272DhKj6tvBTCzvx3KRc8ys8"
|
||||
}
|
||||
}
|
@ -1,54 +1,52 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example Corp",
|
||||
"parentOrg": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
"InvalidProfile"
|
||||
],
|
||||
"name": "Example Corp",
|
||||
"parentOrg": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"InvalidProfile"
|
||||
],
|
||||
"name": "Example Parent Corp"
|
||||
}
|
||||
"name": "Example Parent Corp"
|
||||
}
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3f57gU5zssuyZTW2HxK2tV6qXCHyE3xdCHCczsUoRMSDBooCGboVBWUZygqpqskN5Mmpww8Qu3JARf1YvGcCzE34"
|
||||
}
|
||||
}
|
@ -1,47 +1,45 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"InvalidProfile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"InvalidProfile"
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
"Achievement"
|
||||
],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z2t8HUUbHs1G3o5t1uCTA7kbdprP21W9xmf8qJaDBWBoHSBFvJB26Bdq7Fi1ko2cnaHAvXETdMX6dPGFSA2rTP4KW"
|
||||
}
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Example University Degree",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -17,13 +16,12 @@
|
||||
"AchievementSubject"
|
||||
]
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-06-28T16:28:36Z",
|
||||
"verificationMethod": "did:key:z6MkkUD3J14nkYzn46QeuaVSnp7dF85QJKwKvJvfsjx79aXj",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3MUt2ZuU8Byqivxh6GphEM65AFYyNaGYibm97xLTafM7uGufZQLKvJR8itZwxKskvtFM3CUty46v26DZidMNoQnM"
|
||||
}
|
||||
]
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5ZjnJNPeQznivpmedtQZDAy9vXVz2BbhZp13fGpTfMnsgzccs2Z3Se2BRWeECSMo92cUsQP63LhMb6veWuD223j2"
|
||||
}
|
||||
}
|
@ -1,33 +1,23 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"type": ["VerifiableCredential", "OpenBadgeCredential"],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"type": ["Profile"],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"type": ["AchievementSubject"],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"type": ["Achievement"],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
@ -37,11 +27,12 @@
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2024-03-20T14:53:19Z",
|
||||
"verificationMethod": "z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,33 +1,23 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"type": ["VerifiableCredential", "OpenBadgeCredential"],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"type": ["Profile"],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"type": ["AchievementSubject"],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"type": ["Achievement"],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
@ -37,11 +27,12 @@
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "did:example:z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2024-03-20T14:53:19Z",
|
||||
"verificationMethod": "did:example:z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,33 +1,23 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"type": ["VerifiableCredential", "OpenBadgeCredential"],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"type": ["Profile"],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"type": ["AchievementSubject"],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"type": ["Achievement"],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
@ -37,11 +27,12 @@
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "xxx:z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2024-03-20T14:53:19Z",
|
||||
"verificationMethod": "xxx:z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"type": [
|
||||
@ -17,7 +16,7 @@
|
||||
],
|
||||
"name": "Example University"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Example University Degree",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -42,13 +41,12 @@
|
||||
"type": "1EdTechJsonSchemaValidator2019"
|
||||
}
|
||||
],
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-09-15T15:48:32Z",
|
||||
"verificationMethod": "https://example.edu/issuers/565049#xxMkmY1R6tG2NEdRHzphdRT6JqxeYpHwLAHwbrDfQULpkMAj",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3yUuWbFsLUp2CUrSZRaRbTk1UnkhpoJgJYu1SdMqd3AEMotpY41sKky7VzavnSfjApggtWJg1tcREvs5H4ZNnBRH"
|
||||
}
|
||||
]
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.edu/issuers/565049#z6MkjZRsdasZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z4HwAsa7GvwL7so7CoQ8v3ShzykRPCq8pfkAFKuAPrJx28S69pXphpqL8ApjoxEcMaqbgkaCUyKuEohhGXBR4Fh3L"
|
||||
}
|
||||
}
|
@ -1,34 +1,23 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/extensions.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": ["VerifiableCredential", "OpenBadgeCredential"],
|
||||
"issuer": {
|
||||
"id": "https://example.edu/issuers/565049",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example University"
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": ["Profile"],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"name": "Example University Degree",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"type": ["AchievementSubject"],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"type": ["Achievement"],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
@ -36,19 +25,14 @@
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"credentialSchema": [
|
||||
{
|
||||
"id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_achievementcredential_schema.json",
|
||||
"type": "1EdTechJsonSchemaValidator2019"
|
||||
}
|
||||
],
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-09-15T15:48:32Z",
|
||||
"verificationMethod": "https://example.edu/issuers/565049#z6MkmY1R6tG2NEdRHzphdRT6JqxeYpHwLAHwbrDfQULpkMAj",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2024-03-20T14:53:19Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z3fQCWGpz7b1HSH6DTwYiH5vutqtpJb5SHiP1VFK22xeBEW2D61tC9j3SktwPLNxPnTNZnPt4GeAZJPdVYserRqs4"
|
||||
"proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LvNFodwov9rPQxi3QRP7adCrzV"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,36 +1,34 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.edu/credentials/3732",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OtherCredential"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.edu/issuers/565049",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OtherCredential"
|
||||
"Profile"
|
||||
],
|
||||
"issuer": {
|
||||
"id": "https://example.edu/issuers/565049",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"name": "Example University"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"name": "Example University Degree",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
]
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-06-09T22:56:28Z",
|
||||
"verificationMethod": "https://example.edu/issuers/565049#key-1",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z58ieJCh4kN6eE2Vq4TyYURKSC4hWWEK7b75NNUL2taZMhKqwTteuByG1wRoGDdCqqNLW5Gq1diUi4qyZ63tQRtyN"
|
||||
}
|
||||
"name": "Example University"
|
||||
},
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Example University Degree",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
]
|
||||
}
|
||||
},
|
||||
"proof": {
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z662W1sSqKoA8ryTKK7PPVGKRrBkx5id3aDvdFNtguJcVFHJggDnkwJFntbo2cWfSwumCh9mgcYUe2RgpK1GZFyxa"
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
@ -5,34 +5,24 @@
|
||||
<![CDATA[
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
"VerifiableCredential",
|
||||
"OpenBadgeCredential"
|
||||
],
|
||||
"type": ["VerifiableCredential", "OpenBadgeCredential"],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": [
|
||||
"Profile"
|
||||
],
|
||||
"type": ["Profile"],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": [
|
||||
"AchievementSubject"
|
||||
],
|
||||
"type": ["AchievementSubject"],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": [
|
||||
"Achievement"
|
||||
],
|
||||
"type": ["Achievement"],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
@ -42,11 +32,12 @@
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2024-03-20T14:53:19Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.7 KiB |
@ -1,8 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
@ -16,7 +15,7 @@
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -35,17 +34,19 @@
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [{
|
||||
"proof": [
|
||||
{
|
||||
"type": "SomeProofType",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"proofPurpose": "assertionMethod"
|
||||
},
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
"proofValue": "z41ZsNkz78FHSGkAD5J4b8EN49DkywMMJSL3UdUNffbsCAWmTLPvtnJpd3JGGooYX7TNrzgsTLkXUWiGsRRZ788ML"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
"https://www.w3.org/ns/credentials/v2",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": [
|
||||
@ -16,7 +15,7 @@
|
||||
],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"validFrom": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
@ -35,13 +34,12 @@
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
"proof": [{
|
||||
"type": "DataIntegrityProof",
|
||||
"created": "2010-01-01T19:23:24Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi",
|
||||
"cryptosuite": "eddsa-rdfc-2022",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z41ZsNkz78FHSGkAD5J4b8EN49DkywMMJSL3UdUNffbsCAWmTLPvtnJpd3JGGooYX7TNrzgsTLkXUWiGsRRZ788ML"
|
||||
}]
|
||||
}
|
38
inspector-vc/src/test/resources/ob30/simple_v1.json
Normal file
38
inspector-vc/src/test/resources/ob30/simple_v1.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"@context": [
|
||||
"https://www.w3.org/2018/credentials/v1",
|
||||
"https://purl.imsglobal.org/spec/ob/v3p0/context.json",
|
||||
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||
],
|
||||
"id": "http://example.com/credentials/3527",
|
||||
"type": ["VerifiableCredential", "OpenBadgeCredential"],
|
||||
"issuer": {
|
||||
"id": "https://example.com/issuers/876543",
|
||||
"type": ["Profile"],
|
||||
"name": "Example Corp"
|
||||
},
|
||||
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||
"name": "Teamwork Badge",
|
||||
"credentialSubject": {
|
||||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||
"type": ["AchievementSubject"],
|
||||
"achievement": {
|
||||
"id": "https://example.com/achievements/21st-century-skills/teamwork",
|
||||
"type": ["Achievement"],
|
||||
"criteria": {
|
||||
"narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
|
||||
},
|
||||
"description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
|
||||
"name": "Teamwork"
|
||||
}
|
||||
},
|
||||
"proof": [
|
||||
{
|
||||
"type": "Ed25519Signature2020",
|
||||
"created": "2022-11-16T18:54:22Z",
|
||||
"verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv",
|
||||
"proofPurpose": "assertionMethod",
|
||||
"proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK"
|
||||
}
|
||||
]
|
||||
}
|
4
pom.xml
4
pom.xml
@ -7,7 +7,7 @@
|
||||
|
||||
<groupId>org.1edtech</groupId>
|
||||
<artifactId>vc-public-validator</artifactId>
|
||||
<version>1.0.4</version>
|
||||
<version>1.0.5</version>
|
||||
<name>vc-public-validator</name>
|
||||
<packaging>pom</packaging>
|
||||
<developers>
|
||||
@ -22,7 +22,7 @@
|
||||
<java.version>11</java.version>
|
||||
<log4j.version>2.17.2</log4j.version>
|
||||
<skipTests>false</skipTests>
|
||||
<public.core.version>1.0.4</public.core.version>
|
||||
<public.core.version>1.0.6</public.core.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
|
Loading…
Reference in New Issue
Block a user