├── .gitignore ├── LICENSE ├── README.md ├── inspector-clr ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── oneedtech │ │ └── inspect │ │ └── clr │ │ ├── CLR20Inspector.java │ │ └── probe │ │ └── ClrSubjectProbe.java │ └── test │ ├── java │ └── org │ │ └── oneedtech │ │ └── inspect │ │ └── clr │ │ ├── CLR20Tests.java │ │ └── Samples.java │ └── resources │ └── clr20 │ ├── complex.json │ ├── simple-noproof.json │ ├── simple.json │ ├── simple.jwt │ ├── simple_old_safesigned.json │ └── simple_v1.json ├── inspector-vc-web ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── oneedtech │ │ └── inspect │ │ └── vc │ │ └── web │ │ └── ValidatorApplication.java │ └── resources │ ├── application.properties │ └── validators.json ├── inspector-vc ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── oneedtech │ │ │ └── inspect │ │ │ └── vc │ │ │ ├── Assertion.java │ │ │ ├── BitstringStatusListCredentialInspector.java │ │ │ ├── Credential.java │ │ │ ├── EndorsementInspector.java │ │ │ ├── OB20EndorsementInspector.java │ │ │ ├── OB20Inspector.java │ │ │ ├── OB30Inspector.java │ │ │ ├── VCInspector.java │ │ │ ├── Validation.java │ │ │ ├── VerifiableCredential.java │ │ │ ├── W3CVCHolder.java │ │ │ ├── W3CVerifiableCredentialDM2.java │ │ │ ├── jsonld │ │ │ ├── JsonLDObjectUtils.java │ │ │ ├── JsonLdGeneratedObject.java │ │ │ └── probe │ │ │ │ ├── ExtensionProbe.java │ │ │ │ ├── GraphFetcherProbe.java │ │ │ │ ├── JsonLDCompactionProve.java │ │ │ │ └── JsonLDValidationProbe.java │ │ │ ├── payload │ │ │ ├── JsonParser.java │ │ │ ├── JwtParser.java │ │ │ ├── PayloadParser.java │ │ │ ├── PayloadParserFactory.java │ │ │ ├── PngParser.java │ │ │ └── SvgParser.java │ │ │ ├── probe │ │ │ ├── AssertionRevocationListProbe.java │ │ │ ├── ContextPropertyProbe.java │ │ │ ├── CredentialParseProbe.java │ │ │ ├── CredentialSubjectProbe.java │ │ │ ├── EmbeddedProofModel.java │ │ │ ├── EmbeddedProofModelGenerator.java │ │ │ ├── EmbeddedProofProbe.java │ │ │ ├── EvidenceProbe.java │ │ │ ├── ExpirationProbe.java │ │ │ ├── ExternalProofProbe.java │ │ │ ├── InlineJsonSchemaProbe.java │ │ │ ├── IssuanceProbe.java │ │ │ ├── IssuerProbe.java │ │ │ ├── JsonSchemasProbe.java │ │ │ ├── PropertyProbe.java │ │ │ ├── RevocationListProbe.java │ │ │ ├── RunContextKey.java │ │ │ ├── StringValuePropertyProbe.java │ │ │ ├── TypePropertyProbe.java │ │ │ ├── VerificationDependenciesProbe.java │ │ │ ├── VerificationJWTProbe.java │ │ │ ├── VerificationRecipientProbe.java │ │ │ ├── did │ │ │ │ ├── DidResolution.java │ │ │ │ ├── DidResolutionException.java │ │ │ │ ├── DidResolver.java │ │ │ │ └── SimpleDidResolver.java │ │ │ └── validation │ │ │ │ ├── ValidationImagePropertyProbe.java │ │ │ │ ├── ValidationIssuerPropertyProbe.java │ │ │ │ ├── ValidationPropertyProbe.java │ │ │ │ ├── ValidationPropertyProbeFactory.java │ │ │ │ └── ValidationRdfTypePropertyProbe.java │ │ │ ├── resource │ │ │ ├── DefaultUriResourceFactory.java │ │ │ └── UriResourceFactory.java │ │ │ ├── status │ │ │ └── bitstring │ │ │ │ └── BitstringStatusListProbe.java │ │ │ ├── util │ │ │ ├── CachingDocumentLoader.java │ │ │ ├── JsonNodeUtil.java │ │ │ └── PrimitiveValueValidator.java │ │ │ └── verification │ │ │ ├── Ed25519Signature2022LdVerifier.java │ │ │ ├── Ed25519Signature2022SignatureSuite.java │ │ │ ├── Ed25519Signature2022VCDM20LdVerifier.java │ │ │ ├── Eddsa2022LdProof.java │ │ │ ├── Eddsa2022v2LdProof.java │ │ │ ├── LDSecurityContexts.java │ │ │ ├── SignatureSuites.java │ │ │ └── URDNA2015Canonicalizer.java │ └── resources │ │ └── contexts │ │ ├── 2018-credentials-examples-v1.jsonld │ │ ├── 2018-credentials-v1.jsonld │ │ ├── clr-v2p0-2.0.1.json │ │ ├── clr-v2p0.json │ │ ├── credentials-v2.jsonld │ │ ├── data-integrity-v1.jsonld │ │ ├── did-v1.jsonld │ │ ├── ob-v2p0.json │ │ ├── ob-v3p0-3.0.1.json │ │ ├── ob-v3p0-3.0.2.json │ │ ├── ob-v3p0-3.0.3.json │ │ ├── ob-v3p0-extensions.json │ │ ├── ob-v3p0.json │ │ ├── obv2x-applylink-extensions.json │ │ ├── obv2x-example-extension.json │ │ ├── obv2x.jsonld │ │ ├── obv3x.jsonld │ │ ├── odrl.jsonld │ │ ├── security-bbs-v1.jsonld │ │ ├── security-suites-ed25519-2020-v1.jsonld │ │ ├── security-v1.jsonld │ │ ├── security-v2.jsonld │ │ ├── security-v3-unstable.jsonld │ │ ├── suites-ed25519-2018.jsonld │ │ ├── suites-ed25519-2020.jsonld │ │ ├── suites-jws-2020.jsonld │ │ ├── suites-secp256k1-2019.jsonld │ │ └── suites-x25519-2019.jsonld │ └── test │ ├── java │ └── org │ │ └── oneedtech │ │ └── inspect │ │ └── vc │ │ ├── BitstringStatusListCredentialInspectorTest.java │ │ ├── Endorsement30Tests.java │ │ ├── OB20Tests.java │ │ ├── OB30Tests.java │ │ ├── Samples.java │ │ ├── credential │ │ └── PayloadParserTests.java │ │ ├── resource │ │ └── TestUriResourceFactory.java │ │ └── util │ │ ├── CachingDocumentLoaderTests.java │ │ ├── JsonNodeUtilTests.java │ │ ├── PrimitiveValueValidatorTests.java │ │ └── TestOB20Inspector.java │ └── resources │ ├── ob20 │ ├── assertion-with-data-image.json │ ├── assertion-with-endorsements.json │ ├── assertion-with-extension-node-basic.json │ ├── assertion-with-extension-node-invalid.json │ ├── assertion-with-multiple-extensions.json │ ├── assets │ │ ├── altbadgeurl.json │ │ ├── bad-issuer.json │ │ ├── badge-from-organization-with-empty-revocation-list.json │ │ ├── badge-from-organization-with-revocation-list.json │ │ ├── badge-with-bad-issuer.json │ │ ├── badge-with-data-image.json │ │ ├── badgeclass-with-complex-image.json │ │ ├── badgeclass-with-endorsements.json │ │ ├── badgeclass-with-language.json │ │ ├── badgeclass-with-verification-invalid-multiple-starts-with.json │ │ ├── badgeclass-with-verification-invalid-starts-with.json │ │ ├── badgeclass-with-verification-valid-multiple-starts-with.json │ │ ├── badgeclass-with-verification-valid-starts-with.json │ │ ├── badgeclass-with-verification.json │ │ ├── badgeclass1.json │ │ ├── badgecriteria.json │ │ ├── basic-badge-no-public-key.json │ │ ├── beths-robot-badge.png │ │ ├── beths-robot-work.html │ │ ├── criteria-no-type.json │ │ ├── empty-revocation-list.json │ │ ├── endorsement-1.json │ │ ├── endorsement-2.json │ │ ├── endorsement-3.json │ │ ├── endorsement-4.json │ │ ├── issuer-invalid-type.json │ │ ├── issuer-with-allowed-origins-invalid-multiple-starts-with.json │ │ ├── issuer-with-allowed-origins-invalid-starts-with.json │ │ ├── issuer-with-allowed-origins-valid-multiple-starts-with.json │ │ ├── issuer-with-allowed-origins-valid-starts-with.json │ │ ├── issuer-with-allowed-origins.json │ │ ├── issuer1.json │ │ ├── key1.json │ │ ├── key2.json │ │ ├── key3.json │ │ ├── openbadges_context.json │ │ ├── organization-no-public-key.json │ │ ├── organization-with-empty-revocation-list.json │ │ ├── organization-with-revocation-list.json │ │ ├── organization.json │ │ ├── revocation-list.json │ │ ├── robotics-badge.json │ │ └── robotics-badge.png │ ├── badge-class-with-language.json │ ├── basic-assertion-expired-before-issued.json │ ├── basic-assertion-expired.json │ ├── basic-assertion-in-future.json │ ├── basic-assertion-invalid-context.json │ ├── basic-assertion-invalid-type.json │ ├── basic-assertion-no-public-key.json │ ├── basic-assertion-with-allowed-origins-invalid-multiple-starts-with.json │ ├── basic-assertion-with-allowed-origins-invalid-starts-with.json │ ├── basic-assertion-with-allowed-origins-valid-multiple-starts-with.json │ ├── basic-assertion-with-allowed-origins-valid-starts-with.json │ ├── basic-assertion-with-allowed-origins.json │ ├── basic-assertion-with-language.json │ ├── basic-assertion.json │ ├── issuer-compact-iri-validation.json │ ├── rdf-validation │ │ ├── badge-class-invalid-issuer-type.json │ │ ├── invalid-class.json │ │ ├── invalid-empty-type.json │ │ ├── invalid-one-invalid-class.json │ │ ├── valid-alignment-object.json │ │ ├── valid-badge-class-empty-criteria-type.json │ │ ├── valid-badge-class.json │ │ ├── valid-cool-class.json │ │ └── valid-issuer-extension.json │ ├── redirected-validation-subject.json │ ├── simple-badge.png │ ├── simple-not-revoked.jwt │ ├── simple-revoked.jwt │ ├── simple.jwt │ ├── warning-issuer-non-http.json │ └── warning-with-redirection.json │ └── ob30 │ ├── bit-string-list │ ├── credential-status-revoked-blank-nodes.json │ ├── credential-status-revoked.json │ └── testlist │ ├── complete.json │ ├── complete_v1.json │ ├── credential-status-revoked.json │ ├── endorsement-err-schema-status-refresh.json │ ├── endorsement-valid.json │ ├── simple-context-alias.json │ ├── simple-context-version.json │ ├── simple-did-key-method.json │ ├── simple-did-web-method.json │ ├── simple-eddsa-2022.json │ ├── simple-err-context.json │ ├── simple-err-credential-subject-achievement-result-description-type.json │ ├── simple-err-credential-subject-identifier-type.json │ ├── simple-err-credential-subject-profile-type.json │ ├── simple-err-credential-subject-result-type.json │ ├── simple-err-credential-subject-type.json │ ├── simple-err-evidence-type.json │ ├── simple-err-expired.json │ ├── simple-err-issued.json │ ├── simple-err-issuer-otheridentifier-type.json │ ├── simple-err-issuer-parentorg-type.json │ ├── simple-err-issuer-type.json │ ├── simple-err-issuer.json │ ├── simple-err-proof-method-no-scheme.json │ ├── simple-err-proof-method-unknown-did-method.json │ ├── simple-err-proof-method-unknown-scheme.json │ ├── simple-err-proof-method.json │ ├── simple-err-proof-value.json │ ├── simple-err-type.json │ ├── simple-json.png │ ├── simple-json.svg │ ├── simple-jwt.png │ ├── simple-jwt.svg │ ├── simple-jwt_v1.png │ ├── simple-jwt_v1.svg │ ├── simple-multiple-proofs.json │ ├── simple-noproof.json │ ├── simple.1ob │ ├── simple.json │ ├── simple.jwt │ └── simple_v1.json └── pom.xml /inspector-clr/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | org.1edtech 7 | vc-public-validator 8 | 1.3.5 9 | 10 | inspector-clr 11 | 12 | 13 | org.1edtech 14 | inspector-vc 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /inspector-clr/src/main/java/org/oneedtech/inspect/clr/probe/ClrSubjectProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.clr.probe; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import org.oneedtech.inspect.core.probe.RunContext; 8 | import org.oneedtech.inspect.core.report.ReportItems; 9 | import org.oneedtech.inspect.vc.probe.CredentialSubjectProbe; 10 | 11 | import com.fasterxml.jackson.databind.JsonNode; 12 | 13 | public class ClrSubjectProbe extends CredentialSubjectProbe { 14 | 15 | public ClrSubjectProbe(String requiredType) { 16 | super(requiredType); 17 | } 18 | 19 | @Override 20 | protected Optional checkAchievement(JsonNode achievementNode, RunContext ctx) { 21 | if ( achievementNode.isObject() ) { 22 | return super.checkAchievement(achievementNode, ctx); 23 | } 24 | if (achievementNode.isArray()) { 25 | List reportItems = new ArrayList<>(); 26 | for (JsonNode node : achievementNode) { 27 | if (node.isObject()) { 28 | Optional result = super.checkAchievement(node, ctx); 29 | if (result.isPresent()) { 30 | reportItems.add(result.get()); 31 | } 32 | } 33 | } 34 | return !reportItems.isEmpty() ? 35 | Optional.of(new ReportItems(reportItems)) : 36 | Optional.empty(); 37 | } 38 | return Optional.empty(); 39 | } 40 | 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /inspector-clr/src/test/java/org/oneedtech/inspect/clr/CLR20Tests.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.clr; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 | import static org.oneedtech.inspect.test.Assertions.assertValid; 5 | import static org.oneedtech.inspect.test.Assertions.assertWarning; 6 | 7 | import org.junit.jupiter.api.BeforeAll; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | import org.oneedtech.inspect.core.Inspector; 11 | import org.oneedtech.inspect.core.Inspector.Behavior; 12 | import org.oneedtech.inspect.core.report.Report; 13 | import org.oneedtech.inspect.test.PrintHelper; 14 | 15 | public class CLR20Tests { 16 | private static CLR20Inspector validator; 17 | private static boolean verbose = true; 18 | 19 | @BeforeAll 20 | static void setup() { 21 | validator = new CLR20Inspector.Builder() 22 | .set(Behavior.TEST_INCLUDE_SUCCESS, true) 23 | .set(Behavior.VALIDATOR_FAIL_FAST, false) 24 | .inject(Inspector.InjectionKeys.DID_RESOLUTION_SERVICE_URL, "http://dev.uniresolver.io/1.0/identifiers/") 25 | .build(); 26 | } 27 | 28 | @Test 29 | void testSimpleJsonValid() { 30 | assertDoesNotThrow(()->{ 31 | Report report = validator.run(Samples.CLR20.JSON.SIMPLE_JSON.asFileResource()); 32 | if(verbose) PrintHelper.print(report, true); 33 | assertValid(report); 34 | }); 35 | } 36 | 37 | @Test 38 | void testSimpleV1JsonValid() { 39 | assertDoesNotThrow(()->{ 40 | Report report = validator.run(Samples.CLR20.JSON.SIMPLE_V1_JSON.asFileResource()); 41 | if(verbose) PrintHelper.print(report, true); 42 | // warning due to outdated context versions 43 | assertWarning(report); 44 | }); 45 | } 46 | 47 | // commented out due that https://western.riverwell.k12.or.us/ is not accessible 48 | // @Test 49 | // void testComplexJsonValid() { 50 | // assertDoesNotThrow(()->{ 51 | // Report report = validator.run(Samples.CLR20.JSON.COMPLEX_JSON.asFileResource()); 52 | // if(verbose) PrintHelper.print(report, true); 53 | // assertValid(report); 54 | // }); 55 | // } 56 | 57 | @Disabled 58 | @Test 59 | void testSimpleJWTValid() { 60 | assertDoesNotThrow(()->{ 61 | Report report = validator.run(Samples.CLR20.JSON.SIMPLE_JWT.asFileResource()); 62 | if(verbose) PrintHelper.print(report, true); 63 | assertValid(report); 64 | }); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /inspector-clr/src/test/java/org/oneedtech/inspect/clr/Samples.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.clr; 2 | 3 | import org.oneedtech.inspect.test.Sample; 4 | 5 | public class Samples { 6 | public static final class CLR20 { 7 | public static final class JSON { 8 | public final static Sample SIMPLE_JSON = new Sample("clr20/simple.json", true); 9 | public final static Sample SIMPLE_V1_JSON = new Sample("clr20/simple_v1.json", true); 10 | public final static Sample SIMPLE_JSON_NOPROOF = new Sample("clr20/simple-noproof.json", true); 11 | public final static Sample SIMPLE_JWT = new Sample("clr20/simple.jwt", true); 12 | public final static Sample COMPLEX_JSON = new Sample("clr20/complex.json", true); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /inspector-vc-web/src/main/java/org/oneedtech/inspect/vc/web/ValidatorApplication.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.web; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | import org.oneedtech.inspect.web.InspectorWebConfig; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.ComponentScan; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Import; 11 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 12 | 13 | @SpringBootApplication // == @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan 14 | @Configuration 15 | @Import(InspectorWebConfig.class) 16 | @ComponentScan("org.oneedtech.inspect.web") 17 | public class ValidatorApplication implements WebMvcConfigurer { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(ValidatorApplication.class, args); 21 | } 22 | 23 | private final static Logger logger = LogManager.getLogger(); 24 | } 25 | -------------------------------------------------------------------------------- /inspector-vc-web/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # To build a docker image for distribution, set spring.profiles.active=prod and dockerMode=true 2 | # To build a fatjar for deployment on the ims website with oauth sso, set dockerMode=false and spring.profiles.active=prod 3 | # During development, set spring.profiles.active=dev. If dockerMode is true during devMode, a jwt license in /resources is used as a dummy. 4 | 5 | # to deploy jars to nexus: set profile=prod & dockerMode false, then mvn clean deploy -Dmaven.test.skip=true -P deploy-nexus 6 | # to build docker: set profile=prod & dockerMode true, then mvn clean install -Dmaven.test.skip=true -P docker, then docker:push gcr.io/staging-1edtech/ims/inspector:0.x.0 7 | 8 | #spring.profiles.active = dev | prod 9 | spring.profiles.active=dev 10 | dockerMode=false 11 | app.version=1.0.0 12 | 13 | # misc 14 | spring.jackson.serialization.INDENT_OUTPUT=true 15 | server.servlet.encoding.charset=UTF-8 16 | server.servlet.encoding.force-response=true -------------------------------------------------------------------------------- /inspector-vc-web/src/main/resources/validators.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "id": "vc", 5 | "name": "Verifiable Credentials", 6 | "desc": "Verifiers for the Open Badges and Comprehensive Learner Record specifications" 7 | } 8 | ], 9 | "validators" : [ 10 | { 11 | "id": "OB30Inspector", 12 | "name": "Open Badges 3.0 Verifier", 13 | "pkg": "org.oneedtech.inspect.vc", 14 | "desc": "Verifies Open Badges 3.0 files", 15 | "instr": "This validator supports Open Badges 3.0 files.", 16 | "spec": "ob", 17 | "group": "vc", 18 | "initParams": { 19 | "DID_RESOLUTION_SERVICE_URL": "http://dev.uniresolver.io/1.0/identifiers/" 20 | }, 21 | "supportsCertification": false, 22 | "submissionTypes": ["upload","uri"] 23 | }, 24 | { 25 | "id": "OB20Inspector", 26 | "name": "Open Badges 2.0 Verifier", 27 | "pkg": "org.oneedtech.inspect.vc", 28 | "desc": "Verifies Open Badges 2.0 files", 29 | "instr": "This validator supports Open Badges 2.0 files.", 30 | "spec": "ob", 31 | "group": "vc", 32 | "supportsCertification": false, 33 | "submissionTypes": ["upload","uri"] 34 | }, 35 | { 36 | "id": "CLR20Inspector", 37 | "name": "CLR 2.0 Verifier", 38 | "pkg": "org.oneedtech.inspect.clr", 39 | "desc": "Verifies Comprehensive Learner Record (CLR) 2.0 files", 40 | "instr": "This validator supports Comprehensive Learner Record (CLR) 2.0 files.", 41 | "spec": "spec-pid-todo", 42 | "group": "vc", 43 | "initParams": { 44 | "DID_RESOLUTION_SERVICE_URL": "http://dev.uniresolver.io/1.0/identifiers/" 45 | }, 46 | "supportsCertification": false, 47 | "submissionTypes": ["upload","uri"] 48 | } 49 | ] 50 | 51 | } -------------------------------------------------------------------------------- /inspector-vc/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | org.1edtech 7 | vc-public-validator 8 | 1.3.5 9 | 10 | inspector-vc 11 | 12 | 13 | org.1edtech 14 | inspector-core 15 | 16 | 17 | com.auth0 18 | auth0 19 | 1.42.0 20 | 21 | 22 | com.auth0 23 | jwks-rsa 24 | 0.21.1 25 | 26 | 27 | com.auth0 28 | java-jwt 29 | 3.19.2 30 | 31 | 32 | 33 | 34 | com.danubetech 35 | verifiable-credentials-java 36 | 1.12.0 37 | 38 | 39 | 40 | 41 | com.apicatalog 42 | iron-eddsa-rdfc-2022 43 | 0.14.0 44 | 45 | 46 | 47 | 48 | decentralized-identity 49 | uni-resolver-client 50 | 0.5.0 51 | 52 | 53 | 54 | 55 | org.apache.httpcomponents 56 | httpclient 57 | 4.5.13 58 | 59 | 60 | org.glassfish 61 | jakarta.json 62 | 2.0.1 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/W3CVCHolder.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc; 2 | 3 | import java.io.StringReader; 4 | import java.util.List; 5 | 6 | import org.oneedtech.inspect.vc.jsonld.JsonLDObjectUtils; 7 | import org.oneedtech.inspect.vc.util.CachingDocumentLoader; 8 | 9 | import info.weboftrust.ldsignatures.LdProof; 10 | 11 | /** 12 | * Holder for W3C's Verifiable Credential 13 | */ 14 | public class W3CVCHolder { 15 | private com.danubetech.verifiablecredentials.VerifiableCredential credential; 16 | 17 | public W3CVCHolder(VerifiableCredential credential) { 18 | switch (credential.version) { 19 | case VCDMv1p1: 20 | this.credential = com.danubetech.verifiablecredentials.VerifiableCredential 21 | .fromJson(new StringReader(credential.getJson().toString())); 22 | break; 23 | case VCDMv2p0: 24 | this.credential = W3CVerifiableCredentialDM2 25 | .fromJson(new StringReader(credential.getJson().toString())); 26 | break; 27 | default: 28 | throw new IllegalArgumentException("Unsupported version: " + credential.version); 29 | } 30 | this.credential.setDocumentLoader(new CachingDocumentLoader()); 31 | } 32 | 33 | /** 34 | * Get the list of proofs in the credential. 35 | * {@link VerifiableCredential} contains the method getLdProof(), but only works with one proof. This methods 36 | * returns a list of all proofs defined in the credential. 37 | * @return proofs defined in the credential 38 | */ 39 | public List getProofs() { 40 | return JsonLDObjectUtils.getListFromJsonLDObject(LdProof.class, credential); 41 | } 42 | 43 | public com.danubetech.verifiablecredentials.VerifiableCredential getCredential() { 44 | return credential; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/W3CVerifiableCredentialDM2.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc; 2 | 3 | import java.net.URI; 4 | import java.util.Date; 5 | import java.util.Map; 6 | 7 | import com.fasterxml.jackson.annotation.JsonCreator; 8 | 9 | import foundation.identity.jsonld.JsonLDUtils; 10 | 11 | public class W3CVerifiableCredentialDM2 extends com.danubetech.verifiablecredentials.VerifiableCredential { 12 | public static final URI[] DEFAULT_JSONLD_CONTEXTS = { URI.create(VerifiableCredential.JSONLD_CONTEXT_W3C_CREDENTIALS_V2) }; 13 | 14 | @JsonCreator 15 | public W3CVerifiableCredentialDM2() { 16 | super(); 17 | } 18 | 19 | protected W3CVerifiableCredentialDM2(Map jsonObject) { 20 | super(jsonObject); 21 | } 22 | 23 | public static W3CVerifiableCredentialDM2 fromJson(String json) { 24 | return new W3CVerifiableCredentialDM2(readJson(json)); 25 | } 26 | 27 | public Date getValidFrom() { 28 | return JsonLDUtils.stringToDate(JsonLDUtils.jsonLdGetString(this.getJsonObject(), JSONLD_TERM_VALIDFROM)); 29 | } 30 | 31 | public Date getValidUntil() { 32 | return JsonLDUtils.stringToDate(JsonLDUtils.jsonLdGetString(this.getJsonObject(), JSONLD_TERM_VALIDUNTIL)); 33 | } 34 | private static final String JSONLD_TERM_VALIDFROM = "validFrom"; 35 | private static final String JSONLD_TERM_VALIDUNTIL = "validUntil"; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/jsonld/JsonLDObjectUtils.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.jsonld; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.stream.Collectors; 9 | 10 | import foundation.identity.jsonld.JsonLDObject; 11 | 12 | public class JsonLDObjectUtils { 13 | @SuppressWarnings("unchecked") 14 | public static List getListFromJsonLDObject(Class cl, JsonLDObject jsonLdObject) { 15 | String term = JsonLDObject.getDefaultJsonLDPredicate(cl); 16 | List> jsonObjects = jsonLdGetJsonObjectList(jsonLdObject.getJsonObject(), term); 17 | if (jsonObjects == null) return null; 18 | try { 19 | Method method = cl.getMethod("fromMap", Map.class); 20 | return jsonObjects.stream().map(jsonObject -> { 21 | try { 22 | return (C) method.invoke(null, jsonObject); 23 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 24 | throw new Error(e); 25 | } 26 | }).collect(Collectors.toList()); 27 | } catch (NoSuchMethodException | SecurityException e) { 28 | throw new Error(e); 29 | } 30 | } 31 | 32 | @SuppressWarnings("unchecked") 33 | public static List> jsonLdGetJsonObjectList(Map jsonObject, String term) { 34 | Object entry = jsonObject.get(term); 35 | if (entry == null) return null; 36 | 37 | if (entry instanceof Map) { 38 | return Collections.singletonList((Map) entry); 39 | } else if (entry instanceof List && ((List) entry).stream().allMatch(e -> e instanceof Map)) { 40 | return (List>) (List>) entry; 41 | } else { 42 | throw new IllegalArgumentException("Cannot get json object '" + term + "' from " + jsonObject); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/jsonld/JsonLdGeneratedObject.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.jsonld; 2 | 3 | import org.oneedtech.inspect.core.probe.GeneratedObject; 4 | 5 | public class JsonLdGeneratedObject extends GeneratedObject { 6 | private String json; 7 | 8 | public JsonLdGeneratedObject(String json) { 9 | this(ID, json); 10 | } 11 | 12 | public JsonLdGeneratedObject(String id, String json) { 13 | super(id, GeneratedObject.Type.INTERNAL); 14 | this.json = json; 15 | } 16 | 17 | public String getJson() { 18 | return json; 19 | } 20 | 21 | /** 22 | * Update internal json. We allow this update because some validations updates JSON-LD id attributes with 23 | * autogenerated ones 24 | * @param json 25 | */ 26 | public void setJson(String json) { 27 | this.json = json; 28 | } 29 | 30 | public static final String ID = JsonLdGeneratedObject.class.getCanonicalName(); 31 | } 32 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/jsonld/probe/JsonLDCompactionProve.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.jsonld.probe; 2 | 3 | import java.io.StringReader; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.probe.RunContext.Key; 8 | import org.oneedtech.inspect.core.report.ReportItems; 9 | import org.oneedtech.inspect.util.resource.Resource; 10 | import org.oneedtech.inspect.vc.Credential; 11 | import org.oneedtech.inspect.vc.jsonld.JsonLdGeneratedObject; 12 | 13 | import com.apicatalog.jsonld.JsonLd; 14 | import com.apicatalog.jsonld.JsonLdOptions; 15 | import com.apicatalog.jsonld.document.JsonDocument; 16 | import com.apicatalog.jsonld.loader.DocumentLoader; 17 | 18 | import jakarta.json.JsonObject; 19 | 20 | /** 21 | * JSON-LD compaction probe for Open Badges 2.0 22 | * Maps to "JSONLD_COMPACT_DATA" task in python implementation 23 | * @author xaracil 24 | */ 25 | public class JsonLDCompactionProve extends Probe { 26 | private final String context; 27 | 28 | public JsonLDCompactionProve(String context) { 29 | super(ID); 30 | this.context = context; 31 | } 32 | 33 | @Override 34 | public ReportItems run(Credential crd, RunContext ctx) throws Exception { 35 | try { 36 | // compact JSON 37 | JsonDocument jsonDocument = JsonDocument.of(new StringReader(crd.getJson().toString())); 38 | JsonObject compactedObject = JsonLd.compact(jsonDocument, context) 39 | .options(new JsonLdOptions((DocumentLoader) ctx.get(Key.JSON_DOCUMENT_LOADER))) 40 | .get(); 41 | 42 | ctx.addGeneratedObject(new JsonLdGeneratedObject(getId(crd), compactedObject.toString())); 43 | 44 | // Handle mismatch between URL node source and declared ID. 45 | if (compactedObject.get("id") != null && crd.getResource().getID() != null 46 | && !compactedObject.get("id").toString().equals(crd.getResource().getID())) { 47 | // TODO: a new fetch of the JSON document at id is required 48 | return warning("Node fetched from source " + crd.getResource().getID() + " declared its id as " + compactedObject.get("id").toString(), ctx); 49 | } 50 | 51 | return success(this, ctx); 52 | } catch (Exception e) { 53 | return fatal("Error while compacting JSON-LD: " + crd.getJson() + ". Caused by: " + e.getMessage(), ctx); 54 | } 55 | } 56 | 57 | public static String getId(Credential crd) { 58 | return getId(crd.getResource()); 59 | } 60 | 61 | public static String getId(Resource resource) { 62 | return getId(resource.getID()); 63 | } 64 | public static String getId(String id) { 65 | return "json-ld-compact:" + id; 66 | } 67 | 68 | public static final String ID = JsonLDCompactionProve.class.getSimpleName(); 69 | } 70 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/jsonld/probe/JsonLDValidationProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.jsonld.probe; 2 | 3 | import java.io.StringReader; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | import org.oneedtech.inspect.vc.Credential; 9 | import org.oneedtech.inspect.vc.jsonld.JsonLdGeneratedObject; 10 | 11 | import foundation.identity.jsonld.JsonLDObject; 12 | import foundation.identity.jsonld.validation.Validation; 13 | 14 | public class JsonLDValidationProbe extends Probe { 15 | private final JsonLdGeneratedObject jsonLdObject; 16 | 17 | public JsonLDValidationProbe(JsonLdGeneratedObject jsonLdObject) { 18 | super(); 19 | this.jsonLdObject = jsonLdObject; 20 | } 21 | 22 | @Override 23 | public ReportItems run(Credential crd, RunContext ctx) throws Exception { 24 | JsonLDObject jsonLd = JsonLDObject.fromJson(new StringReader(jsonLdObject.getJson())); 25 | try { 26 | Validation.validate(jsonLd); 27 | return success(this, ctx); 28 | } catch (Exception e) { 29 | return fatal("Error while validation JSON LD object: " + e.getMessage(), ctx); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/JsonParser.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.payload; 2 | 3 | import static java.nio.charset.StandardCharsets.UTF_8; 4 | import static org.oneedtech.inspect.util.code.Defensives.checkTrue; 5 | 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.probe.RunContext.Key; 8 | import org.oneedtech.inspect.util.resource.Resource; 9 | import org.oneedtech.inspect.util.resource.ResourceType; 10 | import org.oneedtech.inspect.vc.Credential; 11 | import com.fasterxml.jackson.databind.JsonNode; 12 | 13 | /** 14 | * A credential extractor for JSON files. 15 | * @author mgylling 16 | */ 17 | public final class JsonParser extends PayloadParser { 18 | 19 | @Override 20 | public boolean supports(ResourceType type) { 21 | return type == ResourceType.JSON; 22 | } 23 | 24 | @Override 25 | public Credential parse(Resource resource, RunContext ctx) throws Exception { 26 | checkTrue(resource.getType() == ResourceType.JSON); 27 | String json = resource.asByteSource().asCharSource(UTF_8).read(); 28 | JsonNode node = fromString(json, ctx); 29 | 30 | return getBuilder(ctx) 31 | .resource(resource) 32 | .jsonData(node) 33 | .build(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/JwtParser.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.payload; 2 | 3 | import static java.nio.charset.StandardCharsets.UTF_8; 4 | import static org.oneedtech.inspect.util.code.Defensives.checkTrue; 5 | 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.util.resource.Resource; 8 | import org.oneedtech.inspect.util.resource.ResourceType; 9 | import org.oneedtech.inspect.vc.Credential; 10 | 11 | import com.fasterxml.jackson.databind.JsonNode; 12 | 13 | /** 14 | * A credential extractor for JWT files. 15 | * @author mgylling 16 | */ 17 | public final class JwtParser extends PayloadParser { 18 | 19 | @Override 20 | public boolean supports(ResourceType type) { 21 | return type == ResourceType.JWT; 22 | } 23 | 24 | @Override 25 | public Credential parse(Resource resource, RunContext ctx) throws Exception { 26 | checkTrue(resource.getType() == ResourceType.JWT); 27 | String jwt = resource.asByteSource().asCharSource(UTF_8).read(); 28 | JsonNode node = fromJwt(jwt, ctx); 29 | return getBuilder(ctx) 30 | .resource(resource) 31 | .jsonData(node) 32 | .jwt(jwt) 33 | .build(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/PayloadParser.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.payload; 2 | 3 | import static com.apicatalog.jsonld.StringUtils.isBlank; 4 | 5 | import java.util.Base64; 6 | import java.util.Base64.Decoder; 7 | import java.util.List; 8 | 9 | import org.oneedtech.inspect.core.probe.RunContext; 10 | import org.oneedtech.inspect.core.probe.RunContext.Key; 11 | import org.oneedtech.inspect.util.resource.Resource; 12 | import org.oneedtech.inspect.util.resource.ResourceType; 13 | import org.oneedtech.inspect.vc.Credential; 14 | 15 | import com.fasterxml.jackson.databind.JsonNode; 16 | import com.fasterxml.jackson.databind.ObjectMapper; 17 | import com.google.common.base.Splitter; 18 | 19 | /** 20 | * Abstract base for extracting Credential instances from payloads. 21 | * @author mgylling 22 | */ 23 | public abstract class PayloadParser { 24 | 25 | public abstract boolean supports(ResourceType type); 26 | 27 | public abstract Credential parse(Resource source, RunContext ctx) throws Exception; 28 | 29 | @SuppressWarnings("rawtypes") 30 | public static Credential.Builder getBuilder(RunContext context) { 31 | return ((Credential.Builder) context.get(RunContext.Key.GENERATED_OBJECT_BUILDER)); 32 | } 33 | 34 | protected static JsonNode fromString(String json, RunContext context) throws Exception { 35 | return ((ObjectMapper)context.get(RunContext.Key.JACKSON_OBJECTMAPPER)).readTree(json); 36 | } 37 | 38 | /** 39 | * Decode as per https://www.imsglobal.org/spec/ob/v3p0/#jwt-proof 40 | * @return The decoded JSON String 41 | */ 42 | public static JsonNode fromJwt(String jwt, RunContext context) throws Exception { 43 | List parts = Splitter.on('.').splitToList(jwt); 44 | if(parts.size() != 3) throw new IllegalArgumentException("invalid jwt"); 45 | 46 | final Decoder decoder = Base64.getUrlDecoder(); 47 | /* 48 | * For this step we are only deserializing the stored badge out of the payload. 49 | * The entire jwt is stored separately for signature verification later. 50 | */ 51 | String jwtPayload = new String(decoder.decode(parts.get(1))); 52 | 53 | //Deserialize and fetch the credential node from the object 54 | JsonNode outerPayload = fromString(jwtPayload, context); 55 | String nodeName = (String) context.get(Key.JWT_CREDENTIAL_NODE_NAME); 56 | if (isBlank(nodeName)) { 57 | return outerPayload; 58 | } 59 | JsonNode vcNode = outerPayload.get(nodeName); 60 | if (vcNode == null && (Boolean) context.get(Key.JWT_CREDENTIAL_ALLOW_WHOLE_PAYLOAD)) { 61 | return outerPayload; 62 | } 63 | 64 | return vcNode; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/payload/PayloadParserFactory.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.payload; 2 | 3 | import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; 4 | 5 | import java.util.List; 6 | 7 | import org.oneedtech.inspect.util.resource.Resource; 8 | 9 | /** 10 | * A factory to create PayloadParser instances for various resource types. 11 | * @author mgylling 12 | */ 13 | public class PayloadParserFactory { 14 | private static final Iterable parsers = List.of( 15 | new PngParser(), new SvgParser(), 16 | new JsonParser(), new JwtParser()); 17 | 18 | public static PayloadParser of(Resource resource) { 19 | checkNotNull(resource.getType()); 20 | for(PayloadParser cex : parsers) { 21 | if(cex.supports(resource.getType())) return cex; 22 | } 23 | throw new IllegalArgumentException(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ContextPropertyProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import org.oneedtech.inspect.core.probe.RunContext; 9 | import org.oneedtech.inspect.core.report.ReportItems; 10 | import org.oneedtech.inspect.vc.Credential.CredentialEnum; 11 | 12 | import com.fasterxml.jackson.databind.JsonNode; 13 | 14 | /** 15 | * A Probe that verifies a credential's context property. 16 | * 17 | * @author mgylling 18 | */ 19 | public class ContextPropertyProbe extends StringValuePropertyProbe { 20 | private final CredentialEnum type; 21 | 22 | public ContextPropertyProbe(CredentialEnum type) { 23 | super(ID, type.toString(), "@context"); 24 | this.type = checkNotNull(type); 25 | setValueValidations(this::validate); 26 | } 27 | 28 | @Override 29 | protected ReportItems reportForNonExistentProperty(JsonNode node, RunContext ctx) { 30 | return notRun("No @context property", ctx); 31 | } 32 | 33 | public ReportItems validate(List nodeValues, RunContext ctx) { 34 | if (!nodeValues.isEmpty()) { // empty context uri node: inline context 35 | List contextUris = type.getContextUris(); 36 | checkNotNull(contextUris); 37 | 38 | int pos = 0; 39 | List warnings = new ArrayList<>(); 40 | for (String uri : contextUris) { 41 | if ((nodeValues.size() < pos + 1) || !contains(uri, nodeValues.get(pos))) { 42 | return error("missing required @context uri " + uri + " at position " + (pos + 1), ctx); 43 | } 44 | if (!nodeValues.get(pos).equals(uri)) { 45 | warnings.add(warning("expected @context uri " + uri + " at position " + (pos + 1) + ", gotten " + nodeValues.get(pos).toString() + " instead", ctx)); 46 | } 47 | 48 | pos++; 49 | } 50 | if (!warnings.isEmpty()) { 51 | return new ReportItems(warnings); 52 | } 53 | } 54 | 55 | return success(ctx); 56 | } 57 | 58 | private boolean contains(String uri, String nodeValue) { 59 | // check equal case 60 | if (nodeValue.equals(uri)) { 61 | return true; 62 | } 63 | // check aliases 64 | if (type.getContextAliases().containsKey(uri)) { 65 | if (type.getContextAliases().get(uri).stream().anyMatch(alias -> nodeValue.equals(alias))) { 66 | return true; 67 | } 68 | } 69 | // check versioning 70 | if (type.getContextVersionPatterns().containsKey(uri)) { 71 | if (type.getContextVersionPatterns().get(uri).stream().anyMatch(version -> nodeValue.matches(version))) { 72 | return true; 73 | } 74 | } 75 | return false; 76 | } 77 | 78 | public static final String ID = ContextPropertyProbe.class.getSimpleName(); 79 | } 80 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/CredentialParseProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.Optional; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | import org.oneedtech.inspect.util.resource.Resource; 9 | import org.oneedtech.inspect.util.resource.ResourceType; 10 | import org.oneedtech.inspect.util.resource.detect.TypeDetector; 11 | import org.oneedtech.inspect.vc.Credential; 12 | import org.oneedtech.inspect.vc.VerifiableCredential; 13 | import org.oneedtech.inspect.vc.payload.PayloadParserFactory; 14 | 15 | /** 16 | * A probe that verifies that the incoming credential resource is of a recognized payload type 17 | * and if so extracts and stores the VC json data (a 'Credential' instance) 18 | * in the RunContext. 19 | * @author mgylling 20 | */ 21 | public class CredentialParseProbe extends Probe { 22 | 23 | @Override 24 | public ReportItems run(Resource resource, RunContext context) throws Exception { 25 | 26 | try { 27 | 28 | //TODO if .detect reads from a URIResource twice. Cache the resource on first call. 29 | 30 | Optional type = Optional.ofNullable(resource.getType()); 31 | if(type.isEmpty() || type.get() == ResourceType.UNKNOWN) { 32 | type = TypeDetector.detect(resource, true); 33 | if(type.isEmpty()) { 34 | //TODO if URI fetch, TypeDetector likely to fail 35 | System.err.println("typedetector fail: extend behavior here"); 36 | return fatal("Could not detect credential payload type", context); 37 | } else { 38 | resource.setType(type.get()); 39 | } 40 | } 41 | 42 | if(!VerifiableCredential.RECOGNIZED_PAYLOAD_TYPES.contains(type.get())) { 43 | return fatal("Payload type not supported: " + type.get().getName(), context); 44 | } 45 | 46 | Credential crd = PayloadParserFactory.of(resource).parse(resource, context); 47 | context.addGeneratedObject(crd); 48 | return success(this, context); 49 | 50 | } catch (Exception e) { 51 | return fatal("Error while parsing credential: " + e.getMessage(), context); 52 | } 53 | } 54 | 55 | public static final String ID = CredentialParseProbe.class.getSimpleName(); 56 | 57 | } 58 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EmbeddedProofModel.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.HexFormat; 4 | 5 | import org.oneedtech.inspect.core.probe.GeneratedObject; 6 | import org.oneedtech.inspect.vc.verification.URDNA2015Canonicalizer; 7 | 8 | public class EmbeddedProofModel extends GeneratedObject { 9 | public static final String ID = "vc.embedded.proof"; 10 | 11 | 12 | private final String ldProofWithoutProofValues; 13 | private final String jsonLdObjectWithoutProof; 14 | private final String canonicalizedLdProofWithoutProofValues; 15 | private final String canonicalizedJsonLdObjectWithoutProof; 16 | private final String canonicalizationResult; 17 | 18 | public EmbeddedProofModel(URDNA2015Canonicalizer canonicalizer) { 19 | super(ID, Type.EXTERNAL); 20 | this.ldProofWithoutProofValues = canonicalizer.getLdProofWithoutProofValues().toJson(true); 21 | this.jsonLdObjectWithoutProof = canonicalizer.getJsonLdObjectWithoutProof().toJson(true); 22 | this.canonicalizedLdProofWithoutProofValues = canonicalizer.getCanonicalizedLdProofWithoutProofValues(); 23 | this.canonicalizedJsonLdObjectWithoutProof = canonicalizer.getCanonicalizedJsonLdObjectWithoutProof(); 24 | this.canonicalizationResult = HexFormat.of().formatHex(canonicalizer.getCanonicalizationResult()); 25 | } 26 | 27 | public String getLdProofWithoutProofValues() { 28 | return ldProofWithoutProofValues; 29 | } 30 | 31 | public String getJsonLdObjectWithoutProof() { 32 | return jsonLdObjectWithoutProof; 33 | } 34 | 35 | public String getCanonicalizedLdProofWithoutProofValues() { 36 | return canonicalizedLdProofWithoutProofValues; 37 | } 38 | 39 | public String getCanonicalizedJsonLdObjectWithoutProof() { 40 | return canonicalizedJsonLdObjectWithoutProof; 41 | } 42 | 43 | public String getCanonicalizationResult() { 44 | return canonicalizationResult; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EmbeddedProofModelGenerator.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import org.oneedtech.inspect.core.probe.ObjectGenerator; 4 | import org.oneedtech.inspect.vc.verification.URDNA2015Canonicalizer; 5 | 6 | public class EmbeddedProofModelGenerator implements ObjectGenerator { 7 | private final EmbeddedProofModel model; 8 | 9 | public EmbeddedProofModelGenerator(URDNA2015Canonicalizer canonicalizer) { 10 | this.model = new EmbeddedProofModel(canonicalizer); 11 | } 12 | 13 | public EmbeddedProofModel getGeneratedObject() { 14 | return model; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/EvidenceProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.List; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | import org.oneedtech.inspect.vc.util.JsonNodeUtil; 9 | 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | 12 | public class EvidenceProbe extends Probe { 13 | public EvidenceProbe() { 14 | super(ID); 15 | } 16 | 17 | @Override 18 | public ReportItems run(JsonNode root, RunContext ctx) throws Exception { 19 | 20 | if (root.hasNonNull("evidence")) { 21 | /* 22 | * evidence is an array, so check type of each element 23 | */ 24 | List evidences = JsonNodeUtil.asNodeList(root.get("evidence")); 25 | for (JsonNode evidence : evidences) { 26 | // check that type contains "Evidence" 27 | if (!JsonNodeUtil.asStringList(evidence.get("type")).contains("Evidence")) { 28 | return error("evidence is not of type \"Evidence\"", ctx); 29 | } 30 | } 31 | } 32 | 33 | return success(ctx); 34 | } 35 | 36 | public static final String ID = EvidenceProbe.class.getSimpleName(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ExpirationProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.time.ZonedDateTime; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | import org.oneedtech.inspect.vc.Credential; 9 | 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | 12 | /** 13 | * A Probe that verifies a credential's expiration status 14 | * @author mgylling 15 | */ 16 | public class ExpirationProbe extends Probe { 17 | 18 | public ExpirationProbe() { 19 | super(ID); 20 | } 21 | 22 | @Override 23 | public ReportItems run(Credential crd, RunContext ctx) throws Exception { 24 | /* 25 | * If the AchievementCredential or EndorsementCredential has an “expirationDate” or "validUntil" property 26 | * and the expiration date is prior to the current date, the credential has expired. 27 | */ 28 | JsonNode node = crd.getJson().get(crd.getExpiresAtPropertyName()); 29 | if(node != null && !node.isNull()) { 30 | try { 31 | ZonedDateTime expirationDate = ZonedDateTime.parse(node.textValue()); 32 | if (ZonedDateTime.now().isAfter(expirationDate)) { 33 | return fatal("The credential has expired (expiration date or validUntil was " + node.asText() + ").", ctx); 34 | } 35 | } catch (Exception e) { 36 | return exception("Error while checking expirationDate or validUntil: " + e.getMessage(), ctx.getResource()); 37 | } 38 | } 39 | return success(ctx); 40 | } 41 | 42 | public static final String ID = ExpirationProbe.class.getSimpleName(); 43 | } 44 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/InlineJsonSchemaProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | 9 | import org.oneedtech.inspect.core.probe.Probe; 10 | import org.oneedtech.inspect.core.probe.RunContext; 11 | import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe; 12 | import org.oneedtech.inspect.core.report.ReportItems; 13 | import org.oneedtech.inspect.schema.SchemaKey; 14 | import org.oneedtech.inspect.vc.VerifiableCredential; 15 | import org.oneedtech.inspect.vc.util.JsonNodeUtil; 16 | 17 | import com.fasterxml.jackson.databind.JsonNode; 18 | import com.fasterxml.jackson.databind.node.ArrayNode; 19 | 20 | /** 21 | * Detect inline schemas in a credential and run them. 22 | * @author mgylling 23 | */ 24 | public class InlineJsonSchemaProbe extends Probe { 25 | private static final Set types = Set.of("1EdTechJsonSchemaValidator2019"); 26 | private SchemaKey skip; 27 | 28 | public InlineJsonSchemaProbe() { 29 | super(ID); 30 | } 31 | 32 | public InlineJsonSchemaProbe(SchemaKey skip) { 33 | super(ID); 34 | this.skip = skip; 35 | } 36 | 37 | @Override 38 | public ReportItems run(JsonNode root, RunContext ctx) throws Exception { 39 | List accumulator = new ArrayList<>(); 40 | Set ioErrors = new HashSet<>(); 41 | 42 | //note - we don't get deep nested ones in e.g. EndorsementCredential 43 | JsonNode credentialSchemaNode = root.get("credentialSchema"); 44 | if(credentialSchemaNode == null) return success(ctx); 45 | 46 | List schemas = JsonNodeUtil.asNodeList(credentialSchemaNode); 47 | 48 | for(JsonNode schemaNode : schemas) { 49 | JsonNode typeNode = schemaNode.get("type"); 50 | if(typeNode == null || !types.contains(typeNode.asText())) continue; 51 | JsonNode idNode = schemaNode.get("id"); 52 | if(idNode == null) continue; 53 | String id = idNode.asText().strip(); 54 | if(ioErrors.contains(id)) continue; 55 | if(equals(skip, id)) continue; 56 | try { 57 | accumulator.add(new JsonSchemaProbe(id).run(root, ctx)); 58 | } catch (Exception e) { 59 | if(!ioErrors.contains(id)) { 60 | ioErrors.add(id); 61 | accumulator.add(error("Could not read schema resource " + id, ctx)); 62 | } 63 | } 64 | } 65 | 66 | return new ReportItems(accumulator); 67 | } 68 | 69 | private boolean equals(SchemaKey key, String id) { 70 | if(key == null) return false; 71 | return key.getCanonicalURI().equals(id); 72 | } 73 | 74 | public static final String ID = InlineJsonSchemaProbe.class.getSimpleName(); 75 | } 76 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/IssuanceProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.time.ZonedDateTime; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | import org.oneedtech.inspect.vc.Credential; 9 | 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | 12 | /** 13 | * A Probe that verifies a credential's issuance status 14 | * @author mgylling 15 | */ 16 | public class IssuanceProbe extends Probe { 17 | 18 | public IssuanceProbe() { 19 | super(ID); 20 | } 21 | 22 | @Override 23 | public ReportItems run(Credential crd, RunContext ctx) throws Exception { 24 | /* 25 | * If the AchievementCredential or EndorsementCredential “issuanceDate” or "validFrom" 26 | * property after the current date, the credential is not yet valid. 27 | */ 28 | JsonNode node = crd.getJson().get(crd.getIssuedOnPropertyName()); 29 | if(node != null) { 30 | try { 31 | ZonedDateTime issuanceDate = ZonedDateTime.parse(node.textValue()); 32 | if (issuanceDate.isAfter(ZonedDateTime.now())) { 33 | return fatal("The credential is not yet issued or valid (issuance date or validFrom is " + node.asText() + ").", ctx); 34 | } 35 | } catch (Exception e) { 36 | return exception("Error while checking issuanceDate or ValidFrom: " + e.getMessage(), ctx.getResource()); 37 | } 38 | } 39 | return success(ctx); 40 | } 41 | 42 | public static final String ID = IssuanceProbe.class.getSimpleName(); 43 | } 44 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/IssuerProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.net.URI; 4 | import java.util.List; 5 | 6 | import org.oneedtech.inspect.core.probe.Probe; 7 | import org.oneedtech.inspect.core.probe.RunContext; 8 | import org.oneedtech.inspect.core.report.ReportItems; 9 | import org.oneedtech.inspect.util.resource.UriResource; 10 | import org.oneedtech.inspect.vc.util.JsonNodeUtil; 11 | 12 | import com.fasterxml.jackson.databind.JsonNode; 13 | 14 | public class IssuerProbe extends Probe { 15 | public IssuerProbe() { 16 | super(ID); 17 | } 18 | 19 | @Override 20 | public ReportItems run(JsonNode root, RunContext ctx) throws Exception { 21 | JsonNode issuer = root.get("issuer"); 22 | if(issuer == null) return error("no issuer node found", ctx); 23 | 24 | // check that type contains "Profile" 25 | if (!JsonNodeUtil.asStringList(issuer.get("type")).contains("Profile")) { 26 | return error("issuer is not of type \"Profile\"", ctx); 27 | } 28 | 29 | // check url is accessible 30 | if (issuer.hasNonNull("url")) { 31 | try { 32 | UriResource urlResource = new UriResource(new URI(issuer.get("url").asText().strip())); 33 | if (!urlResource.exists()) { 34 | return warning("url \"" + issuer.get("url").asText().strip() + "\" in issuer is not accessible", ctx); 35 | } 36 | } catch (Exception e) { 37 | return warning("url \"" + issuer.get("url").asText().strip() + "\" in issuer is not accessible", ctx); 38 | } 39 | } 40 | 41 | // check other identifier 42 | if (issuer.hasNonNull("otherIdentifier")) { 43 | List otherIdentifiers = JsonNodeUtil.asNodeList(issuer.get("otherIdentifier")); 44 | for (JsonNode otherIdentifier : otherIdentifiers) { 45 | // check that type contains "IdentifierEntry" 46 | if (!JsonNodeUtil.asStringList(otherIdentifier.get("type")).contains("IdentifierEntry")) { 47 | return error("otherIdentifier in issuer is not of type \"IdentifierEntry\"", ctx); 48 | } 49 | } 50 | } 51 | 52 | // check parent issuer 53 | if (issuer.hasNonNull("parentOrg")) { 54 | JsonNode parentOrg = issuer.get("parentOrg"); 55 | // check that type contains "Profile" 56 | if (!JsonNodeUtil.asStringList(parentOrg.get("type")).contains("Profile")) { 57 | return error("parentOrg in issuer is not of type \"Profile\"", ctx); 58 | } 59 | } 60 | 61 | return success(ctx); 62 | } 63 | 64 | public static final String ID = IssuerProbe.class.getSimpleName(); 65 | 66 | } 67 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/JsonSchemasProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.stream.Collectors; 4 | import java.util.stream.StreamSupport; 5 | 6 | import org.oneedtech.inspect.core.probe.Outcome; 7 | import org.oneedtech.inspect.core.probe.Probe; 8 | import org.oneedtech.inspect.core.probe.RunContext; 9 | import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe; 10 | import org.oneedtech.inspect.core.report.ReportItem; 11 | import org.oneedtech.inspect.core.report.ReportItems; 12 | import org.oneedtech.inspect.schema.SchemaKey; 13 | import org.oneedtech.inspect.vc.VerifiableCredential; 14 | 15 | public class JsonSchemasProbe extends Probe { 16 | private SchemaKey key; 17 | 18 | public JsonSchemasProbe(SchemaKey key) { 19 | this.key = key; 20 | } 21 | 22 | @Override 23 | public ReportItems run(VerifiableCredential cred, RunContext ctx) throws Exception { 24 | 25 | // main run 26 | JsonSchemaProbe jsonSchemaProbe = new JsonSchemaProbe(key); 27 | ReportItems report = jsonSchemaProbe.run(cred.getJson(), ctx); 28 | 29 | if (report.asBoolean()) { 30 | return report; 31 | } 32 | 33 | // aliases run 34 | if (key.getAliases().isPresent()) { 35 | for (SchemaKey alias : key.getAliases().get()) { 36 | jsonSchemaProbe = new JsonSchemaProbe(alias); 37 | ReportItems newReport = jsonSchemaProbe.run(cred.getJson(), ctx); 38 | 39 | if (newReport.asBoolean()) { 40 | // return old errors as warnings 41 | return new ReportItems( 42 | StreamSupport.stream(report.spliterator(), false) 43 | .map( 44 | item -> 45 | new ReportItem.Builder(this) 46 | .msg( 47 | "JSON-LD schema validation succeed. However, Plain JSON schema" 48 | + " validation failed, so it could have an impact when working with" 49 | + " plain JSON platforms. Error:" 50 | + item.getMessage()) 51 | .loc(item.getLocation()) 52 | .outcome(Outcome.WARNING) 53 | .build()) 54 | .collect(Collectors.toUnmodifiableList())); 55 | } 56 | } 57 | 58 | } 59 | 60 | return report; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/PropertyProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.function.BiFunction; 4 | 5 | import org.oneedtech.inspect.core.probe.Probe; 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | 9 | import com.fasterxml.jackson.databind.JsonNode; 10 | 11 | public class PropertyProbe extends Probe { 12 | private final String propertyName; 13 | private BiFunction validations; 14 | 15 | public PropertyProbe(String id, String typeName, String propertyName) { 16 | super(id, typeName, propertyName); 17 | this.propertyName = propertyName; 18 | this.validations = this::defaultValidation; 19 | } 20 | 21 | public void setValidations(BiFunction validations) { 22 | this.validations = validations; 23 | } 24 | 25 | @Override 26 | public ReportItems run(JsonNode root, RunContext ctx) throws Exception { 27 | JsonNode propertyNode = root.get(propertyName); 28 | if (propertyNode == null) { 29 | return reportForNonExistentProperty(root, ctx); 30 | } 31 | 32 | return validations.apply(propertyNode, ctx); 33 | } 34 | 35 | protected ReportItems reportForNonExistentProperty(JsonNode node, RunContext ctx) { 36 | return fatal("No " + propertyName + " property", ctx); 37 | } 38 | 39 | private ReportItems defaultValidation(JsonNode node, RunContext ctx) { 40 | return success(ctx); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/RunContextKey.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | public class RunContextKey { 4 | public static final String DID_RESOLVER = "context.key.vc.didresolver"; 5 | } 6 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/StringValuePropertyProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import java.util.List; 4 | import java.util.function.BiFunction; 5 | 6 | import org.oneedtech.inspect.core.probe.RunContext; 7 | import org.oneedtech.inspect.core.report.ReportItems; 8 | import org.oneedtech.inspect.vc.util.JsonNodeUtil; 9 | 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | 12 | public class StringValuePropertyProbe extends PropertyProbe { 13 | private BiFunction, RunContext, ReportItems> valueValidations; 14 | 15 | public StringValuePropertyProbe(String id, String credentialType, String propertyName) { 16 | super(id, credentialType, propertyName); 17 | this.valueValidations = this::defaultValidation; 18 | super.setValidations(this::nodeValidation); 19 | } 20 | 21 | public void setValueValidations(BiFunction, RunContext, ReportItems> validations) { 22 | this.valueValidations = validations; 23 | } 24 | 25 | private ReportItems nodeValidation(JsonNode node, RunContext ctx) { 26 | List values = JsonNodeUtil.asStringList(node); 27 | return valueValidations.apply(values, ctx); 28 | } 29 | 30 | private ReportItems defaultValidation(List nodeValues, RunContext ctx) { 31 | return success(ctx); 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe; 2 | 3 | import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | import org.oneedtech.inspect.core.probe.RunContext; 9 | import org.oneedtech.inspect.core.report.ReportItems; 10 | import org.oneedtech.inspect.vc.Credential.CredentialEnum; 11 | 12 | /** 13 | * A Probe that verifies a credential's type property. 14 | * 15 | * @author mgylling 16 | */ 17 | public class TypePropertyProbe extends StringValuePropertyProbe { 18 | private final CredentialEnum expected; 19 | 20 | public TypePropertyProbe(CredentialEnum expected) { 21 | super(ID, expected.toString(), "type"); 22 | this.expected = checkNotNull(expected); 23 | this.setValueValidations(this::validate); 24 | } 25 | 26 | public ReportItems validate(List values, RunContext ctx) { 27 | List requiredTypeValues = expected.getRequiredTypeValues(); 28 | if (!requiredTypeValues.isEmpty()) { 29 | if (!requiredTypeValues.stream().allMatch(requiredValue -> values.contains(requiredValue))) { 30 | return fatal(formatMessage(requiredTypeValues), ctx); 31 | } 32 | } 33 | 34 | if (expected.isAllowedTypeValuesRequired()) { 35 | List allowedValues = expected.getAllowedTypeValues(); 36 | if (allowedValues.isEmpty()) { 37 | return fatal("The type property is invalid", ctx); 38 | } 39 | if (!values.stream().anyMatch(v -> allowedValues.contains(v))) { 40 | return fatal(formatMessage(values), ctx); 41 | } 42 | } 43 | 44 | return success(ctx); 45 | } 46 | 47 | private String formatMessage(List values) { 48 | StringBuffer buffer = new StringBuffer("The type property does not contain "); 49 | if (values.size() > 1) { 50 | buffer.append("one of"); 51 | buffer.append(values.stream() 52 | .map(value -> "'" + value + "'") 53 | .collect(Collectors.joining(" or ")) 54 | ); 55 | 56 | } else { 57 | buffer.append("the entry '" + values.get(0) + "'"); 58 | } 59 | return buffer.toString(); 60 | } 61 | 62 | public static final String ID = TypePropertyProbe.class.getSimpleName(); 63 | } 64 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/did/DidResolution.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe.did; 2 | 3 | public class DidResolution { 4 | private final String publicKeyMultibase; 5 | private final String publicKeyJwk; 6 | private final String controller; 7 | 8 | DidResolution(Builder builder) { 9 | this.publicKeyMultibase = builder.publicKeyMultibase; 10 | this.publicKeyJwk = builder.publicKeyJwk; 11 | this.controller = builder.controller; 12 | } 13 | 14 | public String getPublicKeyMultibase() { 15 | return publicKeyMultibase; 16 | } 17 | 18 | public String getPublicKeyJwk() { 19 | return publicKeyJwk; 20 | } 21 | 22 | public String getController() { 23 | return controller; 24 | } 25 | 26 | public static Builder builder() { 27 | return new Builder(); 28 | } 29 | 30 | // builder 31 | public static class Builder { 32 | String publicKeyMultibase; 33 | String publicKeyJwk; 34 | String controller; 35 | 36 | public Builder publicKeyMultibase(String publicKeyMultibase) { 37 | this.publicKeyMultibase = publicKeyMultibase; 38 | return this; 39 | } 40 | 41 | public Builder publicKeyJwk(String publicKeyJwk) { 42 | this.publicKeyJwk = publicKeyJwk; 43 | return this; 44 | } 45 | 46 | public Builder controller(String controller) { 47 | this.controller = controller; 48 | return this; 49 | } 50 | 51 | public DidResolution build() { 52 | return new DidResolution(this); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/did/DidResolutionException.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe.did; 2 | 3 | public class DidResolutionException extends Exception { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public DidResolutionException(String message) { 8 | super(message); 9 | } 10 | 11 | public DidResolutionException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/did/DidResolver.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe.did; 2 | 3 | import java.net.URI; 4 | 5 | import com.apicatalog.jsonld.loader.DocumentLoader; 6 | 7 | public interface DidResolver { 8 | DidResolution resolve(URI did, DocumentLoader documentLoader) throws DidResolutionException; 9 | } 10 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/validation/ValidationIssuerPropertyProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe.validation; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | import org.oneedtech.inspect.core.probe.RunContext; 6 | import org.oneedtech.inspect.core.report.ReportItems; 7 | import org.oneedtech.inspect.vc.Validation; 8 | import org.oneedtech.inspect.vc.Validation.MessageLevel; 9 | 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | 12 | /** 13 | * Issuer properties additional validator for Open Badges 2.0 14 | * Maps to "ISSUER_PROPERTY_DEPENDENCIES" task in python implementation 15 | * @author xaracil 16 | */ 17 | public class ValidationIssuerPropertyProbe extends ValidationPropertyProbe { 18 | 19 | public ValidationIssuerPropertyProbe(String credentialType, Validation validation) { 20 | this(credentialType, validation, true); 21 | } 22 | 23 | public ValidationIssuerPropertyProbe(String credentialType, Validation validation, boolean fullValidate) { 24 | super(ID, credentialType, validation, fullValidate); 25 | } 26 | 27 | @Override 28 | protected ReportItems validate(JsonNode node, RunContext ctx) { 29 | if (!Pattern.compile("^http(s)?://.+", Pattern.CASE_INSENSITIVE).matcher(node.asText()).matches()) { 30 | return buildResponse("Issuer Profile " + node.toString() + " not hosted with HTTP-based identifier." + 31 | "Many platforms can only handle HTTP(s)-hosted issuers.", ctx); 32 | } 33 | return success(ctx); 34 | } 35 | 36 | private ReportItems buildResponse(String msg, RunContext ctx) { 37 | if (validation.getMessageLevel() == MessageLevel.Warning) { 38 | return warning(msg, ctx); 39 | } 40 | return error(msg, ctx); 41 | } 42 | 43 | public static final String ID = ValidationIssuerPropertyProbe.class.getSimpleName(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/validation/ValidationPropertyProbeFactory.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe.validation; 2 | 3 | import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; 4 | 5 | import org.oneedtech.inspect.vc.Assertion.ValueType; 6 | import org.oneedtech.inspect.vc.Credential.CredentialEnum; 7 | import org.oneedtech.inspect.vc.Assertion; 8 | import org.oneedtech.inspect.vc.Validation; 9 | 10 | /** 11 | * Factory for ValidationPropertyProbes 12 | * @author xaracil 13 | */ 14 | public class ValidationPropertyProbeFactory { 15 | public static ValidationPropertyProbe of(String type, Validation validation) { 16 | return of(type, validation, true); 17 | } 18 | 19 | public static ValidationPropertyProbe of(String type, Validation validation, boolean fullValidate) { 20 | checkNotNull(validation.getType()); 21 | if (validation.getType() == ValueType.RDF_TYPE) { 22 | return new ValidationRdfTypePropertyProbe(type, validation, fullValidate); 23 | } 24 | if (validation.getType() == ValueType.IMAGE) { 25 | return new ValidationImagePropertyProbe(type, validation); 26 | } 27 | if (validation.getType() == ValueType.ISSUER) { 28 | return new ValidationIssuerPropertyProbe(type, validation); 29 | } 30 | return new ValidationPropertyProbe(type, validation, fullValidate); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/validation/ValidationRdfTypePropertyProbe.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.probe.validation; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import org.oneedtech.inspect.core.probe.Outcome; 7 | import org.oneedtech.inspect.core.probe.RunContext; 8 | import org.oneedtech.inspect.core.report.ReportItems; 9 | import org.oneedtech.inspect.vc.Validation; 10 | import org.oneedtech.inspect.vc.util.JsonNodeUtil; 11 | 12 | import com.fasterxml.jackson.databind.JsonNode; 13 | import com.fasterxml.jackson.databind.node.JsonNodeFactory; 14 | import com.fasterxml.jackson.databind.node.TextNode; 15 | 16 | /** 17 | * Validator for properties of type ValueType.RDF_TYPE in Open Badges 2.0 types 18 | * Maps to "VALIDATE_RDF_TYPE_PROPERTY" task in python implementation 19 | * @author xaracil 20 | */ 21 | public class ValidationRdfTypePropertyProbe extends ValidationPropertyProbe { 22 | public ValidationRdfTypePropertyProbe(String credentialType, Validation validation ) { 23 | this(credentialType, validation, true); 24 | } 25 | 26 | public ValidationRdfTypePropertyProbe(String credentialType, Validation validation, boolean fullValidate) { 27 | super(ID, credentialType, validation, fullValidate); 28 | } 29 | 30 | @Override 31 | protected ReportItems reportForNonExistentProperty(JsonNode node, RunContext ctx) { 32 | if (!validation.isRequired()) { 33 | // check if we have a default type 34 | if (validation.getDefaultType() != null) { 35 | JsonNodeFactory factory = JsonNodeFactory.instance; 36 | TextNode textNode = factory.textNode(validation.getDefaultType()); 37 | // validate with default value 38 | return validate(textNode, ctx); 39 | } 40 | } 41 | 42 | // if we're not doing a full validation and it's not and id field, pass 43 | if (!fullValidate && !validation.getName().equals("id")) { 44 | return success(ctx); 45 | } 46 | return error("Required property " + validation.getName() + " not present in " + node.toPrettyString(), ctx); 47 | } 48 | 49 | @Override 50 | protected ReportItems validate(JsonNode node, RunContext ctx) { 51 | ReportItems result = super.validate(node, ctx); 52 | if (result.contains(Outcome.ERROR, Outcome.FATAL)) { 53 | return result; 54 | } 55 | if (!validation.getMustContainOne().isEmpty()) { 56 | List values = JsonNodeUtil.asStringList(node); 57 | boolean valid = validation.getMustContainOne().stream().anyMatch(type -> values.contains(type)); 58 | if (!valid) { 59 | return new ReportItems(List.of(result, 60 | fatal("Node " + validation.getName() + " of type " + node.asText() 61 | + " does not have type among allowed values (" + validation.getMustContainOne().stream().collect(Collectors.joining(",")) + ")", ctx) 62 | )); 63 | } 64 | } 65 | return new ReportItems(List.of(result, success(ctx))); 66 | } 67 | 68 | public static final String ID = ValidationRdfTypePropertyProbe.class.getSimpleName(); 69 | } 70 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/resource/DefaultUriResourceFactory.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.resource; 2 | 3 | import java.net.URI; 4 | import java.net.URISyntaxException; 5 | 6 | import org.oneedtech.inspect.util.resource.UriResource; 7 | 8 | /** 9 | * Default factory for URIResources 10 | * @author xaracil 11 | */ 12 | public class DefaultUriResourceFactory implements UriResourceFactory { 13 | 14 | @Override 15 | public UriResource of(String uri) throws URISyntaxException { 16 | return new UriResource(new URI(uri)); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/resource/UriResourceFactory.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.resource; 2 | 3 | import java.net.URISyntaxException; 4 | 5 | import org.oneedtech.inspect.util.resource.UriResource; 6 | 7 | /** 8 | * Factory interface for URI resources 9 | * @author xaracil 10 | */ 11 | public interface UriResourceFactory { 12 | public UriResource of(String uri) throws URISyntaxException; 13 | } 14 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/util/JsonNodeUtil.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | import java.util.stream.StreamSupport; 7 | 8 | import org.oneedtech.inspect.core.probe.json.JsonPathEvaluator; 9 | 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | import com.fasterxml.jackson.databind.node.ArrayNode; 12 | 13 | /** 14 | * Json node utilities. 15 | * @author mgylling 16 | */ 17 | public class JsonNodeUtil { 18 | 19 | public static List asNodeList(JsonNode root, String jsonPath, JsonPathEvaluator evaluator) { 20 | List list = new ArrayList<>(); 21 | ArrayNode array = evaluator.eval(jsonPath, root); 22 | for(JsonNode node : array) { 23 | if(!(node instanceof ArrayNode)) { 24 | list.add(node); 25 | } else { 26 | ArrayNode values = (ArrayNode) node; 27 | for(JsonNode value : values) { 28 | list.add(value); 29 | } 30 | } 31 | } 32 | return list; 33 | } 34 | 35 | public static List asStringList(JsonNode node) { 36 | if(!(node instanceof ArrayNode)) { 37 | if (node.isObject()) { 38 | return List.of(); 39 | } 40 | return List.of(node.asText()); 41 | } else { 42 | ArrayNode arrayNode = (ArrayNode)node; 43 | return StreamSupport 44 | .stream(arrayNode.spliterator(), false) 45 | .map(n->n.asText().strip()) 46 | .collect(Collectors.toList()); 47 | } 48 | } 49 | 50 | public static List asNodeList(JsonNode node) { 51 | if(node == null) return null; 52 | if(!(node instanceof ArrayNode)) { 53 | return List.of(node); 54 | } else { 55 | ArrayNode arrayNode = (ArrayNode)node; 56 | return StreamSupport 57 | .stream(arrayNode.spliterator(), false) 58 | .collect(Collectors.toList()); 59 | } 60 | } 61 | 62 | public static boolean isNotEmpty(JsonNode node) { 63 | return node != null && !node.isNull() && !node.isEmpty(); 64 | } 65 | 66 | public static boolean isEmpty(JsonNode node) { 67 | return node == null || node.isNull() || node.isEmpty(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/Ed25519Signature2022LdVerifier.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import com.danubetech.keyformats.crypto.ByteVerifier; 4 | import com.danubetech.keyformats.crypto.impl.Ed25519_EdDSA_PublicKeyVerifier; 5 | import com.danubetech.keyformats.jose.JWSAlgorithm; 6 | import info.weboftrust.ldsignatures.LdProof; 7 | import info.weboftrust.ldsignatures.verifier.LdVerifier; 8 | import io.ipfs.multibase.Multibase; 9 | 10 | import java.security.GeneralSecurityException; 11 | 12 | public class Ed25519Signature2022LdVerifier extends LdVerifier { 13 | 14 | public Ed25519Signature2022LdVerifier(ByteVerifier verifier) { 15 | 16 | super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer(Eddsa2022LdProof.builder())); 17 | } 18 | 19 | public Ed25519Signature2022LdVerifier(byte[] publicKey) { 20 | 21 | this(new Ed25519_EdDSA_PublicKeyVerifier(publicKey)); 22 | } 23 | 24 | public Ed25519Signature2022LdVerifier() { 25 | 26 | this((ByteVerifier) null); 27 | } 28 | 29 | public static boolean verify(byte[] signingInput, LdProof ldProof, ByteVerifier verifier) throws GeneralSecurityException { 30 | 31 | // verify 32 | 33 | String proofValue = ldProof.getProofValue(); 34 | if (proofValue == null) throw new GeneralSecurityException("No 'proofValue' in proof."); 35 | 36 | boolean verify; 37 | 38 | byte[] bytes = Multibase.decode(proofValue); 39 | verify = verifier.verify(signingInput, bytes, JWSAlgorithm.EdDSA); 40 | 41 | // done 42 | 43 | return verify; 44 | } 45 | 46 | @Override 47 | public boolean verify(byte[] signingInput, LdProof ldProof) throws GeneralSecurityException { 48 | 49 | return verify(signingInput, ldProof, this.getVerifier()); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/Ed25519Signature2022SignatureSuite.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import com.danubetech.keyformats.jose.JWSAlgorithm; 4 | import com.danubetech.keyformats.jose.KeyTypeName; 5 | import info.weboftrust.ldsignatures.suites.SignatureSuite; 6 | 7 | import java.net.URI; 8 | import java.util.Arrays; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class Ed25519Signature2022SignatureSuite extends SignatureSuite { 13 | 14 | Ed25519Signature2022SignatureSuite() { 15 | 16 | super( 17 | "DataIntegrityProof", 18 | URI.create("https://www.w3.org/TR/vc-di-eddsa"), 19 | URI.create("https://w3id.org/security#URDNA2015"), 20 | URI.create("http://w3id.org/digests#sha256"), 21 | URI.create("http://w3id.org/security#ed25519"), 22 | List.of(KeyTypeName.Ed25519), 23 | Map.of(KeyTypeName.Ed25519, List.of(JWSAlgorithm.EdDSA)), 24 | Arrays.asList(LDSecurityContexts.JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1, 25 | info.weboftrust.ldsignatures.jsonld.LDSecurityContexts.JSONLD_CONTEXT_W3ID_SECURITY_V3)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/Ed25519Signature2022VCDM20LdVerifier.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import com.danubetech.keyformats.crypto.ByteVerifier; 4 | import com.danubetech.keyformats.crypto.impl.Ed25519_EdDSA_PublicKeyVerifier; 5 | import com.danubetech.keyformats.jose.JWSAlgorithm; 6 | import info.weboftrust.ldsignatures.LdProof; 7 | import info.weboftrust.ldsignatures.verifier.LdVerifier; 8 | import io.ipfs.multibase.Multibase; 9 | 10 | import java.security.GeneralSecurityException; 11 | 12 | public class Ed25519Signature2022VCDM20LdVerifier extends LdVerifier { 13 | 14 | public Ed25519Signature2022VCDM20LdVerifier(ByteVerifier verifier) { 15 | 16 | super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer(Eddsa2022v2LdProof.builder())); 17 | } 18 | 19 | public Ed25519Signature2022VCDM20LdVerifier(byte[] publicKey) { 20 | 21 | this(new Ed25519_EdDSA_PublicKeyVerifier(publicKey)); 22 | } 23 | 24 | public Ed25519Signature2022VCDM20LdVerifier() { 25 | 26 | this((ByteVerifier) null); 27 | } 28 | 29 | public static boolean verify(byte[] signingInput, LdProof ldProof, ByteVerifier verifier) throws GeneralSecurityException { 30 | 31 | // verify 32 | 33 | String proofValue = ldProof.getProofValue(); 34 | if (proofValue == null) throw new GeneralSecurityException("No 'proofValue' in proof."); 35 | 36 | boolean verify; 37 | 38 | byte[] bytes = Multibase.decode(proofValue); 39 | verify = verifier.verify(signingInput, bytes, JWSAlgorithm.EdDSA); 40 | 41 | // done 42 | 43 | return verify; 44 | } 45 | 46 | @Override 47 | public boolean verify(byte[] signingInput, LdProof ldProof) throws GeneralSecurityException { 48 | 49 | return verify(signingInput, ldProof, this.getVerifier()); 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/Eddsa2022LdProof.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import java.net.URI; 4 | 5 | import com.apicatalog.jsonld.loader.DocumentLoader; 6 | 7 | import foundation.identity.jsonld.JsonLDObject; 8 | import foundation.identity.jsonld.JsonLDUtils; 9 | import info.weboftrust.ldsignatures.LdProof; 10 | 11 | public class Eddsa2022LdProof extends LdProof { 12 | public static final URI[] DEFAULT_JSONLD_CONTEXTS = { LDSecurityContexts.JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1 }; 13 | public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = LDSecurityContexts.DOCUMENT_LOADER; 14 | 15 | public static Builder> builder() { 16 | return new Builder(new Eddsa2022LdProof()); 17 | } 18 | 19 | /* 20 | * Factory methods 21 | */ 22 | 23 | public static class Builder> extends LdProof.Builder { 24 | 25 | private boolean addCryptosuite = true; 26 | 27 | public Builder(LdProof jsonLdObject) { 28 | super(jsonLdObject); 29 | } 30 | 31 | @Override 32 | public B base(JsonLDObject base) { 33 | addCryptosuite = false; 34 | return super.base(base); 35 | } 36 | 37 | @Override 38 | public LdProof build() { 39 | super.build(); 40 | 41 | if (addCryptosuite) { 42 | JsonLDUtils.jsonLdAdd(this.jsonLdObject, "cryptosuite", "eddsa-rdfc-2022"); 43 | } 44 | 45 | return (LdProof) this.jsonLdObject; 46 | 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/Eddsa2022v2LdProof.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import java.net.URI; 4 | 5 | import com.apicatalog.jsonld.loader.DocumentLoader; 6 | 7 | import foundation.identity.jsonld.JsonLDObject; 8 | import foundation.identity.jsonld.JsonLDUtils; 9 | import info.weboftrust.ldsignatures.LdProof; 10 | 11 | public class Eddsa2022v2LdProof extends LdProof { 12 | public static final URI[] DEFAULT_JSONLD_CONTEXTS = { LDSecurityContexts.JSONLD_CONTEXT_W3ID_VC_V2 }; 13 | public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = LDSecurityContexts.DOCUMENT_LOADER; 14 | 15 | public static Builder> builder() { 16 | return new Builder(new Eddsa2022v2LdProof()); 17 | } 18 | 19 | /* 20 | * Factory methods 21 | */ 22 | 23 | public static class Builder> extends LdProof.Builder { 24 | 25 | private boolean addCryptosuite = true; 26 | 27 | public Builder(LdProof jsonLdObject) { 28 | super(jsonLdObject); 29 | } 30 | 31 | @Override 32 | public B base(JsonLDObject base) { 33 | addCryptosuite = false; 34 | return super.base(base); 35 | } 36 | 37 | @Override 38 | public LdProof build() { 39 | super.build(); 40 | 41 | if (addCryptosuite) { 42 | JsonLDUtils.jsonLdAdd(this.jsonLdObject, "cryptosuite", "eddsa-rdfc-2022"); 43 | } 44 | 45 | return (LdProof) this.jsonLdObject; 46 | 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/LDSecurityContexts.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import java.io.IOException; 4 | import java.net.URI; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import com.apicatalog.jsonld.JsonLdError; 9 | import com.apicatalog.jsonld.document.JsonDocument; 10 | import com.apicatalog.jsonld.http.media.MediaType; 11 | import com.apicatalog.jsonld.loader.DocumentLoader; 12 | import com.google.common.io.Resources; 13 | 14 | import foundation.identity.jsonld.ConfigurableDocumentLoader; 15 | 16 | public class LDSecurityContexts { 17 | public static final URI JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1 = URI.create("https://w3id.org/security/data-integrity/v1"); 18 | public static final URI JSONLD_CONTEXT_W3ID_VC_V2 = URI.create("https://www.w3.org/ns/credentials/v2"); 19 | 20 | public static final Map CONTEXTS; 21 | public static final DocumentLoader DOCUMENT_LOADER; 22 | 23 | static { 24 | 25 | try { 26 | 27 | CONTEXTS = new HashMap<>(); 28 | 29 | CONTEXTS.putAll(info.weboftrust.ldsignatures.jsonld.LDSecurityContexts.CONTEXTS); 30 | 31 | CONTEXTS.put(JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1, 32 | JsonDocument.of(MediaType.JSON_LD, Resources.getResource("contexts/data-integrity-v1.jsonld").openStream())); 33 | CONTEXTS.put(JSONLD_CONTEXT_W3ID_VC_V2, 34 | JsonDocument.of(MediaType.JSON_LD, Resources.getResource("contexts/credentials-v2.jsonld").openStream())); 35 | 36 | for (Map.Entry context : CONTEXTS.entrySet()) { 37 | context.getValue().setDocumentUrl(context.getKey()); 38 | } 39 | } catch (JsonLdError | IOException ex) { 40 | 41 | throw new ExceptionInInitializerError(ex); 42 | } 43 | 44 | DOCUMENT_LOADER = new ConfigurableDocumentLoader(CONTEXTS); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/SignatureSuites.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | public class SignatureSuites { 4 | public static final Ed25519Signature2022SignatureSuite SIGNATURE_SUITE_ED25519SIGNATURE2022 = new Ed25519Signature2022SignatureSuite(); 5 | } 6 | -------------------------------------------------------------------------------- /inspector-vc/src/main/java/org/oneedtech/inspect/vc/verification/URDNA2015Canonicalizer.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.verification; 2 | 3 | import java.io.IOException; 4 | import java.security.GeneralSecurityException; 5 | import java.util.List; 6 | 7 | import foundation.identity.jsonld.JsonLDException; 8 | import foundation.identity.jsonld.JsonLDObject; 9 | import info.weboftrust.ldsignatures.LdProof; 10 | import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer; 11 | import info.weboftrust.ldsignatures.util.SHAUtil; 12 | 13 | public class URDNA2015Canonicalizer extends Canonicalizer { 14 | 15 | private LdProof.Builder proofBuilder; 16 | 17 | // expose intermediate values for reporting 18 | private LdProof ldProofWithoutProofValues; 19 | private JsonLDObject jsonLdObjectWithoutProof; 20 | private String canonicalizedLdProofWithoutProofValues; 21 | private String canonicalizedJsonLdObjectWithoutProof; 22 | private byte[] canonicalizationResult; 23 | 24 | public URDNA2015Canonicalizer(LdProof.Builder proofBuilder) { 25 | super(List.of("urdna2015")); 26 | this.proofBuilder = proofBuilder; 27 | } 28 | 29 | @Override 30 | public byte[] canonicalize(LdProof ldProof, JsonLDObject jsonLdObject) throws IOException, GeneralSecurityException, JsonLDException { 31 | 32 | // construct the LD proof without proof values 33 | ldProofWithoutProofValues = proofBuilder 34 | .base(ldProof) 35 | .defaultContexts(true) 36 | .build(); 37 | LdProof.removeLdProofValues(ldProofWithoutProofValues); 38 | 39 | // construct the LD object without proof 40 | 41 | jsonLdObjectWithoutProof = JsonLDObject.builder() 42 | .base(jsonLdObject) 43 | .build(); 44 | jsonLdObjectWithoutProof.setDocumentLoader(jsonLdObject.getDocumentLoader()); 45 | LdProof.removeFromJsonLdObject(jsonLdObjectWithoutProof); 46 | 47 | // canonicalize the LD proof and LD object 48 | 49 | canonicalizedLdProofWithoutProofValues = ldProofWithoutProofValues.normalize("urdna2015"); 50 | canonicalizedJsonLdObjectWithoutProof = jsonLdObjectWithoutProof.normalize("urdna2015"); 51 | 52 | // construct the canonicalization result 53 | 54 | canonicalizationResult = new byte[64]; 55 | System.arraycopy(SHAUtil.sha256(canonicalizedLdProofWithoutProofValues), 0, canonicalizationResult, 0, 32); 56 | System.arraycopy(SHAUtil.sha256(canonicalizedJsonLdObjectWithoutProof), 0, canonicalizationResult, 32, 32); 57 | 58 | return canonicalizationResult; 59 | } 60 | 61 | public LdProof getLdProofWithoutProofValues() { 62 | return ldProofWithoutProofValues; 63 | } 64 | 65 | public JsonLDObject getJsonLdObjectWithoutProof() { 66 | return jsonLdObjectWithoutProof; 67 | } 68 | 69 | public String getCanonicalizedLdProofWithoutProofValues() { 70 | return canonicalizedLdProofWithoutProofValues; 71 | } 72 | 73 | public String getCanonicalizedJsonLdObjectWithoutProof() { 74 | return canonicalizedJsonLdObjectWithoutProof; 75 | } 76 | 77 | public byte[] getCanonicalizationResult() { 78 | return canonicalizationResult; 79 | } 80 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/2018-credentials-examples-v1.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | { 4 | "@version": 1.1 5 | }, 6 | "https://www.w3.org/ns/odrl.jsonld", 7 | { 8 | "ex": "https://example.org/examples#", 9 | "schema": "http://schema.org/", 10 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 11 | "3rdPartyCorrelation": "ex:3rdPartyCorrelation", 12 | "AllVerifiers": "ex:AllVerifiers", 13 | "Archival": "ex:Archival", 14 | "BachelorDegree": "ex:BachelorDegree", 15 | "Child": "ex:Child", 16 | "CLCredentialDefinition2019": "ex:CLCredentialDefinition2019", 17 | "CLSignature2019": "ex:CLSignature2019", 18 | "IssuerPolicy": "ex:IssuerPolicy", 19 | "HolderPolicy": "ex:HolderPolicy", 20 | "Mother": "ex:Mother", 21 | "RelationshipCredential": "ex:RelationshipCredential", 22 | "UniversityDegreeCredential": "ex:UniversityDegreeCredential", 23 | "AlumniCredential": "ex:AlumniCredential", 24 | "DisputeCredential": "ex:DisputeCredential", 25 | "PrescriptionCredential": "ex:PrescriptionCredential", 26 | "ZkpExampleSchema2018": "ex:ZkpExampleSchema2018", 27 | "issuerData": "ex:issuerData", 28 | "attributes": "ex:attributes", 29 | "signature": "ex:signature", 30 | "signatureCorrectnessProof": "ex:signatureCorrectnessProof", 31 | "primaryProof": "ex:primaryProof", 32 | "nonRevocationProof": "ex:nonRevocationProof", 33 | "alumniOf": { 34 | "@id": "schema:alumniOf", 35 | "@type": "rdf:HTML" 36 | }, 37 | "child": { 38 | "@id": "ex:child", 39 | "@type": "@id" 40 | }, 41 | "degree": "ex:degree", 42 | "degreeType": "ex:degreeType", 43 | "degreeSchool": "ex:degreeSchool", 44 | "college": "ex:college", 45 | "name": { 46 | "@id": "schema:name", 47 | "@type": "rdf:HTML" 48 | }, 49 | "givenName": "schema:givenName", 50 | "familyName": "schema:familyName", 51 | "parent": { 52 | "@id": "ex:parent", 53 | "@type": "@id" 54 | }, 55 | "referenceId": "ex:referenceId", 56 | "documentPresence": "ex:documentPresence", 57 | "evidenceDocument": "ex:evidenceDocument", 58 | "spouse": "schema:spouse", 59 | "subjectPresence": "ex:subjectPresence", 60 | "verifier": { 61 | "@id": "ex:verifier", 62 | "@type": "@id" 63 | }, 64 | "currentStatus": "ex:currentStatus", 65 | "statusReason": "ex:statusReason", 66 | "prescription": "ex:prescription" 67 | } 68 | ] 69 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/clr-v2p0-2.0.1.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "ClrCredential": { 6 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#ClrCredential", 7 | "@context": { 8 | "id": "@id", 9 | "type": "@type", 10 | "partial": { 11 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#partial", 12 | "@type": "xsd:boolean" 13 | } 14 | } 15 | }, 16 | "ClrSubject": { 17 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#ClrSubject", 18 | "@context": { 19 | "id": "@id", 20 | "type": "@type", 21 | "cred": "https://www.w3.org/2018/credentials#", 22 | "obi": "https://purl.imsglobal.org/spec/vc/ob/vocab.html#", 23 | "achievement": { 24 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#achievement", 25 | "@type": "obi:Achievement", 26 | "@container": "@set" 27 | }, 28 | "association": { 29 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#association", 30 | "@type": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#Association", 31 | "@container": "@set" 32 | }, 33 | "verifiableCredential": { 34 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#verifiableCredential", 35 | "@type": "cred:verifiableCredential", 36 | "@container": "@set" 37 | }, 38 | "identifier": { 39 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#identifier-1", 40 | "@type": "obi:Identifier", 41 | "@container": "@set" 42 | } 43 | } 44 | }, 45 | "Association": { 46 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#Association", 47 | "@context": { 48 | "associationType": { 49 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#AssociationType" 50 | }, 51 | "sourceId": { 52 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#sourceId", 53 | "@type": "xsd:anyURI" 54 | }, 55 | "targetId": { 56 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#targetId", 57 | "@type": "xsd:anyURI" 58 | } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/clr-v2p0.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "ClrCredential": { 6 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#ClrCredential", 7 | "@context": { 8 | "id": "@id", 9 | "type": "@type" 10 | } 11 | }, 12 | "ClrSubject": { 13 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#ClrSubject", 14 | "@context": { 15 | "id": "@id", 16 | "type": "@type", 17 | "cred": "https://www.w3.org/2018/credentials#", 18 | "obi": "https://purl.imsglobal.org/spec/ob/v3p0/vocab.html#", 19 | "achievement": { 20 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#achievement", 21 | "@type": "obi:Achievement", 22 | "@container": "@set" 23 | }, 24 | "association": { 25 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#association", 26 | "@type": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#Association", 27 | "@container": "@set" 28 | }, 29 | "verifiableCredential": { 30 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#verifiableCredential", 31 | "@type": "cred:verifiableCredential", 32 | "@container": "@set" 33 | } 34 | } 35 | }, 36 | "Association": { 37 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#Association", 38 | "@context": { 39 | "associationType": { 40 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#AssociationType" 41 | }, 42 | "sourceId": { 43 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#sourceId", 44 | "@type": "xsd:anyURI" 45 | }, 46 | "targetId": { 47 | "@id": "https://purl.imsglobal.org/spec/vc/clr/vocab.html#targetId", 48 | "@type": "xsd:anyURI" 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/data-integrity-v1.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "@protected": true, 6 | "proof": { 7 | "@id": "https://w3id.org/security#proof", 8 | "@type": "@id", 9 | "@container": "@graph" 10 | }, 11 | "DataIntegrityProof": { 12 | "@id": "https://w3id.org/security#DataIntegrityProof", 13 | "@context": { 14 | "@protected": true, 15 | "id": "@id", 16 | "type": "@type", 17 | "challenge": "https://w3id.org/security#challenge", 18 | "created": { 19 | "@id": "http://purl.org/dc/terms/created", 20 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 21 | }, 22 | "domain": "https://w3id.org/security#domain", 23 | "expires": { 24 | "@id": "https://w3id.org/security#expiration", 25 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 26 | }, 27 | "nonce": "https://w3id.org/security#nonce", 28 | "proofPurpose": { 29 | "@id": "https://w3id.org/security#proofPurpose", 30 | "@type": "@vocab", 31 | "@context": { 32 | "@protected": true, 33 | "id": "@id", 34 | "type": "@type", 35 | "assertionMethod": { 36 | "@id": "https://w3id.org/security#assertionMethod", 37 | "@type": "@id", 38 | "@container": "@set" 39 | }, 40 | "authentication": { 41 | "@id": "https://w3id.org/security#authenticationMethod", 42 | "@type": "@id", 43 | "@container": "@set" 44 | }, 45 | "capabilityInvocation": { 46 | "@id": "https://w3id.org/security#capabilityInvocationMethod", 47 | "@type": "@id", 48 | "@container": "@set" 49 | }, 50 | "capabilityDelegation": { 51 | "@id": "https://w3id.org/security#capabilityDelegationMethod", 52 | "@type": "@id", 53 | "@container": "@set" 54 | }, 55 | "keyAgreement": { 56 | "@id": "https://w3id.org/security#keyAgreementMethod", 57 | "@type": "@id", 58 | "@container": "@set" 59 | } 60 | } 61 | }, 62 | "cryptosuite": "https://w3id.org/security#cryptosuite", 63 | "proofValue": { 64 | "@id": "https://w3id.org/security#proofValue", 65 | "@type": "https://w3id.org/security#multibase" 66 | }, 67 | "verificationMethod": { 68 | "@id": "https://w3id.org/security#verificationMethod", 69 | "@type": "@id" 70 | } 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/did-v1.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@protected": true, 4 | "id": "@id", 5 | "type": "@type", 6 | 7 | "alsoKnownAs": { 8 | "@id": "https://www.w3.org/ns/activitystreams#alsoKnownAs", 9 | "@type": "@id" 10 | }, 11 | "assertionMethod": { 12 | "@id": "https://w3id.org/security#assertionMethod", 13 | "@type": "@id", 14 | "@container": "@set" 15 | }, 16 | "authentication": { 17 | "@id": "https://w3id.org/security#authenticationMethod", 18 | "@type": "@id", 19 | "@container": "@set" 20 | }, 21 | "capabilityDelegation": { 22 | "@id": "https://w3id.org/security#capabilityDelegationMethod", 23 | "@type": "@id", 24 | "@container": "@set" 25 | }, 26 | "capabilityInvocation": { 27 | "@id": "https://w3id.org/security#capabilityInvocationMethod", 28 | "@type": "@id", 29 | "@container": "@set" 30 | }, 31 | "controller": { 32 | "@id": "https://w3id.org/security#controller", 33 | "@type": "@id" 34 | }, 35 | "keyAgreement": { 36 | "@id": "https://w3id.org/security#keyAgreementMethod", 37 | "@type": "@id", 38 | "@container": "@set" 39 | }, 40 | "service": { 41 | "@id": "https://www.w3.org/ns/did#service", 42 | "@type": "@id", 43 | "@context": { 44 | "@protected": true, 45 | "id": "@id", 46 | "type": "@type", 47 | "serviceEndpoint": { 48 | "@id": "https://www.w3.org/ns/did#serviceEndpoint", 49 | "@type": "@id" 50 | } 51 | } 52 | }, 53 | "verificationMethod": { 54 | "@id": "https://w3id.org/security#verificationMethod", 55 | "@type": "@id" 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/ob-v3p0-extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "1EdTechJsonSchemaValidator2019": "https://purl.imsglobal.org/spec/vccs/v1p0/context.json#1EdTechJsonSchemaValidator2019", 6 | "1EdTechRevocationList": "https://purl.imsglobal.org/spec/vcrl/v1p0/context.json#1EdTechRevocationList", 7 | "1EdTechCredentialRefresh": "https://purl.imsglobal.org/spec/vccr/v1p0/context.json#1EdTechCredentialRefresh" 8 | } 9 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/obv2x-applylink-extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "obi": "https://w3id.org/openbadges#", 4 | "extensions": "https://w3id.org/openbadges/extensions#", 5 | "url": "extensions:applyLink" 6 | }, 7 | "obi:validation": [ 8 | { 9 | "obi:validatesType": "extensions:ApplyLink", 10 | "obi:validationSchema": "https://openbadgespec.org/extensions/applyLinkExtension/schema.json" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/obv2x-example-extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "obi": "https://w3id.org/openbadges#", 4 | "extensions": "https://w3id.org/openbadges/extensions#", 5 | "exampleProperty": "http://schema.org/text" 6 | }, 7 | "obi:validation": [ 8 | { 9 | "obi:validatesType": "extensions:ExampleExtension", 10 | "obi:validationSchema": "https://openbadgespec.org/extensions/exampleExtension/schema.json" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/security-bbs-v1.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@version": 1.1, 4 | "id": "@id", 5 | "type": "@type", 6 | "BbsBlsSignature2020": { 7 | "@id": "https://w3id.org/security#BbsBlsSignature2020", 8 | "@context": { 9 | "@version": 1.1, 10 | "@protected": true, 11 | "id": "@id", 12 | "type": "@type", 13 | "challenge": "https://w3id.org/security#challenge", 14 | "created": { 15 | "@id": "http://purl.org/dc/terms/created", 16 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 17 | }, 18 | "domain": "https://w3id.org/security#domain", 19 | "proofValue": "https://w3id.org/security#proofValue", 20 | "nonce": "https://w3id.org/security#nonce", 21 | "proofPurpose": { 22 | "@id": "https://w3id.org/security#proofPurpose", 23 | "@type": "@vocab", 24 | "@context": { 25 | "@version": 1.1, 26 | "@protected": true, 27 | "id": "@id", 28 | "type": "@type", 29 | "assertionMethod": { 30 | "@id": "https://w3id.org/security#assertionMethod", 31 | "@type": "@id", 32 | "@container": "@set" 33 | }, 34 | "authentication": { 35 | "@id": "https://w3id.org/security#authenticationMethod", 36 | "@type": "@id", 37 | "@container": "@set" 38 | } 39 | } 40 | }, 41 | "verificationMethod": { 42 | "@id": "https://w3id.org/security#verificationMethod", 43 | "@type": "@id" 44 | } 45 | } 46 | }, 47 | "BbsBlsSignatureProof2020": { 48 | "@id": "https://w3id.org/security#BbsBlsSignatureProof2020", 49 | "@context": { 50 | "@version": 1.1, 51 | "@protected": true, 52 | "id": "@id", 53 | "type": "@type", 54 | 55 | "challenge": "https://w3id.org/security#challenge", 56 | "created": { 57 | "@id": "http://purl.org/dc/terms/created", 58 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 59 | }, 60 | "domain": "https://w3id.org/security#domain", 61 | "nonce": "https://w3id.org/security#nonce", 62 | "proofPurpose": { 63 | "@id": "https://w3id.org/security#proofPurpose", 64 | "@type": "@vocab", 65 | "@context": { 66 | "@version": 1.1, 67 | "@protected": true, 68 | "id": "@id", 69 | "type": "@type", 70 | "sec": "https://w3id.org/security#", 71 | "assertionMethod": { 72 | "@id": "https://w3id.org/security#assertionMethod", 73 | "@type": "@id", 74 | "@container": "@set" 75 | }, 76 | "authentication": { 77 | "@id": "https://w3id.org/security#authenticationMethod", 78 | "@type": "@id", 79 | "@container": "@set" 80 | } 81 | } 82 | }, 83 | "proofValue": "https://w3id.org/security#proofValue", 84 | "verificationMethod": { 85 | "@id": "https://w3id.org/security#verificationMethod", 86 | "@type": "@id" 87 | } 88 | } 89 | }, 90 | "Bls12381G2Key2020": "https://w3id.org/security#Bls12381G2Key2020" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/security-v1.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | 6 | "dc": "http://purl.org/dc/terms/", 7 | "sec": "https://w3id.org/security#", 8 | "xsd": "http://www.w3.org/2001/XMLSchema#", 9 | 10 | "EcdsaKoblitzSignature2016": "sec:EcdsaKoblitzSignature2016", 11 | "Ed25519Signature2018": "sec:Ed25519Signature2018", 12 | "EncryptedMessage": "sec:EncryptedMessage", 13 | "GraphSignature2012": "sec:GraphSignature2012", 14 | "LinkedDataSignature2015": "sec:LinkedDataSignature2015", 15 | "LinkedDataSignature2016": "sec:LinkedDataSignature2016", 16 | "CryptographicKey": "sec:Key", 17 | 18 | "authenticationTag": "sec:authenticationTag", 19 | "canonicalizationAlgorithm": "sec:canonicalizationAlgorithm", 20 | "cipherAlgorithm": "sec:cipherAlgorithm", 21 | "cipherData": "sec:cipherData", 22 | "cipherKey": "sec:cipherKey", 23 | "created": {"@id": "dc:created", "@type": "xsd:dateTime"}, 24 | "creator": {"@id": "dc:creator", "@type": "@id"}, 25 | "digestAlgorithm": "sec:digestAlgorithm", 26 | "digestValue": "sec:digestValue", 27 | "domain": "sec:domain", 28 | "encryptionKey": "sec:encryptionKey", 29 | "expiration": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, 30 | "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, 31 | "initializationVector": "sec:initializationVector", 32 | "iterationCount": "sec:iterationCount", 33 | "nonce": "sec:nonce", 34 | "normalizationAlgorithm": "sec:normalizationAlgorithm", 35 | "owner": {"@id": "sec:owner", "@type": "@id"}, 36 | "password": "sec:password", 37 | "privateKey": {"@id": "sec:privateKey", "@type": "@id"}, 38 | "privateKeyPem": "sec:privateKeyPem", 39 | "publicKey": {"@id": "sec:publicKey", "@type": "@id"}, 40 | "publicKeyBase58": "sec:publicKeyBase58", 41 | "publicKeyPem": "sec:publicKeyPem", 42 | "publicKeyWif": "sec:publicKeyWif", 43 | "publicKeyService": {"@id": "sec:publicKeyService", "@type": "@id"}, 44 | "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"}, 45 | "salt": "sec:salt", 46 | "signature": "sec:signature", 47 | "signatureAlgorithm": "sec:signingAlgorithm", 48 | "signatureValue": "sec:signatureValue" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/suites-ed25519-2018.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "@protected": true, 6 | "proof": { 7 | "@id": "https://w3id.org/security#proof", 8 | "@type": "@id", 9 | "@container": "@graph" 10 | }, 11 | "Ed25519VerificationKey2018": { 12 | "@id": "https://w3id.org/security#Ed25519VerificationKey2018", 13 | "@context": { 14 | "@protected": true, 15 | "id": "@id", 16 | "type": "@type", 17 | "controller": { 18 | "@id": "https://w3id.org/security#controller", 19 | "@type": "@id" 20 | }, 21 | "revoked": { 22 | "@id": "https://w3id.org/security#revoked", 23 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 24 | }, 25 | "publicKeyBase58": { 26 | "@id": "https://w3id.org/security#publicKeyBase58" 27 | } 28 | } 29 | }, 30 | "Ed25519Signature2018": { 31 | "@id": "https://w3id.org/security#Ed25519Signature2018", 32 | "@context": { 33 | "@protected": true, 34 | "id": "@id", 35 | "type": "@type", 36 | "challenge": "https://w3id.org/security#challenge", 37 | "created": { 38 | "@id": "http://purl.org/dc/terms/created", 39 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 40 | }, 41 | "domain": "https://w3id.org/security#domain", 42 | "expires": { 43 | "@id": "https://w3id.org/security#expiration", 44 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 45 | }, 46 | "nonce": "https://w3id.org/security#nonce", 47 | "proofPurpose": { 48 | "@id": "https://w3id.org/security#proofPurpose", 49 | "@type": "@vocab", 50 | "@context": { 51 | "@protected": true, 52 | "id": "@id", 53 | "type": "@type", 54 | "assertionMethod": { 55 | "@id": "https://w3id.org/security#assertionMethod", 56 | "@type": "@id", 57 | "@container": "@set" 58 | }, 59 | "authentication": { 60 | "@id": "https://w3id.org/security#authenticationMethod", 61 | "@type": "@id", 62 | "@container": "@set" 63 | }, 64 | "capabilityInvocation": { 65 | "@id": "https://w3id.org/security#capabilityInvocationMethod", 66 | "@type": "@id", 67 | "@container": "@set" 68 | }, 69 | "capabilityDelegation": { 70 | "@id": "https://w3id.org/security#capabilityDelegationMethod", 71 | "@type": "@id", 72 | "@container": "@set" 73 | }, 74 | "keyAgreement": { 75 | "@id": "https://w3id.org/security#keyAgreementMethod", 76 | "@type": "@id", 77 | "@container": "@set" 78 | } 79 | } 80 | }, 81 | "jws": { 82 | "@id": "https://w3id.org/security#jws" 83 | }, 84 | "verificationMethod": { 85 | "@id": "https://w3id.org/security#verificationMethod", 86 | "@type": "@id" 87 | } 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/suites-ed25519-2020.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "@protected": true, 6 | "proof": { 7 | "@id": "https://w3id.org/security#proof", 8 | "@type": "@id", 9 | "@container": "@graph" 10 | }, 11 | "Ed25519VerificationKey2020": { 12 | "@id": "https://w3id.org/security#Ed25519VerificationKey2020", 13 | "@context": { 14 | "@protected": true, 15 | "id": "@id", 16 | "type": "@type", 17 | "controller": { 18 | "@id": "https://w3id.org/security#controller", 19 | "@type": "@id" 20 | }, 21 | "revoked": { 22 | "@id": "https://w3id.org/security#revoked", 23 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 24 | }, 25 | "publicKeyMultibase": { 26 | "@id": "https://w3id.org/security#publicKeyMultibase", 27 | "@type": "https://w3id.org/security#multibase" 28 | } 29 | } 30 | }, 31 | "Ed25519Signature2020": { 32 | "@id": "https://w3id.org/security#Ed25519Signature2020", 33 | "@context": { 34 | "@protected": true, 35 | "id": "@id", 36 | "type": "@type", 37 | "challenge": "https://w3id.org/security#challenge", 38 | "created": { 39 | "@id": "http://purl.org/dc/terms/created", 40 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 41 | }, 42 | "domain": "https://w3id.org/security#domain", 43 | "expires": { 44 | "@id": "https://w3id.org/security#expiration", 45 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 46 | }, 47 | "nonce": "https://w3id.org/security#nonce", 48 | "proofPurpose": { 49 | "@id": "https://w3id.org/security#proofPurpose", 50 | "@type": "@vocab", 51 | "@context": { 52 | "@protected": true, 53 | "id": "@id", 54 | "type": "@type", 55 | "assertionMethod": { 56 | "@id": "https://w3id.org/security#assertionMethod", 57 | "@type": "@id", 58 | "@container": "@set" 59 | }, 60 | "authentication": { 61 | "@id": "https://w3id.org/security#authenticationMethod", 62 | "@type": "@id", 63 | "@container": "@set" 64 | }, 65 | "capabilityInvocation": { 66 | "@id": "https://w3id.org/security#capabilityInvocationMethod", 67 | "@type": "@id", 68 | "@container": "@set" 69 | }, 70 | "capabilityDelegation": { 71 | "@id": "https://w3id.org/security#capabilityDelegationMethod", 72 | "@type": "@id", 73 | "@container": "@set" 74 | }, 75 | "keyAgreement": { 76 | "@id": "https://w3id.org/security#keyAgreementMethod", 77 | "@type": "@id", 78 | "@container": "@set" 79 | } 80 | } 81 | }, 82 | "proofValue": { 83 | "@id": "https://w3id.org/security#proofValue", 84 | "@type": "https://w3id.org/security#multibase" 85 | }, 86 | "verificationMethod": { 87 | "@id": "https://w3id.org/security#verificationMethod", 88 | "@type": "@id" 89 | } 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/suites-jws-2020.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "privateKeyJwk": { 4 | "@id": "https://w3id.org/security#privateKeyJwk", 5 | "@type": "@json" 6 | }, 7 | "JsonWebKey2020": { 8 | "@id": "https://w3id.org/security#JsonWebKey2020", 9 | "@context": { 10 | "@protected": true, 11 | "id": "@id", 12 | "type": "@type", 13 | "publicKeyJwk": { 14 | "@id": "https://w3id.org/security#publicKeyJwk", 15 | "@type": "@json" 16 | } 17 | } 18 | }, 19 | "JsonWebSignature2020": { 20 | "@id": "https://w3id.org/security#JsonWebSignature2020", 21 | "@context": { 22 | "@protected": true, 23 | 24 | "id": "@id", 25 | "type": "@type", 26 | 27 | "challenge": "https://w3id.org/security#challenge", 28 | "created": { 29 | "@id": "http://purl.org/dc/terms/created", 30 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 31 | }, 32 | "domain": "https://w3id.org/security#domain", 33 | "expires": { 34 | "@id": "https://w3id.org/security#expiration", 35 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 36 | }, 37 | "jws": "https://w3id.org/security#jws", 38 | "nonce": "https://w3id.org/security#nonce", 39 | "proofPurpose": { 40 | "@id": "https://w3id.org/security#proofPurpose", 41 | "@type": "@vocab", 42 | "@context": { 43 | "@protected": true, 44 | 45 | "id": "@id", 46 | "type": "@type", 47 | 48 | "assertionMethod": { 49 | "@id": "https://w3id.org/security#assertionMethod", 50 | "@type": "@id", 51 | "@container": "@set" 52 | }, 53 | "authentication": { 54 | "@id": "https://w3id.org/security#authenticationMethod", 55 | "@type": "@id", 56 | "@container": "@set" 57 | }, 58 | "capabilityInvocation": { 59 | "@id": "https://w3id.org/security#capabilityInvocationMethod", 60 | "@type": "@id", 61 | "@container": "@set" 62 | }, 63 | "capabilityDelegation": { 64 | "@id": "https://w3id.org/security#capabilityDelegationMethod", 65 | "@type": "@id", 66 | "@container": "@set" 67 | }, 68 | "keyAgreement": { 69 | "@id": "https://w3id.org/security#keyAgreementMethod", 70 | "@type": "@id", 71 | "@container": "@set" 72 | } 73 | } 74 | }, 75 | "verificationMethod": { 76 | "@id": "https://w3id.org/security#verificationMethod", 77 | "@type": "@id" 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /inspector-vc/src/main/resources/contexts/suites-x25519-2019.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "id": "@id", 4 | "type": "@type", 5 | "@protected": true, 6 | "X25519KeyAgreementKey2019": { 7 | "@id": "https://w3id.org/security#X25519KeyAgreementKey2019", 8 | "@context": { 9 | "@protected": true, 10 | "id": "@id", 11 | "type": "@type", 12 | "controller": { 13 | "@id": "https://w3id.org/security#controller", 14 | "@type": "@id" 15 | }, 16 | "revoked": { 17 | "@id": "https://w3id.org/security#revoked", 18 | "@type": "http://www.w3.org/2001/XMLSchema#dateTime" 19 | }, 20 | "publicKeyBase58": { 21 | "@id": "https://w3id.org/security#publicKeyBase58" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /inspector-vc/src/test/java/org/oneedtech/inspect/vc/BitstringStatusListCredentialInspectorTest.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 | import static org.oneedtech.inspect.test.Assertions.assertValid; 5 | 6 | import org.junit.jupiter.api.BeforeAll; 7 | import org.junit.jupiter.api.Test; 8 | import org.oneedtech.inspect.core.Inspector.Behavior; 9 | import org.oneedtech.inspect.core.report.Report; 10 | import org.oneedtech.inspect.test.PrintHelper; 11 | import org.oneedtech.inspect.util.resource.ResourceType; 12 | 13 | public class BitstringStatusListCredentialInspectorTest { 14 | private static BitstringStatusListCredentialInspector validator; 15 | private static boolean verbose = true; 16 | 17 | @BeforeAll 18 | static void setup() { 19 | validator = new BitstringStatusListCredentialInspector.Builder() 20 | .set(Behavior.TEST_INCLUDE_SUCCESS, true) 21 | .set(Behavior.VALIDATOR_FAIL_FAST, true) 22 | .build(); 23 | } 24 | 25 | @Test 26 | void testSimpleJsonValid() { 27 | assertDoesNotThrow(()->{ 28 | Report report = validator.run(Samples.OB30.BSL.SIMPLE_JSON.asFileResource(ResourceType.JSON)); 29 | if(verbose) PrintHelper.print(report, true); 30 | assertValid(report); 31 | }); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /inspector-vc/src/test/java/org/oneedtech/inspect/vc/Endorsement30Tests.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 | import static org.oneedtech.inspect.test.Assertions.assertFatalCount; 5 | import static org.oneedtech.inspect.test.Assertions.assertHasProbeID; 6 | import static org.oneedtech.inspect.test.Assertions.assertInvalid; 7 | import static org.oneedtech.inspect.test.Assertions.assertValid; 8 | 9 | import org.junit.jupiter.api.BeforeAll; 10 | import org.junit.jupiter.api.Test; 11 | import org.oneedtech.inspect.core.Inspector.Behavior; 12 | import org.oneedtech.inspect.core.report.Report; 13 | import org.oneedtech.inspect.test.PrintHelper; 14 | import org.oneedtech.inspect.vc.probe.CredentialParseProbe; 15 | 16 | public class Endorsement30Tests { 17 | private static EndorsementInspector validator; 18 | private static boolean verbose = true; 19 | 20 | @BeforeAll 21 | static void setup() { 22 | validator = new EndorsementInspector.Builder() 23 | .set(Behavior.TEST_INCLUDE_SUCCESS, true) 24 | .set(Behavior.VALIDATOR_FAIL_FAST, false) 25 | .build(); 26 | } 27 | 28 | @Test 29 | void testEndorsementWithoutErrors() { 30 | assertDoesNotThrow(()->{ 31 | Report report = validator.run(Samples.OB30.JSON.ENDORSEMENT_VALID.asFileResource()); 32 | if(verbose) PrintHelper.print(report, true); 33 | assertValid(report); 34 | }); 35 | } 36 | 37 | @Test 38 | void testEndorsementWithErrors() { 39 | assertDoesNotThrow(()->{ 40 | Report report = validator.run(Samples.OB30.JSON.ENDORSEMENT_ERR_SCHEMA_STATUS_REFRESH.asFileResource()); 41 | if(verbose) PrintHelper.print(report, true); 42 | assertInvalid(report); 43 | assertFatalCount(report, 1); 44 | // Parse probe fails because refresh points to invalid URL so nothing to parse 45 | assertHasProbeID(report, CredentialParseProbe.ID, true); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /inspector-vc/src/test/java/org/oneedtech/inspect/vc/resource/TestUriResourceFactory.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.resource; 2 | 3 | import java.net.URI; 4 | import java.net.URISyntaxException; 5 | 6 | import org.oneedtech.inspect.util.resource.UriResource; 7 | import org.oneedtech.inspect.vc.util.CachingDocumentLoader; 8 | 9 | import com.apicatalog.jsonld.loader.DocumentLoader; 10 | 11 | import foundation.identity.jsonld.ConfigurableDocumentLoader; 12 | 13 | /** 14 | * UriResource factory for test, resolving local references 15 | * @author xaracil 16 | */ 17 | public class TestUriResourceFactory implements UriResourceFactory { 18 | 19 | final DocumentLoader documentLoader; 20 | 21 | public TestUriResourceFactory(DocumentLoader documentLoader) { 22 | this.documentLoader = documentLoader; 23 | } 24 | 25 | @Override 26 | public UriResource of(String uriString) throws URISyntaxException { 27 | URI uri = new URI(uriString); 28 | if (documentLoader instanceof CachingDocumentLoader) { 29 | URI resolvedUri = ((CachingDocumentLoader.HttpLoader) ConfigurableDocumentLoader.getDefaultHttpLoader()).resolve(uri); 30 | uri = resolvedUri; 31 | } 32 | return new UriResource(uri); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /inspector-vc/src/test/java/org/oneedtech/inspect/vc/util/CachingDocumentLoaderTests.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.util; 2 | 3 | import java.net.URI; 4 | import java.net.URL; 5 | import java.util.Map; 6 | 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import com.apicatalog.jsonld.document.Document; 11 | import com.apicatalog.jsonld.document.JsonDocument; 12 | import com.apicatalog.jsonld.loader.DocumentLoader; 13 | import com.apicatalog.jsonld.loader.DocumentLoaderOptions; 14 | import com.google.common.io.Resources; 15 | 16 | public class CachingDocumentLoaderTests { 17 | 18 | @Test 19 | void testStaticCachedDocumentBundled() { 20 | Assertions.assertDoesNotThrow(()->{ 21 | DocumentLoader loader = new CachingDocumentLoader(); 22 | for(String id : CachingDocumentLoader.bundled.keySet()) { 23 | Document doc = loader.loadDocument(new URI(id), new DocumentLoaderOptions()); 24 | Assertions.assertNotNull(doc); 25 | } 26 | }); 27 | } 28 | 29 | @Test 30 | void testLocalDomainCachedDocument() { 31 | Assertions.assertDoesNotThrow(()->{ 32 | Map localDomains = Map.of(new URI("http://example.org/"), "ob20"); 33 | DocumentLoader loader = new CachingDocumentLoader(localDomains); 34 | URI uri = new URI("http://example.org/basic-assertion.json"); 35 | Document doc = loader.loadDocument(uri, new DocumentLoaderOptions()); 36 | Assertions.assertNotNull(doc); 37 | 38 | // assert the returned document is the same as the local resource 39 | URL resource = Resources.getResource("ob20/basic-assertion.json"); 40 | JsonDocument resourceDocument = JsonDocument.of(resource.openStream()); 41 | Assertions.assertEquals(resourceDocument.getJsonContent().toString(), doc.getJsonContent().toString()); 42 | }); 43 | } 44 | 45 | @Test 46 | void testStaticCachedDocumentKey() { 47 | Assertions.assertDoesNotThrow(()->{ 48 | DocumentLoader loader = new CachingDocumentLoader(); 49 | URI uri = new URI("https://www.w3.org/ns/did/v1"); 50 | Document doc = loader.loadDocument(uri, new DocumentLoaderOptions()); 51 | Assertions.assertNotNull(doc); 52 | }); 53 | } 54 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/java/org/oneedtech/inspect/vc/util/JsonNodeUtilTests.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.util; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertTrue; 4 | import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT; 5 | 6 | import java.util.List; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | import org.oneedtech.inspect.core.probe.json.JsonPathEvaluator; 11 | import org.oneedtech.inspect.util.json.ObjectMapperCache; 12 | import org.oneedtech.inspect.vc.Samples; 13 | 14 | import com.fasterxml.jackson.databind.JsonNode; 15 | import com.fasterxml.jackson.databind.ObjectMapper; 16 | import com.fasterxml.jackson.databind.node.ArrayNode; 17 | 18 | public class JsonNodeUtilTests { 19 | static final ObjectMapper mapper = ObjectMapperCache.get(DEFAULT); 20 | static final JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper); 21 | 22 | @Test 23 | void testFlattenNodeList() { 24 | Assertions.assertDoesNotThrow(()->{ 25 | String json = Samples.OB30.JSON.COMPLETE_JSON.asString(); 26 | JsonNode root = mapper.readTree(json); 27 | List list = JsonNodeUtil.asNodeList(root, "$..endorsement", jsonPath); 28 | Assertions.assertEquals(5, list.size()); 29 | for(JsonNode node : list) { 30 | ArrayNode types = (ArrayNode) node.get("type"); 31 | boolean found = false; 32 | for(JsonNode val : types) { 33 | if(val.asText().equals("EndorsementCredential")) { 34 | found = true; 35 | } 36 | } 37 | assertTrue(found); 38 | } 39 | 40 | }); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /inspector-vc/src/test/java/org/oneedtech/inspect/vc/util/TestOB20Inspector.java: -------------------------------------------------------------------------------- 1 | package org.oneedtech.inspect.vc.util; 2 | 3 | import java.net.URI; 4 | import java.util.Collections; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import org.oneedtech.inspect.util.resource.ResourceType; 9 | import org.oneedtech.inspect.util.spec.Specification; 10 | import org.oneedtech.inspect.vc.OB20Inspector; 11 | import org.oneedtech.inspect.vc.resource.TestUriResourceFactory; 12 | import org.oneedtech.inspect.vc.resource.UriResourceFactory; 13 | 14 | import com.apicatalog.jsonld.loader.DocumentLoader; 15 | 16 | /** 17 | * OpenBadges 2.0 Test inspector. 18 | * It's a subclass of main OB2.0 inspector, setting redirection of urls to local resources for testing 19 | */ 20 | public class TestOB20Inspector extends OB20Inspector { 21 | protected final Map localDomains; 22 | 23 | protected TestOB20Inspector(TestBuilder builder) { 24 | super(builder); 25 | if (getBehavior(OB20Inspector.Behavior.ALLOW_LOCAL_REDIRECTION) == Boolean.TRUE) { 26 | this.localDomains = builder.localDomains; 27 | } else { 28 | this.localDomains = Collections.emptyMap(); 29 | } 30 | } 31 | 32 | @Override 33 | protected DocumentLoader getDocumentLoader() { 34 | return new CachingDocumentLoader(localDomains); 35 | } 36 | 37 | @Override 38 | protected UriResourceFactory getUriResourceFactory(DocumentLoader documentLoader) { 39 | return new TestUriResourceFactory(documentLoader); 40 | } 41 | 42 | public static class TestBuilder extends OB20Inspector.Builder { 43 | final Map localDomains; 44 | 45 | public TestBuilder() { 46 | super(); 47 | // don't allow local redirections by default 48 | super.behaviors.put(OB20Inspector.Behavior.ALLOW_LOCAL_REDIRECTION, true); 49 | this.localDomains = new HashMap<>(); 50 | } 51 | 52 | public TestBuilder add(URI localDomain, String resourcePath) { 53 | localDomains.put(localDomain, resourcePath); 54 | return this; 55 | } 56 | 57 | @Override 58 | public TestOB20Inspector build() { 59 | set(Specification.OB20); 60 | set(ResourceType.OPENBADGE); 61 | return new TestOB20Inspector(this); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assertion-with-data-image.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOUMyqsBwACeQFChxlltgAAAABJRU5ErkJggg==", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assertion-with-endorsements.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": { 15 | "type": "BadgeClass", 16 | "id": "https://example.org/badgeclass-with-endorsements.json", 17 | "name": "Awesome Robotics Badge", 18 | "description": "For doing awesome things with robots that people think is pretty great.", 19 | "image": "https://example.org/robotics-badge.png", 20 | "criteria": "https://example.org/badgecriteria.json", 21 | "issuer": "https://example.org/organization.json", 22 | "endorsement": ["https://example.org/endorsement-3.json", "https://example.org/endorsement-4.json"] 23 | }, 24 | "verification": { 25 | "type": "hosted" 26 | }, 27 | "endorsement": ["https://example.org/endorsement-1.json", "https://example.org/endorsement-2.json"] 28 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assertion-with-extension-node-basic.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/openbadges/v2" 4 | ], 5 | "id": "http://example.org/assertion", 6 | "type": "Assertion", 7 | "recipient": { 8 | "type": "email", 9 | "hashed": true, 10 | "salt": "deadsea", 11 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 12 | }, 13 | "image": "https://example.org/beths-robot-badge.png", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "issuedOn": "2016-12-31T23:59:59Z", 16 | "verification": { 17 | "type": "hosted" 18 | }, 19 | "extensions:exampleExtension": { 20 | "@context": ["https://w3id.org/openbadges/extensions/exampleExtension/context.json"], 21 | "type": [ 22 | "Extension", 23 | "extensions:ExampleExtension" 24 | ], 25 | "http://schema.org/text": "I'm a property, short and sweet" 26 | }, 27 | "evidence": { 28 | "id": "_:b1", 29 | "narrative": "Rocked the free world" 30 | } 31 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assertion-with-extension-node-invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/openbadges/v2", 4 | "https://w3id.org/openbadges/extensions/exampleExtension/context.json" 5 | ], 6 | "id": "http://example.org/assertion", 7 | "type": "Assertion", 8 | "recipient": { 9 | "type": "email", 10 | "hashed": true, 11 | "salt": "deadsea", 12 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 13 | }, 14 | "image": "https://example.org/beths-robot-badge.png", 15 | "badge": "https://example.org/robotics-badge.json", 16 | "issuedOn": "2016-12-31T23:59:59Z", 17 | "verification": { 18 | "type": "hosted" 19 | }, 20 | "extensions:exampleExtension": { 21 | "id": "_:b0", 22 | "type": [ 23 | "Extension", 24 | "obi:extensions/#ExampleExtension" 25 | ], 26 | "http://schema.org/text": 1337 27 | }, 28 | "evidence": { 29 | "id": "_:b1", 30 | "narrative": "Rocked the free world" 31 | } 32 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assertion-with-multiple-extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/openbadges/v2" 4 | ], 5 | "id": "http://example.org/assertion", 6 | "type": "Assertion", 7 | "recipient": { 8 | "type": "email", 9 | "hashed": true, 10 | "salt": "deadsea", 11 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 12 | }, 13 | "image": "https://example.org/beths-robot-badge.png", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "issuedOn": "2016-12-31T23:59:59Z", 16 | "verification": { 17 | "type": "hosted" 18 | }, 19 | "extensions:exampleExtension": { 20 | "@context": [ 21 | "https://w3id.org/openbadges/extensions/exampleExtension/context.json", 22 | "https://w3id.org/openbadges/extensions/applyLinkExtension/context.json" 23 | ], 24 | "type": [ 25 | "Extension", 26 | "extensions:ExampleExtension", 27 | "extensions:ApplyLink" 28 | ], 29 | "exampleProperty": "I'm a property, short and sweet", 30 | "url": "http://www.1edtech.org" 31 | }, 32 | "evidence": { 33 | "id": "_:b1", 34 | "narrative": "Rocked the free world" 35 | } 36 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/altbadgeurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/robotics-badge.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "http://example.com/badgecriteria.json", 9 | "issuer": "https://example.org/organization.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badge-from-organization-with-empty-revocation-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/badge-from-organization-with-empty-revocation-list.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "http://example.com/badgecriteria.json", 9 | "issuer": "https://example.org/organization-with-empty-revocation-list.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badge-from-organization-with-revocation-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/badge-from-organization-with-revocation-list.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "http://example.com/badgecriteria.json", 9 | "issuer": "https://example.org/organization-with-revocation-list.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badge-with-bad-issuer.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "http://example.org/badge-with-bad-issuer.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "http://example.com/badgecriteria.json", 9 | "issuer": "https://example.org/bad-issuer.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badge-with-data-image.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/badge-from-organization-with-revocation-list.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOUMyqsBwACeQFChxlltgAAAABJRU5ErkJggg==", 8 | "criteria": "http://example.com/badgecriteria.json", 9 | "issuer": "https://example.org/organization-with-revocation-list.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badgeclass-with-complex-image.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/badgeclass-with-complex-image.json", 4 | "type": "BadgeClass", 5 | "name": "Example Badge", 6 | "description": "An example", 7 | "criteria": "http://example.com/badgecriteria.json", 8 | "issuer": "http://example.org/issuer1.json", 9 | "image": { 10 | "id": "http://example.org/beths-robot-badge.png", 11 | "author": "http://someoneelse.org/1", 12 | "caption": "A hexagon with attitude" 13 | } 14 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badgeclass-with-endorsements.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/badgeclass-with-endorsements.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "https://example.org/badgecriteria.json", 9 | "issuer": "https://example.org/organization.json", 10 | "endorsement": ["https://example.org/endorsement-3.json", "https://example.org/endorsement-4.json"] 11 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badgeclass-with-language.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/badgeclass-with-language.json", 5 | "@language": "es", 6 | "name": "Insignia fantastica", 7 | "description": "For doing awesome things with robots that people think is pretty great.", 8 | "image": "https://example.org/robotics-badge.png", 9 | "criteria": "https://example.org/badgecriteria.json", 10 | "issuer": "https://example.org/organization.json", 11 | "related": { 12 | "id": "https://example.org/robotics-badge.json", 13 | "@language": "en-US" 14 | } 15 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/badgecriteria.json: -------------------------------------------------------------------------------- 1 | { 2 | "narrative": "Do the important things." 3 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/basic-badge-no-public-key.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/basic-badge-no-public-key.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "https://example.org/badgecriteria.json", 9 | "issuer": "https://example.org/organization-no-public-key.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/beths-robot-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob20/assets/beths-robot-badge.png -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/beths-robot-work.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob20/assets/beths-robot-work.html -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/empty-revocation-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/empty-revocation-list.json", 4 | "type": "RevocationList", 5 | "revokedAssertions": [] 6 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/endorsement-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/endorsement-1.json", 4 | "type": "Endorsement", 5 | "claim": { 6 | "id": "https://example.org/badgeclass-with-endorsements.json", 7 | "endorsementComment": "Pretty good" 8 | }, 9 | "issuedOn": "2017-10-01T00:00Z", 10 | "issuer": "http://example.org/issuer1.json", 11 | "verification": { 12 | "type": "HostedBadge" 13 | } 14 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/endorsement-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/endorsement-2.json", 4 | "type": "Endorsement", 5 | "claim": { 6 | "id": "https://example.org/badgeclass-with-endorsements.json", 7 | "endorsementComment": "Pretty good" 8 | }, 9 | "issuedOn": "2017-10-01T00:00Z", 10 | "issuer": "http://example.org/issuer1.json", 11 | "verification": { 12 | "type": "HostedBadge" 13 | } 14 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/endorsement-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/endorsement-3.json", 4 | "type": "Endorsement", 5 | "claim": { 6 | "id": "https://example.org/badgeclass-with-endorsements.json", 7 | "endorsementComment": "Pretty good" 8 | }, 9 | "issuedOn": "2017-10-01T00:00Z", 10 | "issuer": "http://example.org/issuer1.json", 11 | "verification": { 12 | "type": "HostedBadge" 13 | } 14 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/endorsement-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/endorsement-4.json", 4 | "type": "Endorsement", 5 | "claim": { 6 | "id": "https://example.org/badgeclass-with-endorsements.json", 7 | "endorsementComment": "Pretty good" 8 | }, 9 | "issuedOn": "2017-10-01T00:00Z", 10 | "issuer": "http://example.org/issuer1.json", 11 | "verification": { 12 | "type": "HostedBadge" 13 | } 14 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/key1.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/key1.json", 4 | "type": "CryptographicKey", 5 | "owner": "https://example.org/organization.json", 6 | "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAko9t/QZEwRUainRO5MqY\nGBBeFe7rm/BVg6ugkgkyRGdDkjCeEjNfCm6An+bQqeCsHoMCprs629/a9yJ58/4w\nP7ws/5lJ9YwZYXpGvLfha0xrpWl5DiExeOMB9pB8p4ze0AI6H49w9ZX0G+cgaqaK\n/FbQ/Ln1zkZH6+VaAntoaLu3I5kLLR1F31HqLmSKpm6rHyLFkq534dGfuNmjSM+x\nZxBKu+ugmyeL9DinHvBZ/dwFMGS+o4/bT54UeLMd7a71ONevRY2hXgwarfWjqkDs\nAgqnfKSDjjDZQDM2OlyLWvyI2SWF4eWxIUtWuFP4j0d/5SUFjhAldRLjIXMQWMEN\nNwIDAQAB\n-----END PUBLIC KEY-----" 7 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/key2.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/key2.json", 4 | "type": "CryptographicKey", 5 | "owner": "https://example.org/organization-with-empty-revocation-list.json", 6 | "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjjtSHqVnCOhOe91mt1hh\nWa0h6qF5K32ETY3+6ENQ7kR6qvI1S4prxptYfkuCncJFeZkCu306QS8E/iYCUEoC\ndKOYMVtn1Tm16p2cD+d4LQNYDQbKyKIqU8Cgqb3GoS2MWlJ6Q9sVW1B24RYAokW9\npm80xFJMJAIbZKBfr/hMLofGD5vvBHV/UFYtGvy7PByA7eNPkSLFnIY2L6WBWVyE\na2o95Jzvih+H2CmAk6HSumJL/PdV3yys/m4TEmU0V3m7B8voa3yEIFYG4hKxGUCi\nRqaq/wTFsTVBsEZn9rcpjG58ibjfd1+HBhWjRqsa5NNM9sQqnvvNBSWnqE5ggiNc\nzQIDAQAB\n-----END PUBLIC KEY-----" 7 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/key3.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/key3.json", 4 | "type": "CryptographicKey", 5 | "owner": "https://example.org/organization-with-revocation-list.json", 6 | "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlxjYVv/2hAXO/D9b/Ifq\ng4n8TQCG3tq6JUyQPrhW27E9htH5UexdbOAAlzydQ5kYve3F8fhHuue/mjnKrMJn\najdTU4BBIPT4CJ3ZCCzKZf9OvMwobZT5P5QmkG1eVLOTGFs9BTvpbGQ7qugUbxHH\nXeHK/OoBnenKmLV0R4+KePe0oTcNToDQbx0uMZzNM9TRpnVBHlCXwYbFzw1js0Tt\nuT4M8MtKOoyNf+ZA8fcsSpmE7K1xDYOY7o9tZMFtGIQuhKlZyVpKpAu4KrhrZBJG\nJ47zcxzrncQHmft3aL8qWNCtZ+fOa+/fPkjT+bPhCwHSkE9Xj8Q0AF1vmDNReun1\nhwIDAQAB\n-----END PUBLIC KEY-----" 7 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/organization-no-public-key.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Issuer", 4 | "id": "https://example.org/organization-no-public-key.json", 5 | "name": "An Example Badge Issuer", 6 | "url": "https://example.org", 7 | "email": "contact@example.org" 8 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/organization-with-empty-revocation-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Issuer", 4 | "id": "https://example.org/organization-with-empty-revocation-list.json", 5 | "name": "An Example Badge Issuer", 6 | "url": "https://example.org", 7 | "email": "contact@example.org", 8 | "revocationList": "http://example.org/empty-revocation-list.json", 9 | "publicKey": "http://example.org/key2.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/organization-with-revocation-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Issuer", 4 | "id": "https://example.org/organization-with-revocation-list.json", 5 | "name": "An Example Badge Issuer", 6 | "url": "https://example.org", 7 | "email": "contact@example.org", 8 | "revocationList": "http://example.org/revocation-list.json", 9 | "publicKey": "http://example.org/key3.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/organization.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Issuer", 4 | "id": "https://example.org/organization.json", 5 | "name": "An Example Badge Issuer", 6 | "url": "https://example.org", 7 | "email": "contact@example.org", 8 | "publicKey": "http://example.org/key1.json" 9 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/revocation-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/revocation-list.json", 4 | "type": "RevocationList", 5 | "revokedAssertions": [ 6 | { 7 | "id": "https://example.org/beths-robotics-badge-revoked.json", 8 | "revocationReason": "A good reason, for sure" 9 | }, 10 | { 11 | "id": "urn:uuid:52e4c6b3-8c13-4fa8-8482-a5cf34ef37a9" 12 | }, 13 | "urn:uuid:6deb4a00-ebce-4b28-8cc2-afa705ef7be4" 14 | ] 15 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/robotics-badge.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "BadgeClass", 4 | "id": "https://example.org/robotics-badge.json", 5 | "name": "Awesome Robotics Badge", 6 | "description": "For doing awesome things with robots that people think is pretty great.", 7 | "image": "https://example.org/robotics-badge.png", 8 | "criteria": "https://example.org/badgecriteria.json", 9 | "issuer": "https://example.org/organization.json" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/assets/robotics-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob20/assets/robotics-badge.png -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/badge-class-with-language.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/badgeclass", 4 | "@language": "en-US", 5 | "name": "Example Badge", 6 | "description": "An example", 7 | "criteria": "http://example.com/badgecriteria.json", 8 | "issuer": "http://example.org/issuer1.json", 9 | "type": "BadgeClass" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-expired-before-issued.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2022-12-31T23:59:59Z", 14 | "expires": "2022-11-15T23:59:59Z", 15 | "badge": "https://example.org/robotics-badge.json", 16 | "verification": { 17 | "type": "hosted" 18 | } 19 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-expired.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "expires": "2022-11-15T23:59:59Z", 15 | "badge": "https://example.org/robotics-badge.json", 16 | "verification": { 17 | "type": "hosted" 18 | } 19 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-in-future.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2100-12-31T23:59:59Z", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-invalid-context.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/invalid", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-invalid-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "OtherAssertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-no-public-key.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/basic-badge-no-public-key.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-with-allowed-origins-invalid-multiple-starts-with.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/badgeclass-with-verification-invalid-multiple-starts-with.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-with-allowed-origins-invalid-starts-with.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/badgeclass-with-verification-invalid-starts-with.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-with-allowed-origins-valid-multiple-starts-with.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/badgeclass-with-verification-valid-multiple-starts-with.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-with-allowed-origins-valid-starts-with.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/badgeclass-with-verification-valid-starts-with.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-with-allowed-origins.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/badgeclass-with-verification.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion-with-language.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "recipient": { 5 | "type": "email", 6 | "hashed": true, 7 | "salt": "deadsea", 8 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 9 | }, 10 | "id": "https://example.org/beths-robotics-badge.json", 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/badgeclass-with-language.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/basic-assertion.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/issuer-compact-iri-validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Issuer", 4 | "id": "https://example.org/organization.json", 5 | "url": "https://example.org", 6 | "name": "An Example Badge Issuer", 7 | "email": "contact@example.org", 8 | "verification": { 9 | "verificationProperty": "id" 10 | } 11 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/rdf-validation/badge-class-invalid-issuer-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "id": "http://example.org/badgeclass", 4 | "@language": "en-US", 5 | "name": "Example Badge", 6 | "description": "An example", 7 | "criteria": "http://example.com/badgecriteria.json", 8 | "issuer": "http://example.org/issuer-invalid-type.json", 9 | "type": "BadgeClass" 10 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/redirected-validation-subject.json: -------------------------------------------------------------------------------- 1 | { // both http://example.org/altbadgeurl and https://example.org/beths-robotics-badge.json return this json 2 | "@context": "https://w3id.org/openbadges/v2", // openbadges_context.json 3 | "type": "Assertion", 4 | "id": "http://example.org/altbadgeurl", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", // image 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "https://example.org/robotics-badge.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/simple-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob20/simple-badge.png -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/simple-not-revoked.jwt: -------------------------------------------------------------------------------- 1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvb3BlbmJhZGdlcy92MiIsInR5cGUiOiJBc3NlcnRpb24iLCJpZCI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmV0aHMtcm9ib3RpY3MtYmFkZ2UuanNvbiIsInJlY2lwaWVudCI6eyJ0eXBlIjoiZW1haWwiLCJoYXNoZWQiOnRydWUsInNhbHQiOiJkZWFkc2VhIiwiaWRlbnRpdHkiOiJzaGEyNTYkZWNmNTQwOWYzZjRiOTFhYjYwY2M1ZWY0YzAyYWVmNzAzMjM1NDM3NWU3MGNmNGQ4ZTQzZjZhMWQyOTg5MTk0MiJ9LCJpbWFnZSI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmV0aHMtcm9ib3QtYmFkZ2UucG5nIiwiZXZpZGVuY2UiOiJodHRwczovL2V4YW1wbGUub3JnL2JldGhzLXJvYm90LXdvcmsuaHRtbCIsImlzc3VlZE9uIjoiMjAxNi0xMi0zMVQyMzo1OTo1OVoiLCJiYWRnZSI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmFkZ2UtZnJvbS1vcmdhbml6YXRpb24td2l0aC1lbXB0eS1yZXZvY2F0aW9uLWxpc3QuanNvbiIsInZlcmlmaWNhdGlvbiI6eyJ0eXBlIjoic2lnbmVkIiwiY3JlYXRvciI6Imh0dHA6Ly9leGFtcGxlLm9yZy9rZXkyLmpzb24ifX0.gLjqNnlBSJ3oWt84iPhVaFjYGR2bhrSLDnTHh5mcjujO_VxYFop5EJlGHV4C7UC6xnM01Yy4y8JxqCIvLLudVRrPtK3pYumWJvGnc43cNyjZq8IY6L1qrsklP_gJyV0P9IKUzh6kQDdSGx_1TwYY3qwKlLXqNuxqkjdcD0z3zlhYfCnEpk7GZAXP_1Np123g-R9i3OZ18cxcUrCo1W7fZGkH4NXayXvdQpGwKmyCiju0N3ZLbHtfcbdWyVLLDF1RJJuRoVRgETly4uqVu8aFJ9O62HuOJggF7eLTos1gg-M2IpCa7yuUDVqGCWIRun5tbuUbJv_0Kg68lCslpZ09aw -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/simple-revoked.jwt: -------------------------------------------------------------------------------- 1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvb3BlbmJhZGdlcy92MiIsInR5cGUiOiJBc3NlcnRpb24iLCJpZCI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmV0aHMtcm9ib3RpY3MtYmFkZ2UtcmV2b2tlZC5qc29uIiwicmVjaXBpZW50Ijp7InR5cGUiOiJlbWFpbCIsImhhc2hlZCI6dHJ1ZSwic2FsdCI6ImRlYWRzZWEiLCJpZGVudGl0eSI6InNoYTI1NiRlY2Y1NDA5ZjNmNGI5MWFiNjBjYzVlZjRjMDJhZWY3MDMyMzU0Mzc1ZTcwY2Y0ZDhlNDNmNmExZDI5ODkxOTQyIn0sImltYWdlIjoiaHR0cHM6Ly9leGFtcGxlLm9yZy9iZXRocy1yb2JvdC1iYWRnZS5wbmciLCJldmlkZW5jZSI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmV0aHMtcm9ib3Qtd29yay5odG1sIiwiaXNzdWVkT24iOiIyMDE2LTEyLTMxVDIzOjU5OjU5WiIsImJhZGdlIjoiaHR0cHM6Ly9leGFtcGxlLm9yZy9iYWRnZS1mcm9tLW9yZ2FuaXphdGlvbi13aXRoLXJldm9jYXRpb24tbGlzdC5qc29uIiwidmVyaWZpY2F0aW9uIjp7InR5cGUiOiJzaWduZWQiLCJjcmVhdG9yIjoiaHR0cDovL2V4YW1wbGUub3JnL2tleTMuanNvbiJ9fQ.RPJ0gudgtSYwjlZLnMmPHuL_SZmlW46cD3GXE8JQgOk02RwofMUt1w14ey8x7nWexXhvoBIA63qT4S0MfVuMeznAzNMO9_Upm0fworkR500257402NoXTnyzvF8Z8j_bCfoDZrdvljHFCieE1txmhDvRLvR5_y8KaZ6XC3fggokqMUQj6Is6LO4rnazqQixZWT8h_mPbE18_lUi0ocvHdrkwVWIeQi8_B-vgsUOANoBkX9ALBwHnqgfmfOwd-zGV39rBY4lj2nAxoHmY4VClqRj3Qqzoml7bd2eIhFtkJUmxfFuKdcfVhknWqw72MDGb6T-iCKYjuBNhYdxw6i1yQg -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/simple.jwt: -------------------------------------------------------------------------------- 1 | eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvb3BlbmJhZGdlcy92MiIsInR5cGUiOiJBc3NlcnRpb24iLCJpZCI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmV0aHMtcm9ib3RpY3MtYmFkZ2UuanNvbiIsInJlY2lwaWVudCI6eyJ0eXBlIjoiZW1haWwiLCJoYXNoZWQiOnRydWUsInNhbHQiOiJkZWFkc2VhIiwiaWRlbnRpdHkiOiJzaGEyNTYkZWNmNTQwOWYzZjRiOTFhYjYwY2M1ZWY0YzAyYWVmNzAzMjM1NDM3NWU3MGNmNGQ4ZTQzZjZhMWQyOTg5MTk0MiJ9LCJpbWFnZSI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvYmV0aHMtcm9ib3QtYmFkZ2UucG5nIiwiZXZpZGVuY2UiOiJodHRwczovL2V4YW1wbGUub3JnL2JldGhzLXJvYm90LXdvcmsuaHRtbCIsImlzc3VlZE9uIjoiMjAxNi0xMi0zMVQyMzo1OTo1OVoiLCJiYWRnZSI6Imh0dHBzOi8vZXhhbXBsZS5vcmcvcm9ib3RpY3MtYmFkZ2UuanNvbiIsInZlcmlmaWNhdGlvbiI6eyJ0eXBlIjoic2lnbmVkIiwiY3JlYXRvciI6Imh0dHA6Ly9leGFtcGxlLm9yZy9rZXkxLmpzb24ifX0.bR5tt-GEneb7tdWfmDdCq2FCBRuvSnKxNIfMPVz4lXiLcC_MobAB1zC9VQTJ5wJMzyS7Z7SR6eqt5WjuV4gl-6cT1qm3Af4VaKMEpi5bc3w2EGMlw10YxYAIrFEmdAXod9jwA2hPd9k4ypuIIIyzThRAhxVY36vf6nZWkC11MNj0QJoAJ-q2JlaERaGnwSOf1h63jUIyWtsfs6ocXb_hiFIaxPKAqnJSnWeF672vo3lOG_0vM6Tk4Ug73DRzJOsJhGwSWWze_GmwgqtUcWS2b8HmpoEaS_1gXwqnhNxiNNN0a39P-MqP86cY6pb64WKcIVY0ZSnvb4mwzXzZ3cPOTg -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/warning-issuer-non-http.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/warning-issuer-non-http.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "issuedOn": "2016-12-31T23:59:59Z", 13 | "badge": "http://example.org/badge-with-bad-issuer.json", 14 | "verification": { 15 | "type": "hosted" 16 | } 17 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob20/warning-with-redirection.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://w3id.org/openbadges/v2", 3 | "type": "Assertion", 4 | "id": "https://example.org/beths-robotics-badge.json", 5 | "recipient": { 6 | "type": "email", 7 | "hashed": true, 8 | "salt": "deadsea", 9 | "identity": "sha256$ecf5409f3f4b91ab60cc5ef4c02aef7032354375e70cf4d8e43f6a1d29891942" 10 | }, 11 | "image": "https://example.org/beths-robot-badge.png", 12 | "evidence": "https://example.org/beths-robot-work.html", 13 | "issuedOn": "2016-12-31T23:59:59Z", 14 | "badge": "http://example.org/altbadgeurl.json", 15 | "verification": { 16 | "type": "hosted" 17 | } 18 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/bit-string-list/credential-status-revoked-blank-nodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/credential/54418d3f-ec01-4652-800a-861c890a51a1", 7 | "type": [ 8 | "VerifiableCredential", 9 | "AchievementCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://1edtech.edu/issuers/565049", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "address": { 17 | "type": [ 18 | "Address" 19 | ], 20 | "addressCountry": "Japan" 21 | }, 22 | "name": "1EdTech Testing" 23 | }, 24 | "awardedDate": "2023-05-22T10:21:00Z", 25 | "validFrom": "2023-05-23T01:10:41Z", 26 | "name": "ob3-credential-status-revoked.json", 27 | "description": "This achievement credential is used in ims-inspector OB30Tests.", 28 | "credentialSubject": { 29 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:learner:6896f98f-6b42-4c75-98ec-8befd0dc0b29", 30 | "type": [ 31 | "AchievementSubject" 32 | ], 33 | "achievement": { 34 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/achievement/45badd38-e201-4cf3-927f-be55bc7eb414", 35 | "type": [ 36 | "Achievement" 37 | ], 38 | "achievementType": "Achievement", 39 | "criteria": { 40 | "narrative": "Passes tests" 41 | }, 42 | "description": "Test achievement 1", 43 | "name": "Achievement 1" 44 | }, 45 | "source": { 46 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c", 47 | "type": [ 48 | "Profile" 49 | ], 50 | "address": { 51 | "type": [ 52 | "Address" 53 | ], 54 | "addressCountry": "Spain" 55 | }, 56 | "name": "1EdTech Testing Creator" 57 | } 58 | }, 59 | "credentialStatus": { 60 | "id": "https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/refs/heads/main/inspector-vc/src/test/resources/ob30/bit-string-list/testlist#23", 61 | "type": "BitstringStatusListEntry", 62 | "statusPurpose": "revocation", 63 | "statusListIndex": "23", 64 | "statusListCredential": "https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/refs/heads/main/inspector-vc/src/test/resources/ob30/bit-string-list/testlist" 65 | }, 66 | "proof": [{ 67 | "type": "DataIntegrityProof", 68 | "created": "2010-01-01T19:23:24Z", 69 | "verificationMethod": "https://1edtech.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 70 | "cryptosuite": "eddsa-rdfc-2022", 71 | "proofPurpose": "assertionMethod", 72 | "proofValue": "z5115zWQJQk3ni4BQVMevgw693c7xv1DNoH27mZUk9CVS69aaEtG86BYVXbe8pqcDUMCHxZtynj5vQwDdimrzhmq8" 73 | }] 74 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/bit-string-list/credential-status-revoked.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/credential/54418d3f-ec01-4652-800a-861c890a51a1", 7 | "type": [ 8 | "VerifiableCredential", 9 | "AchievementCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://1edtech.edu/issuers/565049", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "1EdTech Testing" 17 | }, 18 | "awardedDate": "2023-05-22T10:21:00Z", 19 | "validFrom": "2023-05-23T01:10:41Z", 20 | "name": "ob3-credential-status-revoked.json", 21 | "description": "This achievement credential is used in ims-inspector OB30Tests.", 22 | "credentialSubject": { 23 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:learner:6896f98f-6b42-4c75-98ec-8befd0dc0b29", 24 | "type": [ 25 | "AchievementSubject" 26 | ], 27 | "achievement": { 28 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/achievement/45badd38-e201-4cf3-927f-be55bc7eb414", 29 | "type": [ 30 | "Achievement" 31 | ], 32 | "achievementType": "Achievement", 33 | "criteria": { 34 | "narrative": "Passes tests" 35 | }, 36 | "description": "Test achievement 1", 37 | "name": "Achievement 1" 38 | }, 39 | "source": { 40 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c", 41 | "type": [ 42 | "Profile" 43 | ], 44 | "name": "1EdTech Testing" 45 | } 46 | }, 47 | "credentialStatus": { 48 | "id": "https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/refs/heads/main/inspector-vc/src/test/resources/ob30/bit-string-list/testlist#23", 49 | "type": "BitstringStatusListEntry", 50 | "statusPurpose": "revocation", 51 | "statusListIndex": "23", 52 | "statusListCredential": "https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/refs/heads/main/inspector-vc/src/test/resources/ob30/bit-string-list/testlist" 53 | }, 54 | "proof": [{ 55 | "type": "DataIntegrityProof", 56 | "created": "2010-01-01T19:23:24Z", 57 | "verificationMethod": "https://1edtech.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 58 | "cryptosuite": "eddsa-rdfc-2022", 59 | "proofPurpose": "assertionMethod", 60 | "proofValue": "z5xRU4TJpeDQBpa3txAq72FPsfHHhMPHHgm3WVWxkVnd6qoxKysSZfZwkCkuWoxjx4WnkSn425jJ76gkJydXhV5pr" 61 | }] 62 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/bit-string-list/testlist: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2" 4 | ], 5 | "id": "https://example.com/credentials/status/3", 6 | "type": [ 7 | "VerifiableCredential", 8 | "BitstringStatusListCredential" 9 | ], 10 | "issuer": "https://1edtech.edu/issuers/565049", 11 | "validFrom": "2021-04-05T14:27:40Z", 12 | "credentialSubject": { 13 | "id": "https://example.com/status/3#list", 14 | "type": "BitstringStatusList", 15 | "statusPurpose": "revocation", 16 | "encodedList": "uH4sIAAAAAAAA_-3BMQEAAAzDoMy_6cnoA9QFAAAAAAAAAAAAAAAAAAAAbD3uPa2cAEAAAA" 17 | }, 18 | "proof": [{ 19 | "type": "DataIntegrityProof", 20 | "created": "2010-01-01T19:23:24Z", 21 | "verificationMethod": "https://1edtech.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 22 | "cryptosuite": "eddsa-rdfc-2022", 23 | "proofPurpose": "assertionMethod", 24 | "proofValue": "z2SkF4nJzMa6wAKgxDdUR1wwZsiYnWi3CtFyRipnMgxUTZKiJvJ1tf5fEtmDFhjkc2JL6XgPTt5SzBCJFSTpBMdDY" 25 | }] 26 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/credential-status-revoked.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.1.json", 5 | "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json", 6 | "https://w3id.org/security/suites/ed25519-2020/v1" 7 | ], 8 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/credential/54418d3f-ec01-4652-800a-861c890a51a1", 9 | "type": [ 10 | "VerifiableCredential", 11 | "AchievementCredential" 12 | ], 13 | "issuer": { 14 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c", 15 | "type": "Profile", 16 | "address": { 17 | "type": "Address", 18 | "addressCountry": "Japan" 19 | }, 20 | "name": "1EdTech Testing" 21 | }, 22 | "awardedDate": "2023-05-22T10:21:00Z", 23 | "issuanceDate": "2023-05-23T01:10:41Z", 24 | "name": "ob3-credential-status-revoked.json", 25 | "description": "This achievement credential is used in ims-inspector OB30Tests.", 26 | "credentialSubject": { 27 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:learner:6896f98f-6b42-4c75-98ec-8befd0dc0b29", 28 | "type": "AchievementSubject", 29 | "achievement": { 30 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/achievement/45badd38-e201-4cf3-927f-be55bc7eb414", 31 | "type": "Achievement", 32 | "achievementType": "Achievement", 33 | "criteria": { 34 | "narrative": "Passes tests" 35 | }, 36 | "description": "Test achievement 1", 37 | "name": "Achievement 1" 38 | }, 39 | "source": { 40 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c", 41 | "type": "Profile", 42 | "address": { 43 | "type": "Address", 44 | "addressCountry": "Japan" 45 | }, 46 | "name": "1EdTech Testing" 47 | } 48 | }, 49 | "credentialStatus": { 50 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/api/revocations/da1e96e9-afcc-4eed-b9a2-2ddf7353214c", 51 | "type": "1EdTechRevocationList" 52 | }, 53 | "refreshService": { 54 | "id": "https://dc.1edtech.org/wellspring2022/wellspring-portal/api/refresh/54418d3f-ec01-4652-800a-861c890a51a1", 55 | "type": "1EdTechCredentialRefresh" 56 | }, 57 | "proof": { 58 | "type": "Ed25519Signature2020", 59 | "created": "2010-01-01T19:23:24Z", 60 | "verificationMethod": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:org:da1e96e9-afcc-4eed-b9a2-2ddf7353214c#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 61 | "proofPurpose": "assertionMethod", 62 | "proofValue": "z3iKMEzqoa1gMf5kZnYeyuNjy1KPYfJE39W9FEMhZ7Hf8S3ESB2wRFR3zVsVit4TkCrv3J5QGwRLLpiYgr2tU4pCg" 63 | } 64 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/endorsement-err-schema-status-refresh.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context.json", 5 | "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json", 6 | "https://w3id.org/security/suites/ed25519-2020/v1" 7 | ], 8 | "id": "http://1edtech.edu/endorsementcredential/3732", 9 | "type": [ 10 | "VerifiableCredential", 11 | "EndorsementCredential" 12 | ], 13 | "issuer": { 14 | "id": "https://state.gov/issuers/565049", 15 | "type": "Profile", 16 | "name": "State Department of Education" 17 | }, 18 | "name": "Example endorsement", 19 | "issuanceDate": "2010-01-01T00:00:00Z", 20 | "expirationDate": "2030-01-01T00:00:00Z", 21 | "credentialSubject": { 22 | "id": "https://1edtech.edu/issuers/565049", 23 | "type": "EndorsementSubject", 24 | "endorsementComment": "1EdTech University is in good standing" 25 | }, 26 | "credentialSchema": [ 27 | { 28 | "id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_endorsementcredential_schema.json", 29 | "type": "1EdTechJsonSchemaValidator2019" 30 | }, 31 | { 32 | "id": "https://state.gov/schema/endorsementcredential.json", 33 | "type": "1EdTechJsonSchemaValidator2019" 34 | } 35 | ], 36 | "credentialStatus": { 37 | "id": "https://state.gov/credentials/3732/revocations", 38 | "type": "1EdTechRevocationList" 39 | }, 40 | "refreshService": { 41 | "id": "http://state.gov/credentials/3732", 42 | "type": "1EdTechCredentialRefresh" 43 | }, 44 | "proof": [ 45 | { 46 | "type": "Ed25519Signature2020", 47 | "created": "2022-12-15T16:53:56Z", 48 | "verificationMethod": "https://state.gov/issuers/565049#z6MkmQ49FhpMN7V11B7Qzc6WC6Q3ymVW4xmHUsHBR2MWMMo1", 49 | "proofPurpose": "assertionMethod", 50 | "proofValue": "z36uHeAeKagDGaXMSqQX1eyKg4rFsWHzYLHxXfypkysPsvTtwN3Z8VZQtn7VQovX2GjkEWgGaW7hQ3UkNKbR84nUn" 51 | } 52 | ] 53 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/endorsement-valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json", 5 | "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json" 6 | ], 7 | "id": "http://1edtech.edu/endorsementcredential/3732", 8 | "type": [ 9 | "VerifiableCredential", 10 | "EndorsementCredential" 11 | ], 12 | "issuer": { 13 | "id": "https://state.gov/issuers/565049", 14 | "type": [ 15 | "Profile" 16 | ], 17 | "name": "State Department of Education" 18 | }, 19 | "validFrom": "2010-01-01T00:00:00Z", 20 | "validUntil": "2030-01-01T00:00:00Z", 21 | "name": "Example endorsement", 22 | "credentialSubject": { 23 | "id": "https://1edtech.edu/issuers/565049", 24 | "type": [ 25 | "EndorsementSubject" 26 | ], 27 | "endorsementComment": "1EdTech University is in good standing" 28 | }, 29 | "credentialSchema": [ 30 | { 31 | "id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_endorsementcredential_schema.json", 32 | "type": "1EdTechJsonSchemaValidator2019" 33 | } 34 | ], 35 | "proof": [{ 36 | "type": "DataIntegrityProof", 37 | "created": "2010-01-01T19:23:24Z", 38 | "verificationMethod": "https://state.gov/issuers/565049#z6MkoMGF38Ck9xkdqrbZt4h9eHb1qc3GhAAkoSWa4Vy3SHRN", 39 | "cryptosuite": "eddsa-rdfc-2022", 40 | "proofPurpose": "assertionMethod", 41 | "proofValue": "z4DKZeDFKKvz5dDVPEky9NU8Zk3J8tH62Vtnm7drwwvPhDKwd6wL6td8skZkbyqw17y5zNJxfjT42dKpQc3Mgx1x6" 42 | }] 43 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-context-alias.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "name": "Teamwork Badge", 19 | "credentialSubject": { 20 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 21 | "type": [ 22 | "AchievementSubject" 23 | ], 24 | "achievement": { 25 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 26 | "type": [ 27 | "Achievement" 28 | ], 29 | "criteria": { 30 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 31 | }, 32 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 33 | "name": "Teamwork" 34 | } 35 | }, 36 | "validFrom": "2024-03-21T14:56:35Z", 37 | "proof": [{ 38 | "type": "DataIntegrityProof", 39 | "created": "2010-01-01T19:23:24Z", 40 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 41 | "cryptosuite": "eddsa-rdfc-2022", 42 | "proofPurpose": "assertionMethod", 43 | "proofValue": "z4sG6oe7cR9GszKfEkjoYr4Kig1k9R8CTBEeqxhNt1qj3MKZW3w8AjE86k3QQpkYYyD74QDj2maQX8pbKHem9Bs6B" 44 | }] 45 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-context-version.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.2.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "proof": [{ 38 | "type": "DataIntegrityProof", 39 | "created": "2010-01-01T19:23:24Z", 40 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 41 | "cryptosuite": "eddsa-rdfc-2022", 42 | "proofPurpose": "assertionMethod", 43 | "proofValue": "zD8RrkKVSVEPYspwCe9T1a68NAVt2GyV566uR6QLdxCMdkg2b4rdUf9w1BC8ZEyhGdEz13kzkBwkjTTvoYAYsy15" 44 | }] 45 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-did-key-method.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json", 5 | "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json" 6 | ], 7 | "id": "urn:uuid:280c19b6-9680-4a37-ba84-e38b1a4e4584", 8 | "type": [ 9 | "VerifiableCredential", 10 | "AchievementCredential" 11 | ], 12 | "issuer": { 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Andy F. Miller", 17 | "id": "urn:uuid:6f2e33e5-7a29-4155-840a-59483ba10164" 18 | }, 19 | "validFrom": "2022-11-10T07:38:00-08:00", 20 | "name": "test 1", 21 | "credentialSubject": { 22 | "id": "urn:uuid:6f2e33e5-7a29-4155-840a-59483ba10164", 23 | "type": [ 24 | "AchievementSubject" 25 | ], 26 | "achievement": { 27 | "id": "urn:uuid:35258e6f-4c05-4215-8ada-38a5a5b80510", 28 | "type": [ 29 | "Achievement" 30 | ], 31 | "achievementType": "Achievement", 32 | "name": "test 1", 33 | "description": "This is a test achievement", 34 | "criteria": { 35 | "narrative": "There is no criteria" 36 | } 37 | } 38 | }, 39 | "proof": [{ 40 | "type": "DataIntegrityProof", 41 | "created": "2010-01-01T19:23:24Z", 42 | "verificationMethod": "did:key:z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 43 | "cryptosuite": "eddsa-rdfc-2022", 44 | "proofPurpose": "assertionMethod", 45 | "proofValue": "z5v2mkEWTLxzJ4VCxvUx5dRoy54Hp81GpyABUk7NswQECwDH6Ecwv5F3Mqso7t18UY6WScm5Qszo6nqiiqmevRWHc" 46 | }] 47 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-did-web-method.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://1edtech.edu/issuers/565049", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "url": "https://www.imsglobal.org", 17 | "name": "Example Corp" 18 | }, 19 | "validFrom": "2010-01-01T00:00:00Z", 20 | "awardedDate": "2010-01-01T00:00:00Z", 21 | "name": "Teamwork Badge", 22 | "credentialSubject": { 23 | "id": "did:web:dc.1edtech.org:wellspring2022:wellspring-portal:learner:e42a88f4-7e1d-429b-bcea-0f3b31ee4e5d", 24 | "name": "Xavi Aracil's Teamwork Badge", 25 | "type": [ 26 | "AchievementSubject" 27 | ], 28 | "achievement": { 29 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 30 | "type": [ 31 | "Achievement" 32 | ], 33 | "criteria": { 34 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 35 | }, 36 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 37 | "name": "Teamwork" 38 | } 39 | }, 40 | "proof": { 41 | "type": "DataIntegrityProof", 42 | "created": "2010-01-01T19:23:24Z", 43 | "verificationMethod": "https://1edtech.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 44 | "cryptosuite": "eddsa-rdfc-2022", 45 | "proofPurpose": "assertionMethod", 46 | "proofValue": "z5MAVhNZYag5uSBiiNFepcUuToSnqRrVHHFYZdxV94bbreyMaQBdmW5839wSPSzb2qMEYRyUjV2oz6hzQbiD24Rdx" 47 | } 48 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-eddsa-2022.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.1.json", 5 | "https://w3id.org/security/data-integrity/v1" 6 | ], 7 | "type": ["VerifiableCredential", "AchievementCredential"], 8 | "id": "http://www.1edtech.org/ob/1", 9 | "issuanceDate": "2022-11-27T00:00:00Z", 10 | "credentialSubject": { 11 | "type": ["AchievementSubject"], 12 | "id": "did:1edtech:1", 13 | "achievement": { 14 | "id": "did:1edtech:achievement:1", 15 | "type": ["Achievement"], 16 | "criteria": { "narrative": "some narrative" }, 17 | "description": "some description", 18 | "name": "some name" 19 | } 20 | }, 21 | "name": "Some name", 22 | "issuer": { "id": "https://example.com/issuers/876543", "type": ["Profile"] }, 23 | "proof": [{ 24 | "type": "DataIntegrityProof", 25 | "created": "2023-05-29T08:42:26Z", 26 | "proofPurpose": "assertionMethod", 27 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 28 | "cryptosuite": "eddsa-2022", 29 | "proofValue": "z2H1miRAGKPRCPUSudNTPrsWyvpRZzgtgjPBmnMkbcwR8StwEv8dr3NigviBgvZwBu8yA7wAyF5qLjyo3zN1UqLR2" 30 | }] 31 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-context.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 4 | ], 5 | "id": "http://example.edu/credentials/3732", 6 | "type": [ 7 | "VerifiableCredential", 8 | "OpenBadgeCredential" 9 | ], 10 | "issuer": { 11 | "id": "https://example.edu/issuers/565049", 12 | "type": [ 13 | "Profile" 14 | ], 15 | "name": "Example University" 16 | }, 17 | "issuanceDate": "2010-01-01T00:00:00Z", 18 | "name": "Example University Degree", 19 | "credentialSubject": { 20 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 21 | "type": [ 22 | "AchievementSubject" 23 | ] 24 | }, 25 | "proof": [ 26 | { 27 | "type": "DataIntegrityProof", 28 | "created": "2024-03-20T14:53:19Z", 29 | "verificationMethod": "https://example.com/issuers/876543#z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x", 30 | "cryptosuite": "eddsa-rdfc-2022", 31 | "proofPurpose": "assertionMethod", 32 | "proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-credential-subject-identifier-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "identifier": [ 22 | { 23 | "type": "InvalidIdentityObject", 24 | "hashed": true, 25 | "identityHash": "asdjhsadas", 26 | "identityType": "lisSourcedId" 27 | } 28 | ], 29 | "type": [ 30 | "AchievementSubject" 31 | ], 32 | "achievement": { 33 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 34 | "type": [ 35 | "Achievement" 36 | ], 37 | "criteria": { 38 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 39 | }, 40 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 41 | "name": "Teamwork" 42 | } 43 | }, 44 | "proof": { 45 | "type": "DataIntegrityProof", 46 | "created": "2010-01-01T19:23:24Z", 47 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 48 | "cryptosuite": "eddsa-rdfc-2022", 49 | "proofPurpose": "assertionMethod", 50 | "proofValue": "z5M8kUcxhKZ8niHpZt1LUBLrJGeLMnYaCmwrdR7MrcGzyiGz65zkk59212f7xpd7odxGVDp4e6MvNABsQ8YGn7U98" 51 | } 52 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-credential-subject-profile-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | }, 36 | "source": { 37 | "id": "https://school.edu/issuers/201234", 38 | "type": "InvalidProfile", 39 | "name": "1EdTech College of Arts" 40 | } 41 | }, 42 | "proof": { 43 | "type": "DataIntegrityProof", 44 | "created": "2010-01-01T19:23:24Z", 45 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 46 | "cryptosuite": "eddsa-rdfc-2022", 47 | "proofPurpose": "assertionMethod", 48 | "proofValue": "z5kJkNSdserQduikVPAfEZ3qMPQRkyvcB7tTaNuxjqNZioQmijmWouvBqSGnAeKKoXAavTk4cxY94iuiEW9boXVyV" 49 | } 50 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-credential-subject-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "InvalidAchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "proof": { 38 | "type": "DataIntegrityProof", 39 | "created": "2010-01-01T19:23:24Z", 40 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 41 | "cryptosuite": "eddsa-rdfc-2022", 42 | "proofPurpose": "assertionMethod", 43 | "proofValue": "z57amKtkLGz6Gs4s1R7hcgkWzrxayXt7HZ4L5Gt8VBGcM2Z4881fEDARqa8pM2N2dniqXz3U4cC6zW3UBfkQZCfN" 44 | } 45 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-evidence-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "evidence": [ 38 | { 39 | "id": "https://1edtech.edu/credentials/3732/evidence/1", 40 | "type": "Evidence", 41 | "narrative": "# Final Project Report \n This project was ...", 42 | "name": "Final Project Report", 43 | "description": "This is the final project report.", 44 | "genre": "Research", 45 | "audience": "Department" 46 | }, 47 | { 48 | "id": "https://github.com/somebody/project", 49 | "type": "InvalidEvidence", 50 | "name": "Final Project Code", 51 | "description": "This is the source code for the final project app.", 52 | "genre": "Research", 53 | "audience": "Department" 54 | } 55 | ], 56 | "proof": { 57 | "type": "DataIntegrityProof", 58 | "created": "2010-01-01T19:23:24Z", 59 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 60 | "cryptosuite": "eddsa-rdfc-2022", 61 | "proofPurpose": "assertionMethod", 62 | "proofValue": "zbXsNxLTdGdCTdyfkefLRenndjs6QoXnwCYtNbXj4ZtwxrGa2xctb78XrBjuTNK8FKskysBYvMuSzvWYSzfzTXWX" 63 | } 64 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-expired.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "validUntil": "2010-01-01T00:00:00Z", 20 | "name": "Teamwork Badge", 21 | "credentialSubject": { 22 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 23 | "type": [ 24 | "AchievementSubject" 25 | ], 26 | "achievement": { 27 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 28 | "type": [ 29 | "Achievement" 30 | ], 31 | "criteria": { 32 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 33 | }, 34 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 35 | "name": "Teamwork" 36 | } 37 | }, 38 | "proof": [{ 39 | "type": "DataIntegrityProof", 40 | "created": "2010-01-01T19:23:24Z", 41 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 42 | "cryptosuite": "eddsa-rdfc-2022", 43 | "proofPurpose": "assertionMethod", 44 | "proofValue": "z2mAP6ezimojRWSHDhS1VfJgDdMCqa4oPbmJT1tCs43t5bRiwsrrhHxrmTEeAF2EBjErrzxoJj3HCKsdkyVkno11f" 45 | }] 46 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-issued.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.edu/credentials/3732", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.edu/issuers/565049", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example University" 17 | }, 18 | "validFrom": "2040-01-01T00:00:00Z", 19 | "validUntil": "2050-01-20T00:00:00Z", 20 | "name": "Example University Degree", 21 | "credentialSubject": { 22 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 23 | "type": [ 24 | "AchievementSubject" 25 | ] 26 | }, 27 | "proof": { 28 | "type": "DataIntegrityProof", 29 | "created": "2010-01-01T19:23:24Z", 30 | "verificationMethod": "https://example.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 31 | "cryptosuite": "eddsa-rdfc-2022", 32 | "proofPurpose": "assertionMethod", 33 | "proofValue": "z5EUB8AAu98Tdagjaf6QP7zY7MovnYTEB6vnNBgWjaCtaiNQfqNLQmEPpxvQuQPmVfQ49wcadz3DNUDk4CAt79HaF" 34 | } 35 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-issuer-otheridentifier-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp", 17 | "otherIdentifier": [ 18 | { 19 | "type": "IdentifierEntry", 20 | "identifier": "12345", 21 | "identifierType": "sourcedId" 22 | }, 23 | { 24 | "type": "InvalidIdentifierEntry", 25 | "identifier": "67890", 26 | "identifierType": "nationalIdentityNumber" 27 | } 28 | ] 29 | }, 30 | "validFrom": "2010-01-01T00:00:00Z", 31 | "name": "Teamwork Badge", 32 | "credentialSubject": { 33 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 34 | "type": [ 35 | "AchievementSubject" 36 | ], 37 | "achievement": { 38 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 39 | "type": [ 40 | "Achievement" 41 | ], 42 | "criteria": { 43 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 44 | }, 45 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 46 | "name": "Teamwork" 47 | } 48 | }, 49 | "proof": { 50 | "type": "DataIntegrityProof", 51 | "created": "2010-01-01T19:23:24Z", 52 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 53 | "cryptosuite": "eddsa-rdfc-2022", 54 | "proofPurpose": "assertionMethod", 55 | "proofValue": "z3y8SeYGgaCjgeqe5vbKv9egn5zxHPoFNDYRXa9pHPxMua2P9PEinYmmjq12FqXYr272DhKj6tvBTCzvx3KRc8ys8" 56 | } 57 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-issuer-parentorg-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp", 17 | "parentOrg": { 18 | "id": "https://example.com/issuers/876543", 19 | "type": [ 20 | "InvalidProfile" 21 | ], 22 | "name": "Example Parent Corp" 23 | } 24 | }, 25 | "validFrom": "2010-01-01T00:00:00Z", 26 | "name": "Teamwork Badge", 27 | "credentialSubject": { 28 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 29 | "type": [ 30 | "AchievementSubject" 31 | ], 32 | "achievement": { 33 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 34 | "type": [ 35 | "Achievement" 36 | ], 37 | "criteria": { 38 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 39 | }, 40 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 41 | "name": "Teamwork" 42 | } 43 | }, 44 | "proof": { 45 | "type": "DataIntegrityProof", 46 | "created": "2010-01-01T19:23:24Z", 47 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 48 | "cryptosuite": "eddsa-rdfc-2022", 49 | "proofPurpose": "assertionMethod", 50 | "proofValue": "z3f57gU5zssuyZTW2HxK2tV6qXCHyE3xdCHCczsUoRMSDBooCGboVBWUZygqpqskN5Mmpww8Qu3JARf1YvGcCzE34" 51 | } 52 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-issuer-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "InvalidProfile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "proof": { 38 | "type": "DataIntegrityProof", 39 | "created": "2010-01-01T19:23:24Z", 40 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 41 | "cryptosuite": "eddsa-rdfc-2022", 42 | "proofPurpose": "assertionMethod", 43 | "proofValue": "z2t8HUUbHs1G3o5t1uCTA7kbdprP21W9xmf8qJaDBWBoHSBFvJB26Bdq7Fi1ko2cnaHAvXETdMX6dPGFSA2rTP4KW" 44 | } 45 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-issuer.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.edu/credentials/3732", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "validFrom": "2010-01-01T00:00:00Z", 12 | "name": "Example University Degree", 13 | "credentialSubject": { 14 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 15 | "type": [ 16 | "AchievementSubject" 17 | ] 18 | }, 19 | "proof": { 20 | "type": "DataIntegrityProof", 21 | "created": "2010-01-01T19:23:24Z", 22 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 23 | "cryptosuite": "eddsa-rdfc-2022", 24 | "proofPurpose": "assertionMethod", 25 | "proofValue": "z5ZjnJNPeQznivpmedtQZDAy9vXVz2BbhZp13fGpTfMnsgzccs2Z3Se2BRWeECSMo92cUsQP63LhMb6veWuD223j2" 26 | } 27 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-proof-method-no-scheme.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": ["VerifiableCredential", "OpenBadgeCredential"], 8 | "issuer": { 9 | "id": "https://example.com/issuers/876543", 10 | "type": ["Profile"], 11 | "name": "Example Corp" 12 | }, 13 | "validFrom": "2010-01-01T00:00:00Z", 14 | "name": "Teamwork Badge", 15 | "credentialSubject": { 16 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 17 | "type": ["AchievementSubject"], 18 | "achievement": { 19 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 20 | "type": ["Achievement"], 21 | "criteria": { 22 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 23 | }, 24 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 25 | "name": "Teamwork" 26 | } 27 | }, 28 | "proof": [ 29 | { 30 | "type": "DataIntegrityProof", 31 | "created": "2024-03-20T14:53:19Z", 32 | "verificationMethod": "z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x", 33 | "cryptosuite": "eddsa-rdfc-2022", 34 | "proofPurpose": "assertionMethod", 35 | "proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV" 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-proof-method-unknown-did-method.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": ["VerifiableCredential", "OpenBadgeCredential"], 8 | "issuer": { 9 | "id": "https://example.com/issuers/876543", 10 | "type": ["Profile"], 11 | "name": "Example Corp" 12 | }, 13 | "validFrom": "2010-01-01T00:00:00Z", 14 | "name": "Teamwork Badge", 15 | "credentialSubject": { 16 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 17 | "type": ["AchievementSubject"], 18 | "achievement": { 19 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 20 | "type": ["Achievement"], 21 | "criteria": { 22 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 23 | }, 24 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 25 | "name": "Teamwork" 26 | } 27 | }, 28 | "proof": [ 29 | { 30 | "type": "DataIntegrityProof", 31 | "created": "2024-03-20T14:53:19Z", 32 | "verificationMethod": "did:example:z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x", 33 | "cryptosuite": "eddsa-rdfc-2022", 34 | "proofPurpose": "assertionMethod", 35 | "proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV" 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-proof-method-unknown-scheme.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": ["VerifiableCredential", "OpenBadgeCredential"], 8 | "issuer": { 9 | "id": "https://example.com/issuers/876543", 10 | "type": ["Profile"], 11 | "name": "Example Corp" 12 | }, 13 | "validFrom": "2010-01-01T00:00:00Z", 14 | "name": "Teamwork Badge", 15 | "credentialSubject": { 16 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 17 | "type": ["AchievementSubject"], 18 | "achievement": { 19 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 20 | "type": ["Achievement"], 21 | "criteria": { 22 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 23 | }, 24 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 25 | "name": "Teamwork" 26 | } 27 | }, 28 | "proof": [ 29 | { 30 | "type": "DataIntegrityProof", 31 | "created": "2024-03-20T14:53:19Z", 32 | "verificationMethod": "xxx:z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x", 33 | "cryptosuite": "eddsa-rdfc-2022", 34 | "proofPurpose": "assertionMethod", 35 | "proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LnVFodwov9rPQxi3QRP7adCrzV" 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-proof-method.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json", 5 | "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json" 6 | ], 7 | "id": "http://example.edu/credentials/3732", 8 | "type": [ 9 | "VerifiableCredential", 10 | "OpenBadgeCredential" 11 | ], 12 | "issuer": { 13 | "id": "https://example.edu/issuers/565049", 14 | "type": [ 15 | "Profile" 16 | ], 17 | "name": "Example University" 18 | }, 19 | "validFrom": "2010-01-01T00:00:00Z", 20 | "name": "Example University Degree", 21 | "credentialSubject": { 22 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 23 | "type": [ 24 | "AchievementSubject" 25 | ], 26 | "achievement": { 27 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 28 | "type": [ 29 | "Achievement" 30 | ], 31 | "criteria": { 32 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 33 | }, 34 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 35 | "name": "Teamwork" 36 | } 37 | }, 38 | "credentialSchema": [ 39 | { 40 | "id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_achievementcredential_schema.json", 41 | "type": "1EdTechJsonSchemaValidator2019" 42 | } 43 | ], 44 | "proof": { 45 | "type": "DataIntegrityProof", 46 | "created": "2010-01-01T19:23:24Z", 47 | "verificationMethod": "https://example.edu/issuers/565049#z6MkjZRsdasZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 48 | "cryptosuite": "eddsa-rdfc-2022", 49 | "proofPurpose": "assertionMethod", 50 | "proofValue": "z4HwAsa7GvwL7so7CoQ8v3ShzykRPCq8pfkAFKuAPrJx28S69pXphpqL8ApjoxEcMaqbgkaCUyKuEohhGXBR4Fh3L" 51 | } 52 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-proof-value.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": ["VerifiableCredential", "OpenBadgeCredential"], 8 | "issuer": { 9 | "id": "https://example.com/issuers/876543", 10 | "type": ["Profile"], 11 | "name": "Example Corp" 12 | }, 13 | "validFrom": "2010-01-01T00:00:00Z", 14 | "name": "Teamwork Badge", 15 | "credentialSubject": { 16 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 17 | "type": ["AchievementSubject"], 18 | "achievement": { 19 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 20 | "type": ["Achievement"], 21 | "criteria": { 22 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 23 | }, 24 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 25 | "name": "Teamwork" 26 | } 27 | }, 28 | "proof": [ 29 | { 30 | "type": "DataIntegrityProof", 31 | "created": "2024-03-20T14:53:19Z", 32 | "verificationMethod": "https://example.com/issuers/876543#z6MkrvfzkMnvCroEUP2DVc9SHPE48CRsvHiVSusHioxTYu1x", 33 | "cryptosuite": "eddsa-rdfc-2022", 34 | "proofPurpose": "assertionMethod", 35 | "proofValue": "z76jrNcyxHg5fV17h96yCRwqUaTQZD2QQivyNqHyLSvqu3aWGC3nLShzZEGbH3LvNFodwov9rPQxi3QRP7adCrzV" 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-err-type.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.edu/credentials/3732", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OtherCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.edu/issuers/565049", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example University" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Example University Degree", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ] 25 | }, 26 | "proof": { 27 | "type": "DataIntegrityProof", 28 | "created": "2010-01-01T19:23:24Z", 29 | "verificationMethod": "https://example.edu/issuers/565049#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 30 | "cryptosuite": "eddsa-rdfc-2022", 31 | "proofPurpose": "assertionMethod", 32 | "proofValue": "z662W1sSqKoA8ryTKK7PPVGKRrBkx5id3aDvdFNtguJcVFHJggDnkwJFntbo2cWfSwumCh9mgcYUe2RgpK1GZFyxa" 33 | } 34 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob30/simple-json.png -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-jwt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob30/simple-jwt.png -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-jwt_v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1EdTech/digital-credentials-public-validator/0442cf4fe3defda269e0816ab3833c31fa16a312/inspector-vc/src/test/resources/ob30/simple-jwt_v1.png -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-multiple-proofs.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "proof": [ 38 | { 39 | "type": "SomeProofType", 40 | "created": "2022-11-16T18:54:22Z", 41 | "proofPurpose": "assertionMethod" 42 | }, 43 | { 44 | "type": "DataIntegrityProof", 45 | "created": "2010-01-01T19:23:24Z", 46 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 47 | "cryptosuite": "eddsa-rdfc-2022", 48 | "proofPurpose": "assertionMethod", 49 | "proofValue": "z41ZsNkz78FHSGkAD5J4b8EN49DkywMMJSL3UdUNffbsCAWmTLPvtnJpd3JGGooYX7TNrzgsTLkXUWiGsRRZ788ML" 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple-noproof.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context.json", 5 | "https://w3id.org/security/suites/ed25519-2020/v1" 6 | ], 7 | "id": "http://example.edu/credentials/3732", 8 | "type": [ 9 | "VerifiableCredential", 10 | "OpenBadgeCredential" 11 | ], 12 | "issuer": { 13 | "id": "https://example.edu/issuers/565049", 14 | "type": [ 15 | "Profile" 16 | ], 17 | "name": "Example University" 18 | }, 19 | "issuanceDate": "2010-01-01T00:00:00Z", 20 | "name": "Example University Degree", 21 | "credentialSubject": { 22 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 23 | "type": [ 24 | "AchievementSubject" 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple.1ob: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "proof": [{ 38 | "type": "DataIntegrityProof", 39 | "created": "2010-01-01T19:23:24Z", 40 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 41 | "cryptosuite": "eddsa-rdfc-2022", 42 | "proofPurpose": "assertionMethod", 43 | "proofValue": "z41ZsNkz78FHSGkAD5J4b8EN49DkywMMJSL3UdUNffbsCAWmTLPvtnJpd3JGGooYX7TNrzgsTLkXUWiGsRRZ788ML" 44 | }] 45 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/ns/credentials/v2", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": [ 8 | "VerifiableCredential", 9 | "OpenBadgeCredential" 10 | ], 11 | "issuer": { 12 | "id": "https://example.com/issuers/876543", 13 | "type": [ 14 | "Profile" 15 | ], 16 | "name": "Example Corp" 17 | }, 18 | "validFrom": "2010-01-01T00:00:00Z", 19 | "name": "Teamwork Badge", 20 | "credentialSubject": { 21 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 22 | "type": [ 23 | "AchievementSubject" 24 | ], 25 | "achievement": { 26 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 27 | "type": [ 28 | "Achievement" 29 | ], 30 | "criteria": { 31 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 32 | }, 33 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 34 | "name": "Teamwork" 35 | } 36 | }, 37 | "proof": [{ 38 | "type": "DataIntegrityProof", 39 | "created": "2010-01-01T19:23:24Z", 40 | "verificationMethod": "https://example.com/issuers/876543#z6MkjZRZv3aez3r18pB1RBFJR1kwUVJ5jHt92JmQwXbd5hwi", 41 | "cryptosuite": "eddsa-rdfc-2022", 42 | "proofPurpose": "assertionMethod", 43 | "proofValue": "z41ZsNkz78FHSGkAD5J4b8EN49DkywMMJSL3UdUNffbsCAWmTLPvtnJpd3JGGooYX7TNrzgsTLkXUWiGsRRZ788ML" 44 | }] 45 | } -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple.jwt: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vaW1zZ2xvYmFsLmdpdGh1Yi5pby9vcGVuYmFkZ2VzLXNwZWNpZmljYXRpb24vY29udGV4dC5qc29uIl0sImlkIjoiaHR0cDovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiT3BlbkJhZGdlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOnsiaWQiOiJodHRwczovL2V4YW1wbGUuZWR1L2lzc3VlcnMvNTY1MDQ5IiwidHlwZSI6WyJQcm9maWxlIl0sIm5hbWUiOiJFeGFtcGxlIFVuaXZlcnNpdHkifSwiaXNzdWFuY2VEYXRlIjoiMjAxMC0wMS0wMVQwMDowMDowMFoiLCJuYW1lIjoiRXhhbXBsZSBVbml2ZXJzaXR5IERlZ3JlZSIsImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmV4YW1wbGU6ZWJmZWIxZjcxMmViYzZmMWMyNzZlMTJlYzIxIiwidHlwZSI6WyJBY2hpZXZlbWVudFN1YmplY3QiXX19LCJpc3MiOiJodHRwczovL2V4YW1wbGUuZWR1L2lzc3VlcnMvNTY1MDQ5IiwibmJmIjoxMjYyMzA0MDAwLCJqdGkiOiJodHRwOi8vZXhhbXBsZS5lZHUvY3JlZGVudGlhbHMvMzczMiIsInN1YiI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFjMjc2ZTEyZWMyMSJ9.G7W8od9rSZRsVyk26rXjg_fH2CyUihwNpepd6tWgLt_UHC1vUU0Clox8IicnOSkMyYEqAuNZAdCC9_35i1oUcyj1c076Aa0dsVQ2fFVuQPqXBlyZWcBmo5jqOK6R9NHzRAYXwLRXgrB8gz3lSK55cnHTnMtkpXXcUcHkS5ylWbXCLeOWKoygOCuxRN3N6kP-0HOyuk15PWlnkJ2zEKz2pBtVPaNEydcT0kEtoHFMEWVwqo6rnGV-Ea3M7ssDt3145mcl-DVYLXmBVdT8KoO47QAOBaVMR6k-hgrHNBcdhpI-o6IvLIFsGLgrNvWN67i8Z7Baum1mP-HBpsAigdmIpA -------------------------------------------------------------------------------- /inspector-vc/src/test/resources/ob30/simple_v1.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context.json", 5 | "https://w3id.org/security/suites/ed25519-2020/v1" 6 | ], 7 | "id": "http://example.com/credentials/3527", 8 | "type": ["VerifiableCredential", "OpenBadgeCredential"], 9 | "issuer": { 10 | "id": "https://example.com/issuers/876543", 11 | "type": ["Profile"], 12 | "name": "Example Corp" 13 | }, 14 | "issuanceDate": "2010-01-01T00:00:00Z", 15 | "name": "Teamwork Badge", 16 | "credentialSubject": { 17 | "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", 18 | "type": ["AchievementSubject"], 19 | "achievement": { 20 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 21 | "type": ["Achievement"], 22 | "criteria": { 23 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 24 | }, 25 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 26 | "name": "Teamwork" 27 | } 28 | }, 29 | "proof": [ 30 | { 31 | "type": "Ed25519Signature2020", 32 | "created": "2022-11-16T18:54:22Z", 33 | "verificationMethod": "https://example.com/issuers/876543#z6MknNHHrBzPytzu6CUBP9Lg7fg4KSBjzimc2Frh693YbMiv", 34 | "proofPurpose": "assertionMethod", 35 | "proofValue": "z5gJZKchSJEYPGeq6bsqiLKuxT6mXqAovPbqYX66CB7u9CSNFdV41vHtysjHFiitvoyhfPxsaZnWftrZZZW2txPQK" 36 | } 37 | ] 38 | } 39 | --------------------------------------------------------------------------------