From 6e061bd71cf7274d68b5a3962534e0f303f461a1 Mon Sep 17 00:00:00 2001 From: azuzi Date: Thu, 19 Dec 2024 09:38:50 +0100 Subject: [PATCH 01/11] fix: Updtae gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f912c3c..c902b2f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /.settings/ /target/ /bin/ +.idea \ No newline at end of file From 43efa6349925b6ab591f19e11d6ea39eab98486a Mon Sep 17 00:00:00 2001 From: azuzi Date: Thu, 19 Dec 2024 09:39:15 +0100 Subject: [PATCH 02/11] feat: V2 builder --- .../VerifiableCredentialV2.java | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java diff --git a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java new file mode 100644 index 0000000..cd6c0e2 --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java @@ -0,0 +1,194 @@ +package com.danubetech.verifiablecredentials; + +import com.apicatalog.jsonld.loader.DocumentLoader; +import com.danubetech.verifiablecredentials.credentialstatus.CredentialStatus; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; +import com.fasterxml.jackson.annotation.JsonCreator; +import foundation.identity.jsonld.JsonLDObject; +import foundation.identity.jsonld.JsonLDUtils; +import info.weboftrust.ldsignatures.LdProof; + +import java.io.Reader; +import java.net.URI; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class VerifiableCredentialV2 extends JsonLDObject { + + public static final URI[] DEFAULT_JSONLD_CONTEXTS = { VerifiableCredentialContexts.JSONLD_CONTEXT_W3C_CREDENTIALS_V2 }; + public static final String[] DEFAULT_JSONLD_TYPES = { VerifiableCredentialKeywords.JSONLD_TERM_VERIFIABLE_CREDENTIAL }; + public static final String DEFAULT_JSONLD_PREDICATE = VerifiableCredentialKeywords.JSONLD_TERM_VERIFIABLECREDENTIAL; + public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = VerifiableCredentialContexts.DOCUMENT_LOADER; + + @JsonCreator + public VerifiableCredentialV2() { + super(); + } + + protected VerifiableCredentialV2(Map jsonObject) { + super(jsonObject); + } + + /* + * Factory methods + */ + + public static class Builder> extends JsonLDObject.Builder { + + private Object issuer; + private Date validFrom; + private Date validUntil; + private CredentialSubject credentialSubject; + private Object credentialStatus; + private String name; + private String description; + private LdProof ldProof; + + public Builder(VerifiableCredentialV2 jsonLdObject) { + super(jsonLdObject); + this.forceContextsArray(true); + this.forceTypesArray(true); + this.defaultContexts(true); + this.defaultTypes(true); + } + + @Override + public VerifiableCredentialV2 build() { + + super.build(); + + // add JSON-LD properties + if (this.issuer != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_ISSUER, this.issuer); + if (this.validFrom != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_VALIDFROM, JsonLDUtils.dateToString(this.validFrom)); + if (this.validUntil != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_VALIDUNTIL, JsonLDUtils.dateToString(this.validUntil)); + if (this.credentialSubject != null) this.credentialSubject.addToJsonLDObject(this.jsonLdObject); + if (this.credentialStatus != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSTATUS, this.credentialStatus); + if(this.name != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.name); + if(this.description != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.description); + if (this.ldProof != null) this.ldProof.addToJsonLDObject(this.jsonLdObject); + + return (VerifiableCredentialV2) this.jsonLdObject; + } + + public B issuer(URI issuer) { + this.issuer = issuer; + return (B) this; + } + + public B validFrom(Date validFrom) { + this.validFrom = validFrom; + return (B) this; + } + + public B validUntil(Date validUntil) { + this.validUntil = validUntil; + return (B) this; + } + + public B credentialSubject(CredentialSubject credentialSubject) { + this.credentialSubject = credentialSubject; + return (B) this; + } + + public B credentialStatus(CredentialStatus credentialStatus) { + this.credentialStatus = credentialStatus; + return (B) this; + } + + public B credentialStatus(List credentialStatus) { + this.credentialStatus = credentialStatus; + return (B) this; + } + + public B ldProof(LdProof ldProof) { + this.ldProof = ldProof; + return (B) this; + } + + public B name(String name) { + this.name = name; + return (B) this; + } + + public B description(String description) { + this.description = description; + return (B) this; + } + } + + public static Builder> builder() { + return new Builder<>(new VerifiableCredentialV2()); + } + + public static VerifiableCredentialV2 fromJsonObject(Map jsonObject) { + return new VerifiableCredentialV2(jsonObject); + } + + public static VerifiableCredentialV2 fromJsonLDObject(JsonLDObject jsonLDObject) { return fromJsonObject(jsonLDObject.getJsonObject()); } + + public static VerifiableCredentialV2 fromJson(Reader reader) { + return new VerifiableCredentialV2(readJson(reader)); + } + + public static VerifiableCredentialV2 fromJson(String json) { + return new VerifiableCredentialV2(readJson(json)); + } + + public static VerifiableCredentialV2 fromMap(Map map) { + return new VerifiableCredentialV2(map); + } + + /* + * Adding, getting, and removing the JSON-LD object + */ + + public static VerifiableCredentialV2 getFromJsonLDObject(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObject(VerifiableCredentialV2.class, jsonLdObject); + } + + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(VerifiableCredentialV2.class, jsonLdObject); + } + + /* + * Getters + */ + + public Object getIssuer() { + return JsonLDUtils.stringToUri(JsonLDUtils.jsonLdGetStringOrObjectId(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_ISSUER)); + } + + public Date getValidFrom() { + return JsonLDUtils.stringToDate(JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_VALIDFROM)); + } + + public Date getValidUntil() { + return JsonLDUtils.stringToDate(JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_VALIDUNTIL)); + } + + public CredentialSubject getCredentialSubject() { + return CredentialSubject.getFromJsonLDObject(this); + } + + public LdProof getLdProof() { + return LdProof.getFromJsonLDObject(this); + } + + //The object can be either CredentialStatus object or list of CredentialStatus objects + public Object getCredentialStatus() { + return CredentialStatus.getFromJsonLDObject(this); + } + + + public String getName(){ + return JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_NAME); + } + + public String getDescription(){ + return JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_DESCRIPTION); + } + + +} From 8a004a62e26608786ee3c9780226b61d58ee642c Mon Sep 17 00:00:00 2001 From: azuzi Date: Thu, 19 Dec 2024 09:39:45 +0100 Subject: [PATCH 03/11] feat: Add extentions --- .../extensions/CredentialSchema.java | 72 +++++++++++++++++++ .../extensions/Evidence.java | 68 ++++++++++++++++++ .../extensions/RefreshService.java | 71 ++++++++++++++++++ .../extensions/TermsOfUse.java | 70 ++++++++++++++++++ 4 files changed, 281 insertions(+) create mode 100644 src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java create mode 100644 src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java create mode 100644 src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java create mode 100644 src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java new file mode 100644 index 0000000..7f57eb8 --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java @@ -0,0 +1,72 @@ +package com.danubetech.verifiablecredentials.extensions; + + + +import com.fasterxml.jackson.annotation.JsonCreator; +import foundation.identity.jsonld.JsonLDObject; + + + +import java.io.Reader; +import java.util.Map; + +public class CredentialSchema extends JsonLDObject { + + @JsonCreator + public CredentialSchema() { + super(); + } + + protected CredentialSchema(Map jsonObject) { + super(jsonObject); + } + + public static class Builder> extends JsonLDObject.Builder { + + public Builder(CredentialSchema jsonLdObject) { + super(jsonLdObject); + } + + @Override + public CredentialSchema build() { + + super.build(); + + return (CredentialSchema) this.jsonLdObject; + } + } + + public static CredentialSchema.Builder> builder() { + return new CredentialSchema.Builder<>(new CredentialSchema()); + } + + public static CredentialSchema fromJsonObject(Map jsonObject) { + return new CredentialSchema(jsonObject); + } + + public static CredentialSchema fromJsonLDObject(JsonLDObject jsonLDObject) { return fromJsonObject(jsonLDObject.getJsonObject()); } + + public static CredentialSchema fromJson(Reader reader) { + return new CredentialSchema(readJson(reader)); + } + + public static CredentialSchema fromJson(String json) { + return new CredentialSchema(readJson(json)); + } + + public static CredentialSchema fromMap(Map jsonObject) { + return new CredentialSchema(jsonObject); + } + + /* + * Adding, getting, and removing the JSON-LD object + */ + + public static CredentialSchema getFromJsonLDObject(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObject(CredentialSchema.class, jsonLdObject); + } + + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(CredentialSchema.class, jsonLdObject); + } +} diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java new file mode 100644 index 0000000..b31ae53 --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java @@ -0,0 +1,68 @@ +package com.danubetech.verifiablecredentials.extensions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import foundation.identity.jsonld.JsonLDObject; + +import java.io.Reader; +import java.util.Map; + +public class Evidence extends JsonLDObject { + + @JsonCreator + public Evidence() { + super(); + } + + protected Evidence(Map jsonObject) { + super(jsonObject); + } + + public static class Builder> extends JsonLDObject.Builder { + + public Builder(Evidence jsonLdObject) { + super(jsonLdObject); + } + + @Override + public Evidence build() { + + super.build(); + + return (Evidence) this.jsonLdObject; + } + } + + public static Evidence.Builder> builder() { + return new Evidence.Builder<>(new Evidence()); + } + + public static Evidence fromJsonObject(Map jsonObject) { + return new Evidence(jsonObject); + } + + public static Evidence fromJsonLDObject(JsonLDObject jsonLDObject) { return fromJsonObject(jsonLDObject.getJsonObject()); } + + public static Evidence fromJson(Reader reader) { + return new Evidence(readJson(reader)); + } + + public static Evidence fromJson(String json) { + return new Evidence(readJson(json)); + } + + public static Evidence fromMap(Map jsonObject) { + return new Evidence(jsonObject); + } + + /* + * Adding, getting, and removing the JSON-LD object + */ + + public static Evidence getFromJsonLDObject(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObject(Evidence.class, jsonLdObject); + } + + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(Evidence.class, jsonLdObject); + } +} diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java new file mode 100644 index 0000000..c949ae3 --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java @@ -0,0 +1,71 @@ +package com.danubetech.verifiablecredentials.extensions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import foundation.identity.jsonld.JsonLDObject; + +import java.io.Reader; +import java.util.Map; + +public class RefreshService extends JsonLDObject { + + @JsonCreator + public RefreshService() { + super(); + } + + protected RefreshService(Map jsonObject) { + super(jsonObject); + } + + public static class Builder> extends JsonLDObject.Builder { + + public Builder(RefreshService jsonLdObject) { + super(jsonLdObject); + } + + @Override + public RefreshService build() { + + super.build(); + + return (RefreshService) this.jsonLdObject; + } + } + + public static RefreshService.Builder> builder() { + return new RefreshService.Builder<>(new RefreshService()); + } + + public static RefreshService fromJsonObject(Map jsonObject) { + return new RefreshService(jsonObject); + } + + public static RefreshService fromJsonLDObject(JsonLDObject jsonLDObject) { + return fromJsonObject(jsonLDObject.getJsonObject()); + } + + public static RefreshService fromJson(Reader reader) { + return new RefreshService(readJson(reader)); + } + + public static RefreshService fromJson(String json) { + return new RefreshService(readJson(json)); + } + + public static RefreshService fromMap(Map jsonObject) { + return new RefreshService(jsonObject); + } + + /* + * Adding, getting, and removing the JSON-LD object + */ + + public static RefreshService getFromJsonLDObject(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObject(RefreshService.class, jsonLdObject); + } + + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(RefreshService.class, jsonLdObject); + } +} + diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java new file mode 100644 index 0000000..c736194 --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java @@ -0,0 +1,70 @@ +package com.danubetech.verifiablecredentials.extensions; + +import com.fasterxml.jackson.annotation.JsonCreator; +import foundation.identity.jsonld.JsonLDObject; + +import java.io.Reader; +import java.util.Map; + +public class TermsOfUse extends JsonLDObject { + @JsonCreator + public TermsOfUse() { + super(); + } + + protected TermsOfUse(Map jsonObject) { + super(jsonObject); + } + + public static class Builder> extends JsonLDObject.Builder { + + public Builder(TermsOfUse jsonLdObject) { + super(jsonLdObject); + } + + @Override + public TermsOfUse build() { + + super.build(); + + return (TermsOfUse) this.jsonLdObject; + } + } + + public static TermsOfUse.Builder> builder() { + return new TermsOfUse.Builder<>(new TermsOfUse()); + } + + public static TermsOfUse fromJsonObject(Map jsonObject) { + return new TermsOfUse(jsonObject); + } + + public static TermsOfUse fromJsonLDObject(JsonLDObject jsonLDObject) { + return fromJsonObject(jsonLDObject.getJsonObject()); + } + + public static TermsOfUse fromJson(Reader reader) { + return new TermsOfUse(readJson(reader)); + } + + public static TermsOfUse fromJson(String json) { + return new TermsOfUse(readJson(json)); + } + + public static TermsOfUse fromMap(Map jsonObject) { + return new TermsOfUse(jsonObject); + } + + /* + * Adding, getting, and removing the JSON-LD object + */ + + public static TermsOfUse getFromJsonLDObject(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObject(TermsOfUse.class, jsonLdObject); + } + + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(TermsOfUse.class, jsonLdObject); + } +} + From 4eece9189da5c90cd3ec10e384afa3fafe82811d Mon Sep 17 00:00:00 2001 From: azuzi Date: Thu, 19 Dec 2024 09:40:28 +0100 Subject: [PATCH 04/11] feat: Add new static variables --- .../jsonld/VerifiableCredentialContexts.java | 6 +++--- .../jsonld/VerifiableCredentialKeywords.java | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialContexts.java b/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialContexts.java index ef24cc9..79a9bb1 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialContexts.java +++ b/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialContexts.java @@ -15,7 +15,7 @@ public class VerifiableCredentialContexts { public static final URI JSONLD_CONTEXT_W3C_2018_CREDENTIALS_V1 = URI.create("https://www.w3.org/2018/credentials/v1"); - public static final URI JSONLD_CONTEXT_W3C_2018_CREDENTIALS_V2 = URI.create("https://www.w3.org/2018/credentials/v2"); + public static final URI JSONLD_CONTEXT_W3C_CREDENTIALS_V2 = URI.create("https://www.w3.org/ns/credentials/v2"); public static final URI JSONLD_CONTEXT_W3C_2018_CREDENTIALS_EXAMPLES_V1 = URI.create("https://www.w3.org/2018/credentials/examples/v1"); public static final URI JSONLD_CONTEXT_W3C_NS_ODRL = URI.create("https://www.w3.org/ns/odrl.jsonld"); public static final URI JSONLD_CONTEXT_DANUBETECH_2020_CREDENTIALS_V1 = URI.create("https://danubetech.com/2020/credentials/v1"); @@ -36,8 +36,8 @@ public class VerifiableCredentialContexts { CONTEXTS.put(JSONLD_CONTEXT_W3C_2018_CREDENTIALS_V1, JsonDocument.of(MediaType.JSON_LD, Objects.requireNonNull(VerifiableCredentialContexts.class.getResourceAsStream("credentials-v1.jsonld")))); - CONTEXTS.put(JSONLD_CONTEXT_W3C_2018_CREDENTIALS_V2, - JsonDocument.of(MediaType.JSON_LD, Objects.requireNonNull(VerifiableCredentialContexts.class.getResourceAsStream("credentials-v2-unstable.jsonld")))); + CONTEXTS.put(JSONLD_CONTEXT_W3C_CREDENTIALS_V2, + JsonDocument.of(MediaType.JSON_LD, Objects.requireNonNull(VerifiableCredentialContexts.class.getResourceAsStream("credentials-v2.jsonld")))); CONTEXTS.put(JSONLD_CONTEXT_W3C_2018_CREDENTIALS_EXAMPLES_V1, JsonDocument.of(MediaType.JSON_LD, Objects.requireNonNull(VerifiableCredentialContexts.class.getResourceAsStream("credentials-examples-v1.jsonld")))); CONTEXTS.put(JSONLD_CONTEXT_W3C_NS_ODRL, diff --git a/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialKeywords.java b/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialKeywords.java index 1254284..80c1e03 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialKeywords.java +++ b/src/main/java/com/danubetech/verifiablecredentials/jsonld/VerifiableCredentialKeywords.java @@ -43,4 +43,19 @@ public class VerifiableCredentialKeywords { public static final String JSONLD_TERM_STATUSLISTINDEX = "statusListIndex"; public static final String JSONLD_TERM_STATUSLISTCREDENTIAL = "statusListCredential"; public static final String JSONLD_TERM_STATUSPURPOSE = "statusPurpose"; + + /* + * https://www.w3.org/ns/credentials/v2 + */ + public static final String JSONLD_TERM_VALIDFROM = "validFrom"; + public static final String JSONLD_TERM_VALIDUNTIL = "validUntil"; + public static final String JSONLD_TERM_STATUS = "status"; + public static final String JSONLD_TERM_CREDENTIALSCHEMA = "credentialSchema"; + public static final String JSONLD_TERM_REFRESHSERVICE = "refreshService"; + public static final String JSONLD_TERM_TERMSOFUSE = "termsOfUse"; + public static final String JSONLD_TERM_EVIDENCE = "evidence"; + public static final String JSONLD_TERM_NAME = "name"; + public static final String JSONLD_TERM_DESCRIPTION = "description"; + + } From 88cd427722c9d164437eaf3f0fbeac86a87c1b1f Mon Sep 17 00:00:00 2001 From: azuzi Date: Thu, 19 Dec 2024 09:40:48 +0100 Subject: [PATCH 05/11] chore: Add v2 context --- .../jsonld/credentials-v2.jsonld | 340 ++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 src/main/resources/com/danubetech/verifiablecredentials/jsonld/credentials-v2.jsonld diff --git a/src/main/resources/com/danubetech/verifiablecredentials/jsonld/credentials-v2.jsonld b/src/main/resources/com/danubetech/verifiablecredentials/jsonld/credentials-v2.jsonld new file mode 100644 index 0000000..717b8f0 --- /dev/null +++ b/src/main/resources/com/danubetech/verifiablecredentials/jsonld/credentials-v2.jsonld @@ -0,0 +1,340 @@ +{ + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "description": "https://schema.org/description", + "digestMultibase": { + "@id": "https://w3id.org/security#digestMultibase", + "@type": "https://w3id.org/security#multibase" + }, + "digestSRI": { + "@id": "https://www.w3.org/2018/credentials#digestSRI", + "@type": "https://www.w3.org/2018/credentials#sriString" + }, + "mediaType": { + "@id": "https://schema.org/encodingFormat" + }, + "name": "https://schema.org/name", + + "VerifiableCredential": { + "@id": "https://www.w3.org/2018/credentials#VerifiableCredential", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "confidenceMethod": { + "@id": "https://www.w3.org/2018/credentials#confidenceMethod", + "@type": "@id" + }, + "credentialSchema": { + "@id": "https://www.w3.org/2018/credentials#credentialSchema", + "@type": "@id" + }, + "credentialStatus": { + "@id": "https://www.w3.org/2018/credentials#credentialStatus", + "@type": "@id" + }, + "credentialSubject": { + "@id": "https://www.w3.org/2018/credentials#credentialSubject", + "@type": "@id" + }, + "description": "https://schema.org/description", + "evidence": { + "@id": "https://www.w3.org/2018/credentials#evidence", + "@type": "@id" + }, + "issuer": { + "@id": "https://www.w3.org/2018/credentials#issuer", + "@type": "@id" + }, + "name": "https://schema.org/name", + "proof": { + "@id": "https://w3id.org/security#proof", + "@type": "@id", + "@container": "@graph" + }, + "refreshService": { + "@id": "https://www.w3.org/2018/credentials#refreshService", + "@type": "@id" + }, + "relatedResource": { + "@id": "https://www.w3.org/2018/credentials#relatedResource", + "@type": "@id" + }, + "renderMethod": { + "@id": "https://www.w3.org/2018/credentials#renderMethod", + "@type": "@id" + }, + "termsOfUse": { + "@id": "https://www.w3.org/2018/credentials#termsOfUse", + "@type": "@id" + }, + "validFrom": { + "@id": "https://www.w3.org/2018/credentials#validFrom", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "validUntil": { + "@id": "https://www.w3.org/2018/credentials#validUntil", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + } + } + }, + + "EnvelopedVerifiableCredential": + "https://www.w3.org/2018/credentials#EnvelopedVerifiableCredential", + + "VerifiablePresentation": { + "@id": "https://www.w3.org/2018/credentials#VerifiablePresentation", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "holder": { + "@id": "https://www.w3.org/2018/credentials#holder", + "@type": "@id" + }, + "proof": { + "@id": "https://w3id.org/security#proof", + "@type": "@id", + "@container": "@graph" + }, + "termsOfUse": { + "@id": "https://www.w3.org/2018/credentials#termsOfUse", + "@type": "@id" + }, + "verifiableCredential": { + "@id": "https://www.w3.org/2018/credentials#verifiableCredential", + "@type": "@id", + "@container": "@graph", + "@context": null + } + } + }, + + "EnvelopedVerifiablePresentation": + "https://www.w3.org/2018/credentials#EnvelopedVerifiablePresentation", + + "JsonSchemaCredential": + "https://www.w3.org/2018/credentials#JsonSchemaCredential", + + "JsonSchema": { + "@id": "https://www.w3.org/2018/credentials#JsonSchema", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "jsonSchema": { + "@id": "https://www.w3.org/2018/credentials#jsonSchema", + "@type": "@json" + } + } + }, + + "BitstringStatusListCredential": + "https://www.w3.org/ns/credentials/status#BitstringStatusListCredential", + + "BitstringStatusList": { + "@id": "https://www.w3.org/ns/credentials/status#BitstringStatusList", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "encodedList": { + "@id": "https://www.w3.org/ns/credentials/status#encodedList", + "@type": "https://w3id.org/security#multibase" + }, + "statusMessage": { + "@id": "https://www.w3.org/ns/credentials/status#statusMessage", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "message": "https://www.w3.org/ns/credentials/status#message", + "status": "https://www.w3.org/ns/credentials/status#status" + } + }, + "statusPurpose": + "https://www.w3.org/ns/credentials/status#statusPurpose", + "statusReference": { + "@id": "https://www.w3.org/ns/credentials/status#statusReference", + "@type": "@id" + }, + "statusSize": { + "@id": "https://www.w3.org/ns/credentials/status#statusSize", + "@type": "https://www.w3.org/2001/XMLSchema#positiveInteger" + }, + "ttl": "https://www.w3.org/ns/credentials/status#ttl" + } + }, + + "BitstringStatusListEntry": { + "@id": + "https://www.w3.org/ns/credentials/status#BitstringStatusListEntry", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "statusListCredential": { + "@id": + "https://www.w3.org/ns/credentials/status#statusListCredential", + "@type": "@id" + }, + "statusListIndex": + "https://www.w3.org/ns/credentials/status#statusListIndex", + "statusPurpose": + "https://www.w3.org/ns/credentials/status#statusPurpose" + } + }, + + "DataIntegrityProof": { + "@id": "https://w3id.org/security#DataIntegrityProof", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "challenge": "https://w3id.org/security#challenge", + "created": { + "@id": "http://purl.org/dc/terms/created", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "cryptosuite": { + "@id": "https://w3id.org/security#cryptosuite", + "@type": "https://w3id.org/security#cryptosuiteString" + }, + "domain": "https://w3id.org/security#domain", + "expires": { + "@id": "https://w3id.org/security#expiration", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "nonce": "https://w3id.org/security#nonce", + "previousProof": { + "@id": "https://w3id.org/security#previousProof", + "@type": "@id" + }, + "proofPurpose": { + "@id": "https://w3id.org/security#proofPurpose", + "@type": "@vocab", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "assertionMethod": { + "@id": "https://w3id.org/security#assertionMethod", + "@type": "@id", + "@container": "@set" + }, + "authentication": { + "@id": "https://w3id.org/security#authenticationMethod", + "@type": "@id", + "@container": "@set" + }, + "capabilityDelegation": { + "@id": "https://w3id.org/security#capabilityDelegationMethod", + "@type": "@id", + "@container": "@set" + }, + "capabilityInvocation": { + "@id": "https://w3id.org/security#capabilityInvocationMethod", + "@type": "@id", + "@container": "@set" + }, + "keyAgreement": { + "@id": "https://w3id.org/security#keyAgreementMethod", + "@type": "@id", + "@container": "@set" + } + } + }, + "proofValue": { + "@id": "https://w3id.org/security#proofValue", + "@type": "https://w3id.org/security#multibase" + }, + "verificationMethod": { + "@id": "https://w3id.org/security#verificationMethod", + "@type": "@id" + } + } + }, + + "...": { + "@id": "https://www.iana.org/assignments/jwt#..." + }, + "_sd": { + "@id": "https://www.iana.org/assignments/jwt#_sd", + "@type": "@json" + }, + "_sd_alg": { + "@id": "https://www.iana.org/assignments/jwt#_sd_alg" + }, + "aud": { + "@id": "https://www.iana.org/assignments/jwt#aud", + "@type": "@id" + }, + "cnf": { + "@id": "https://www.iana.org/assignments/jwt#cnf", + "@context": { + "@protected": true, + + "kid": { + "@id": "https://www.iana.org/assignments/jwt#kid", + "@type": "@id" + }, + "jwk": { + "@id": "https://www.iana.org/assignments/jwt#jwk", + "@type": "@json" + } + } + }, + "exp": { + "@id": "https://www.iana.org/assignments/jwt#exp", + "@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger" + }, + "iat": { + "@id": "https://www.iana.org/assignments/jwt#iat", + "@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger" + }, + "iss": { + "@id": "https://www.iana.org/assignments/jose#iss", + "@type": "@id" + }, + "jku": { + "@id": "https://www.iana.org/assignments/jose#jku", + "@type": "@id" + }, + "kid": { + "@id": "https://www.iana.org/assignments/jose#kid", + "@type": "@id" + }, + "nbf": { + "@id": "https://www.iana.org/assignments/jwt#nbf", + "@type": "https://www.w3.org/2001/XMLSchema#nonNegativeInteger" + }, + "sub": { + "@id": "https://www.iana.org/assignments/jose#sub", + "@type": "@id" + }, + "x5u": { + "@id": "https://www.iana.org/assignments/jose#x5u", + "@type": "@id" + } + } +} \ No newline at end of file From c4c5098072f8a6851dcdde082a065df78ee985fe Mon Sep 17 00:00:00 2001 From: azuzi Date: Thu, 19 Dec 2024 09:41:12 +0100 Subject: [PATCH 06/11] feat: v2 validation --- .../validation/Validation.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java b/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java index 5aade17..a3b9d14 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java +++ b/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java @@ -1,10 +1,14 @@ package com.danubetech.verifiablecredentials.validation; import com.danubetech.verifiablecredentials.VerifiableCredential; +import com.danubetech.verifiablecredentials.VerifiableCredentialV2; import com.danubetech.verifiablecredentials.VerifiablePresentation; +import com.danubetech.verifiablecredentials.credentialstatus.CredentialStatus; import java.net.URI; import java.net.URISyntaxException; +import java.util.List; +import java.util.Map; public class Validation { @@ -70,4 +74,48 @@ public static void validate(VerifiablePresentation verifiablePresentation) throw validateRun(() -> validateTrue(verifiablePresentation.getTypes().contains(VerifiablePresentation.DEFAULT_JSONLD_TYPES[0])), "type must contain VerifiablePresentation: " + verifiablePresentation.getTypes()); validateRun(() -> validateTrue(verifiablePresentation.getVerifiableCredential() != null || verifiablePresentation.getJwtVerifiableCredentialString() != null), "Bad or missing 'verifiableCredential'."); } + + + public static void validate(VerifiableCredentialV2 verifiableCredential) throws IllegalStateException { + + foundation.identity.jsonld.validation.Validation.validate(verifiableCredential); + + validateRun(() -> validateTrue(verifiableCredential.getJsonObject() != null), "Bad or missing JSON object."); + validateRun(() -> validateTrue(!verifiableCredential.getContexts().isEmpty()), "Bad or missing '@context'."); + validateRun(() -> validateUrl(verifiableCredential.getContexts().get(0)), "@context must be a valid URI: " + verifiableCredential.getContexts().get(0)); + validateRun(() -> validateTrue(VerifiableCredentialV2.DEFAULT_JSONLD_CONTEXTS[0].equals(verifiableCredential.getContexts().get(0))), "First value of @context must be " + VerifiableCredentialV2.DEFAULT_JSONLD_CONTEXTS[0] + ": " + verifiableCredential.getContexts().get(0)); + validateRun(() -> { if (verifiableCredential.getId() != null) validateUrl(verifiableCredential.getId()); }, "'id' must be a valid URI."); + + validateRun(() -> validateTrue(!verifiableCredential.getTypes().isEmpty()), "Bad or missing 'type'."); + validateRun(() -> validateTrue(verifiableCredential.getTypes().contains(VerifiableCredential.DEFAULT_JSONLD_TYPES[0])), "'type' must contain 'VerifiableCredential': " + verifiableCredential.getTypes()); + + + //Issuer validation + validateIssuer(verifiableCredential); + validateRun(() -> validateTrue(verifiableCredential.getValidFrom() != null), "Bad or missing 'validFrom'."); + validateRun(verifiableCredential::getValidUntil, "Bad 'validUntil'."); + validateRun(verifiableCredential::getCredentialSubject, "Bad 'credentialSubject'."); + validateRun(() -> validateTrue(verifiableCredential.getCredentialSubject() != null), "Bad or missing 'credentialSubject'."); + + //Validate credential Status : Handle both list and single object of credentialStatus + validateStatus(verifiableCredential); + } + + private static void validateIssuer(VerifiableCredentialV2 verifiableCredential) throws IllegalStateException { + + validateRun(() -> validateTrue(verifiableCredential.getIssuer() != null), "Bad or missing 'issuer'."); + if(verifiableCredential.getIssuer() instanceof String )validateRun(() -> validateUrl(URI.create(verifiableCredential.getIssuer().toString())), "'issuer' must be a valid URI."); + else if(verifiableCredential.getIssuer() instanceof Map) validateRun(()-> validateUrl(URI.create(((Map)verifiableCredential.getIssuer()).get("id").toString())), "'issuer' must be a valid URI."); + else validateRun(()-> validateTrue(false),"'issuer' must be a valid URI or object containing an 'id' property."); + } + + private static void validateStatus(VerifiableCredentialV2 verifiableCredential) throws IllegalStateException { + if(verifiableCredential.getCredentialStatus() == null) return; + if(verifiableCredential.getCredentialStatus() instanceof CredentialStatus) validateCredentialStatus((CredentialStatus) verifiableCredential.getCredentialStatus()); + else if (verifiableCredential.getCredentialStatus() instanceof List) ((List)verifiableCredential.getCredentialStatus()).forEach(Validation::validateCredentialStatus); + } + + private static void validateCredentialStatus(CredentialStatus credentialStatus) throws IllegalStateException { + validateRun(() -> validateTrue(credentialStatus.getType() != null), "Bad or missing 'credentialStatus Type'."); + } } From b8a5cf74601ae48a29fc0795fdbf82dbf313399a Mon Sep 17 00:00:00 2001 From: azuzi Date: Fri, 20 Dec 2024 14:50:06 +0100 Subject: [PATCH 07/11] fix: Handle issuer and issuer object --- .../VerifiableCredentialV2.java | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java index cd6c0e2..468d23b 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java +++ b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java @@ -2,6 +2,10 @@ import com.apicatalog.jsonld.loader.DocumentLoader; import com.danubetech.verifiablecredentials.credentialstatus.CredentialStatus; +import com.danubetech.verifiablecredentials.extensions.CredentialSchema; +import com.danubetech.verifiablecredentials.extensions.Evidence; +import com.danubetech.verifiablecredentials.extensions.RefreshService; +import com.danubetech.verifiablecredentials.extensions.TermsOfUse; import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.fasterxml.jackson.annotation.JsonCreator; @@ -14,6 +18,7 @@ import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; public class VerifiableCredentialV2 extends JsonLDObject { @@ -46,6 +51,13 @@ public static class Builder> extends JsonLDObject.Builder credentialSchema; + private Set evidence; + private TermsOfUse termsOfUse; + private RefreshService refreshService; + public Builder(VerifiableCredentialV2 jsonLdObject) { super(jsonLdObject); this.forceContextsArray(true); @@ -69,6 +81,12 @@ public VerifiableCredentialV2 build() { if(this.description != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.description); if (this.ldProof != null) this.ldProof.addToJsonLDObject(this.jsonLdObject); + //add extensions + if (this.credentialSchema != null) JsonLDUtils.jsonLdAddAsJsonArray(this.jsonLdObject,VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSCHEMA, credentialSchema); + if (this.termsOfUse != null) this.termsOfUse.addToJsonLDObject(this.jsonLdObject); + if (this.evidence != null && !this.evidence.isEmpty()) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_EVIDENCE, this.evidence); + if (this.refreshService != null) this.refreshService.addToJsonLDObject(this.jsonLdObject); + return (VerifiableCredentialV2) this.jsonLdObject; } @@ -77,6 +95,11 @@ public B issuer(URI issuer) { return (B) this; } + public B issuer(Map issuer) { + this.issuer = issuer; + return (B) this; + } + public B validFrom(Date validFrom) { this.validFrom = validFrom; return (B) this; @@ -116,6 +139,25 @@ public B description(String description) { this.description = description; return (B) this; } + + public B evidence(Set evidence) { + this.evidence = evidence; + return (B) this; + } + public B credentialSchema(List credentialSchema) { + this.credentialSchema = credentialSchema; + return (B) this; + } + + public B termsOfUse(TermsOfUse termsOfUse) { + this.termsOfUse = termsOfUse; + return (B) this; + } + + public B refreshService(RefreshService refreshService) { + this.refreshService = refreshService; + return (B) this; + } } public static Builder> builder() { @@ -157,7 +199,14 @@ public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { */ public Object getIssuer() { - return JsonLDUtils.stringToUri(JsonLDUtils.jsonLdGetStringOrObjectId(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_ISSUER)); + return JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_ISSUER); + } + + public URI getIssuerUri() { + + Object issuer = JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_ISSUER); + + return (issuer instanceof String) ? URI.create(issuer.toString()) : URI.create((((Map)issuer).get(VerifiableCredentialKeywords.JSONLD_TERM_ISSUER)).toString()); } public Date getValidFrom() { @@ -190,5 +239,21 @@ public String getDescription(){ return JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_DESCRIPTION); } + public Set getEvidence() { + return (Set) JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(),VerifiableCredentialKeywords.JSONLD_TERM_EVIDENCE); + } + + public List getCredentialSchema() { + return (List) JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSCHEMA); + } + + public TermsOfUse getTermsOfUse() { + return TermsOfUse.getFromJsonLDObject(this); + } + + public RefreshService getRefreshService() { + return RefreshService.getFromJsonLDObject(this); + } + } From 26bd862a2e1c40916841e408a62eef7a90da1474 Mon Sep 17 00:00:00 2001 From: azuzi Date: Fri, 20 Dec 2024 14:51:11 +0100 Subject: [PATCH 08/11] feat: Jwt vc converters --- .../jwt/FromJwtConverter.java | 53 +++++++++++ .../jwt/JwtVerifiableCredentialV2.java | 36 ++++++++ .../jwt/ToJwtConverter.java | 90 +++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 src/main/java/com/danubetech/verifiablecredentials/jwt/JwtVerifiableCredentialV2.java diff --git a/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java b/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java index 6ad4c67..f1f024d 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java +++ b/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java @@ -2,6 +2,7 @@ import com.danubetech.verifiablecredentials.CredentialSubject; import com.danubetech.verifiablecredentials.VerifiableCredential; +import com.danubetech.verifiablecredentials.VerifiableCredentialV2; import com.danubetech.verifiablecredentials.VerifiablePresentation; import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.nimbusds.jwt.JWTClaimsSet; @@ -107,4 +108,56 @@ public static VerifiablePresentation fromJwtVerifiableCredentialToVerifiablePres return verifiablePresentation; } + + + public static VerifiableCredentialV2 fromJwtVerifiableCredential(JwtVerifiableCredentialV2 jwtVerifiableCredential) { + + VerifiableCredentialV2 payloadVerifiableCredential = VerifiableCredentialV2.fromJson(jwtVerifiableCredential.getPayloadObject().toString()); + CredentialSubject payloadCredentialSubject = payloadVerifiableCredential.getCredentialSubject(); + CredentialSubject.removeFromJsonLdObject(payloadVerifiableCredential); + + VerifiableCredentialV2.Builder> verifiableCredentialBuilder = VerifiableCredentialV2.builder() + .base(payloadVerifiableCredential) + .defaultContexts(false) + .defaultTypes(false); + + JWTClaimsSet payload = jwtVerifiableCredential.getPayload(); + + String jwtId = payload.getJWTID(); + if (jwtId != null && payloadVerifiableCredential.getId() == null) { + verifiableCredentialBuilder.id(URI.create(jwtId)); + } + + if (payloadCredentialSubject != null) { + + CredentialSubject.Builder> credentialSubjectBuilder = CredentialSubject.builder() + .base(payloadCredentialSubject); + + String subject = payload.getSubject(); + if (subject != null && payloadCredentialSubject.getId() == null) { + credentialSubjectBuilder.id(URI.create(subject)); + } + + CredentialSubject credentialSubject = credentialSubjectBuilder.build(); + + verifiableCredentialBuilder.credentialSubject(credentialSubject); + } + + String issuer = payload.getIssuer(); + if (issuer != null && payloadVerifiableCredential.getIssuer() == null) { + verifiableCredentialBuilder.issuer(URI.create(issuer)); + } + + Date notBeforeTime = payload.getNotBeforeTime(); + if (notBeforeTime != null && payloadVerifiableCredential.getValidFrom() == null) { + verifiableCredentialBuilder.validFrom(notBeforeTime); + } + + Date expirationTime = payload.getExpirationTime(); + if (expirationTime != null && payloadVerifiableCredential.getValidUntil() == null) { + verifiableCredentialBuilder.validUntil(expirationTime); + } + + return verifiableCredentialBuilder.build(); + } } diff --git a/src/main/java/com/danubetech/verifiablecredentials/jwt/JwtVerifiableCredentialV2.java b/src/main/java/com/danubetech/verifiablecredentials/jwt/JwtVerifiableCredentialV2.java new file mode 100644 index 0000000..5dc7d3a --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/jwt/JwtVerifiableCredentialV2.java @@ -0,0 +1,36 @@ +package com.danubetech.verifiablecredentials.jwt; + + +import com.danubetech.verifiablecredentials.VerifiableCredentialV2; +import com.nimbusds.jose.JWSObject; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; + +import java.text.ParseException; +import java.util.LinkedHashMap; +import java.util.Map; + +public class JwtVerifiableCredentialV2 extends JwtWrappingObject { + + public JwtVerifiableCredentialV2(JWTClaimsSet payload, VerifiableCredentialV2 payloadObject, JWSObject jwsObject, String compactSerialization) { + + super(payload, payloadObject, jwsObject, compactSerialization); + } + + /* + * Factory methods + */ + + public static JwtVerifiableCredentialV2 fromCompactSerialization(String compactSerialization) throws ParseException { + + SignedJWT signedJWT = SignedJWT.parse(compactSerialization); + + JWTClaimsSet jwtPayload = signedJWT.getJWTClaimsSet(); + Map jsonObject = (Map) jwtPayload.getClaims().get(JwtKeywords.JWT_CLAIM_VC); + if (jsonObject == null) return null; + + VerifiableCredentialV2 payloadVerifiableCredential = VerifiableCredentialV2.fromJsonObject(new LinkedHashMap<>(jsonObject)); + + return new JwtVerifiableCredentialV2(jwtPayload, payloadVerifiableCredential, signedJWT, compactSerialization); + } +} diff --git a/src/main/java/com/danubetech/verifiablecredentials/jwt/ToJwtConverter.java b/src/main/java/com/danubetech/verifiablecredentials/jwt/ToJwtConverter.java index 98c7a19..a3be51e 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/jwt/ToJwtConverter.java +++ b/src/main/java/com/danubetech/verifiablecredentials/jwt/ToJwtConverter.java @@ -2,6 +2,7 @@ import com.danubetech.verifiablecredentials.CredentialSubject; import com.danubetech.verifiablecredentials.VerifiableCredential; +import com.danubetech.verifiablecredentials.VerifiableCredentialV2; import com.danubetech.verifiablecredentials.VerifiablePresentation; import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.nimbusds.jwt.JWTClaimsSet; @@ -147,4 +148,93 @@ public static JwtVerifiablePresentation toJwtVerifiablePresentation(VerifiablePr return toJwtVerifiablePresentation(verifiablePresentation, null); } + + + /* + * from JSON-LD to JWT VCDM V2 + */ + + public static JwtVerifiableCredentialV2 toJwtVerifiableCredentialV2(VerifiableCredentialV2 verifiableCredential, String aud, boolean preserveVerifiableCredentialProperties, boolean includeIat) { + + JWTClaimsSet.Builder jwtPayloadBuilder = new JWTClaimsSet.Builder(); + + VerifiableCredentialV2 payloadVerifiableCredential = VerifiableCredentialV2.builder() + .defaultContexts(false) + .defaultTypes(false) + .build(); + + JsonLDUtils.jsonLdAddAll(payloadVerifiableCredential, verifiableCredential.getJsonObject()); + + URI id = verifiableCredential.getId(); + if (id != null) { + jwtPayloadBuilder.jwtID(id.toString()); + if (!preserveVerifiableCredentialProperties) { + JsonLDUtils.jsonLdRemove(payloadVerifiableCredential, JsonLDKeywords.JSONLD_TERM_ID); + } + } + + CredentialSubject credentialSubject = verifiableCredential.getCredentialSubject(); + if (credentialSubject != null && credentialSubject.getId() != null) { + jwtPayloadBuilder.subject(credentialSubject.getId().toString()); + if (!preserveVerifiableCredentialProperties) { + CredentialSubject payloadCredentialSubject = CredentialSubject.builder() + .base(credentialSubject) + .build(); + JsonLDUtils.jsonLdRemove(payloadCredentialSubject, JsonLDKeywords.JSONLD_TERM_ID); + CredentialSubject.removeFromJsonLdObject(payloadVerifiableCredential); + payloadCredentialSubject.addToJsonLDObject(payloadVerifiableCredential); + } + } + + URI issuer = verifiableCredential.getIssuerUri(); + if (issuer != null) { + jwtPayloadBuilder.issuer(issuer.toString()); + if (!preserveVerifiableCredentialProperties) { + JsonLDUtils.jsonLdRemove(payloadVerifiableCredential, VerifiableCredentialKeywords.JSONLD_TERM_ISSUER); + } + } + + Date issuanceDate = verifiableCredential.getValidFrom(); + if (issuanceDate != null) { + jwtPayloadBuilder.notBeforeTime(issuanceDate); + if (includeIat) jwtPayloadBuilder.issueTime(issuanceDate); + if (!preserveVerifiableCredentialProperties) { + JsonLDUtils.jsonLdRemove(payloadVerifiableCredential, VerifiableCredentialKeywords.JSONLD_TERM_ISSUANCEDATE); + } + } + + Date expirationDate = verifiableCredential.getValidUntil(); + if (expirationDate != null) { + jwtPayloadBuilder.expirationTime(expirationDate); + if (!preserveVerifiableCredentialProperties) { + JsonLDUtils.jsonLdRemove(payloadVerifiableCredential, VerifiableCredentialKeywords.JSONLD_TERM_EXPIRATIONDATE); + } + } + + if (aud != null) { + jwtPayloadBuilder.audience(aud); + } + + Map vcContent = new LinkedHashMap<>(payloadVerifiableCredential.getJsonObject()); + jwtPayloadBuilder.claim(JwtKeywords.JWT_CLAIM_VC, vcContent); + + JWTClaimsSet jwtPayload = jwtPayloadBuilder.build(); + + return new JwtVerifiableCredentialV2(jwtPayload, payloadVerifiableCredential, null, null); + } + + public static JwtVerifiableCredentialV2 toJwtVerifiableCredentialV2(VerifiableCredentialV2 verifiableCredential, String aud) { + + return toJwtVerifiableCredentialV2(verifiableCredential, null, false, false); + } + + public static JwtVerifiableCredentialV2 toJwtVerifiableCredentialV2(VerifiableCredentialV2 verifiableCredential, boolean preserveVerifiableCredentialProperties, boolean includeIat) { + + return toJwtVerifiableCredentialV2(verifiableCredential, null, preserveVerifiableCredentialProperties, includeIat); + } + + public static JwtVerifiableCredentialV2 toJwtVerifiableCredentialV2(VerifiableCredentialV2 verifiableCredential) { + + return toJwtVerifiableCredentialV2(verifiableCredential, null, false, false); + } } From 4ca2f62e898ec357c5b9b30556ffddda839a0983 Mon Sep 17 00:00:00 2001 From: azuzi Date: Fri, 20 Dec 2024 16:49:51 +0100 Subject: [PATCH 09/11] fix: Jwt converter issue --- .../danubetech/verifiablecredentials/jwt/FromJwtConverter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java b/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java index f1f024d..5800375 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java +++ b/src/main/java/com/danubetech/verifiablecredentials/jwt/FromJwtConverter.java @@ -110,7 +110,7 @@ public static VerifiablePresentation fromJwtVerifiableCredentialToVerifiablePres } - public static VerifiableCredentialV2 fromJwtVerifiableCredential(JwtVerifiableCredentialV2 jwtVerifiableCredential) { + public static VerifiableCredentialV2 fromJwtVerifiableCredentialV2(JwtVerifiableCredentialV2 jwtVerifiableCredential) { VerifiableCredentialV2 payloadVerifiableCredential = VerifiableCredentialV2.fromJson(jwtVerifiableCredential.getPayloadObject().toString()); CredentialSubject payloadCredentialSubject = payloadVerifiableCredential.getCredentialSubject(); From 86153de80e9c3d852fd12f6a6ea62bc541883c7e Mon Sep 17 00:00:00 2001 From: Markus Sabadello Date: Mon, 23 Dec 2024 08:43:36 +0100 Subject: [PATCH 10/11] feat: Support lists of JSON-LD objects --- pom.xml | 21 ++- .../CredentialSubject.java | 5 + .../VerifiableCredential.java | 9 + .../VerifiableCredentialV2.java | 147 +++++++++++----- .../VerifiablePresentation.java | 77 ++++---- .../VerifiablePresentationV2.java | 166 ++++++++++++++++++ .../credentialstatus/CredentialStatus.java | 5 + .../extensions/CredentialSchema.java | 17 +- .../extensions/Evidence.java | 14 ++ .../extensions/RefreshService.java | 14 ++ .../extensions/TermsOfUse.java | 15 ++ 11 files changed, 391 insertions(+), 99 deletions(-) create mode 100644 src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentationV2.java diff --git a/pom.xml b/pom.xml index a3f2b74..2b515a4 100644 --- a/pom.xml +++ b/pom.xml @@ -158,25 +158,25 @@ org.junit.jupiter junit-jupiter-engine - 5.11.0 + 5.11.4 test org.junit.jupiter junit-jupiter - 5.11.0 + 5.11.4 test org.mockito mockito-core - 5.13.0 + 5.14.2 test org.mockito mockito-junit-jupiter - 5.13.0 + 5.14.2 test @@ -194,23 +194,28 @@ com.google.crypto.tink tink - 1.15.0 + 1.16.0 test + + decentralized-identity + jsonld-common-java + 1.12.0 + info.weboftrust ld-signatures-java - 1.10.0 + 1.11.0 com.nimbusds nimbus-jose-jwt - 9.41.1 + 9.48 com.fasterxml.jackson.core jackson-databind - 2.17.2 + 2.18.2 diff --git a/src/main/java/com/danubetech/verifiablecredentials/CredentialSubject.java b/src/main/java/com/danubetech/verifiablecredentials/CredentialSubject.java index 08a55be..5f6f546 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/CredentialSubject.java +++ b/src/main/java/com/danubetech/verifiablecredentials/CredentialSubject.java @@ -13,6 +13,7 @@ import java.io.Reader; import java.net.URI; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class CredentialSubject extends JsonLDObject { @@ -90,6 +91,10 @@ public static CredentialSubject getFromJsonLDObject(JsonLDObject jsonLdObject) { return JsonLDObject.getFromJsonLDObject(CredentialSubject.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(CredentialSubject.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(CredentialSubject.class, jsonLdObject); } diff --git a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredential.java b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredential.java index 518a006..f11669c 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredential.java +++ b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredential.java @@ -12,6 +12,7 @@ import java.io.Reader; import java.net.URI; import java.util.Date; +import java.util.List; import java.util.Map; public class VerifiableCredential extends JsonLDObject { @@ -128,6 +129,10 @@ public static VerifiableCredential getFromJsonLDObject(JsonLDObject jsonLdObject return JsonLDObject.getFromJsonLDObject(VerifiableCredential.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(VerifiableCredential.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(VerifiableCredential.class, jsonLdObject); } @@ -156,6 +161,10 @@ public LdProof getLdProof() { return LdProof.getFromJsonLDObject(this); } + public List getLdProofAsList() { + return LdProof.getFromJsonLDObjectAsList(this); + } + public CredentialStatus getCredentialStatus() { return CredentialStatus.getFromJsonLDObject(this); } diff --git a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java index 468d23b..2865807 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java +++ b/src/main/java/com/danubetech/verifiablecredentials/VerifiableCredentialV2.java @@ -15,10 +15,7 @@ import java.io.Reader; import java.net.URI; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class VerifiableCredentialV2 extends JsonLDObject { @@ -46,17 +43,17 @@ public static class Builder> extends JsonLDObject.Builder credentialStatus; private String name; private String description; - private LdProof ldProof; + private List ldProof; //extensions private List credentialSchema; - private Set evidence; - private TermsOfUse termsOfUse; - private RefreshService refreshService; + private List evidence; + private List termsOfUse; + private List refreshService; public Builder(VerifiableCredentialV2 jsonLdObject) { super(jsonLdObject); @@ -76,16 +73,16 @@ public VerifiableCredentialV2 build() { if (this.validFrom != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_VALIDFROM, JsonLDUtils.dateToString(this.validFrom)); if (this.validUntil != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_VALIDUNTIL, JsonLDUtils.dateToString(this.validUntil)); if (this.credentialSubject != null) this.credentialSubject.addToJsonLDObject(this.jsonLdObject); - if (this.credentialStatus != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSTATUS, this.credentialStatus); - if(this.name != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.name); - if(this.description != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.description); - if (this.ldProof != null) this.ldProof.addToJsonLDObject(this.jsonLdObject); + if (this.credentialStatus != null) this.credentialStatus.forEach(credentialStatus -> credentialStatus.addToJsonLDObject(this.jsonLdObject)); + if (this.name != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.name); + if (this.description != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_NAME, this.description); + if (this.ldProof != null) this.ldProof.forEach(ldProof -> ldProof.addToJsonLDObject(this.jsonLdObject)); - //add extensions - if (this.credentialSchema != null) JsonLDUtils.jsonLdAddAsJsonArray(this.jsonLdObject,VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSCHEMA, credentialSchema); - if (this.termsOfUse != null) this.termsOfUse.addToJsonLDObject(this.jsonLdObject); - if (this.evidence != null && !this.evidence.isEmpty()) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_EVIDENCE, this.evidence); - if (this.refreshService != null) this.refreshService.addToJsonLDObject(this.jsonLdObject); + // add extensions + if (this.credentialSchema != null) this.credentialSchema.forEach(credentialSchema -> credentialSchema.addToJsonLDObject(this.jsonLdObject)); + if (this.evidence != null) this.evidence.forEach(evidence -> evidence.addToJsonLDObject(this.jsonLdObject)); + if (this.termsOfUse != null) this.termsOfUse.forEach(termsOfUse -> termsOfUse.addToJsonLDObject(this.jsonLdObject)); + if (this.refreshService != null) this.refreshService.forEach(refreshService -> refreshService.addToJsonLDObject(this.jsonLdObject)); return (VerifiableCredentialV2) this.jsonLdObject; } @@ -116,17 +113,14 @@ public B credentialSubject(CredentialSubject credentialSubject) { } public B credentialStatus(CredentialStatus credentialStatus) { - this.credentialStatus = credentialStatus; + if (this.credentialStatus == null) this.credentialStatus = new ArrayList<>(); + this.credentialStatus.add(credentialStatus); return (B) this; } - public B credentialStatus(List credentialStatus) { - this.credentialStatus = credentialStatus; - return (B) this; - } - - public B ldProof(LdProof ldProof) { - this.ldProof = ldProof; + public B credentialStatus(Collection credentialStatus) { + if (this.credentialStatus == null) this.credentialStatus = new ArrayList<>(); + this.credentialStatus.addAll(credentialStatus); return (B) this; } @@ -140,22 +134,63 @@ public B description(String description) { return (B) this; } - public B evidence(Set evidence) { - this.evidence = evidence; + public B ldProof(LdProof ldProof) { + if (this.ldProof == null) this.ldProof = new ArrayList<>(); + this.ldProof.add(ldProof); + return (B) this; + } + + public B ldProof(Collection ldProof) { + if (this.ldProof == null) this.ldProof = new ArrayList<>(); + this.ldProof.addAll(ldProof); + return (B) this; + } + + public B credentialSchema(CredentialSchema credentialSchema) { + if (this.credentialSchema == null) this.credentialSchema = new ArrayList<>(); + this.credentialSchema.add(credentialSchema); return (B) this; } - public B credentialSchema(List credentialSchema) { - this.credentialSchema = credentialSchema; + + public B credentialSchema(Collection credentialSchema) { + if (this.credentialSchema == null) this.credentialSchema = new ArrayList<>(); + this.credentialSchema.addAll(credentialSchema); + return (B) this; + } + + public B evidence(Evidence evidence) { + if (this.evidence == null) this.evidence = new ArrayList<>(); + this.evidence.add(evidence); + return (B) this; + } + + public B evidence(Collection evidence) { + if (this.evidence == null) this.evidence = new ArrayList<>(); + this.evidence.addAll(evidence); return (B) this; } public B termsOfUse(TermsOfUse termsOfUse) { - this.termsOfUse = termsOfUse; + if (this.termsOfUse == null) this.termsOfUse = new ArrayList<>(); + this.termsOfUse.add(termsOfUse); + return (B) this; + } + + public B termsOfUse(Collection termsOfUse) { + if (this.termsOfUse == null) this.termsOfUse = new ArrayList<>(); + this.termsOfUse.addAll(termsOfUse); return (B) this; } public B refreshService(RefreshService refreshService) { - this.refreshService = refreshService; + if (this.refreshService == null) this.refreshService = new ArrayList<>(); + this.refreshService.add(refreshService); + return (B) this; + } + + public B refreshService(Collection refreshService) { + if (this.refreshService == null) this.refreshService = new ArrayList<>(); + this.refreshService.addAll(refreshService); return (B) this; } } @@ -190,6 +225,10 @@ public static VerifiableCredentialV2 getFromJsonLDObject(JsonLDObject jsonLdObje return JsonLDObject.getFromJsonLDObject(VerifiableCredentialV2.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(VerifiableCredentialV2.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(VerifiableCredentialV2.class, jsonLdObject); } @@ -203,9 +242,7 @@ public Object getIssuer() { } public URI getIssuerUri() { - Object issuer = JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_ISSUER); - return (issuer instanceof String) ? URI.create(issuer.toString()) : URI.create((((Map)issuer).get(VerifiableCredentialKeywords.JSONLD_TERM_ISSUER)).toString()); } @@ -221,16 +258,14 @@ public CredentialSubject getCredentialSubject() { return CredentialSubject.getFromJsonLDObject(this); } - public LdProof getLdProof() { - return LdProof.getFromJsonLDObject(this); + public CredentialStatus getCredentialStatus() { + return CredentialStatus.getFromJsonLDObject(this); } - //The object can be either CredentialStatus object or list of CredentialStatus objects - public Object getCredentialStatus() { - return CredentialStatus.getFromJsonLDObject(this); + public List getCredentialStatusAsList() { + return CredentialStatus.getFromJsonLDObjectAsList(this); } - public String getName(){ return JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_NAME); } @@ -239,21 +274,43 @@ public String getDescription(){ return JsonLDUtils.jsonLdGetString(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_DESCRIPTION); } - public Set getEvidence() { - return (Set) JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(),VerifiableCredentialKeywords.JSONLD_TERM_EVIDENCE); + public LdProof getLdProof() { + return LdProof.getFromJsonLDObject(this); + } + + public List getLdProofAsList() { + return LdProof.getFromJsonLDObjectAsList(this); + } + + public CredentialSchema getCredentialSchema() { + return CredentialSchema.getFromJsonLDObject(this); } - public List getCredentialSchema() { - return (List) JsonLDUtils.jsonLdGetJsonValue(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSCHEMA); + public List getCredentialSchemaAsList() { + return CredentialSchema.getFromJsonLDObjectAsList(this); + } + + public Evidence getEvidence() { + return Evidence.getFromJsonLDObject(this); + } + + public List getEvidenceAsList() { + return Evidence.getFromJsonLDObjectAsList(this); } public TermsOfUse getTermsOfUse() { return TermsOfUse.getFromJsonLDObject(this); } + public List getTermsOfUseAsList() { + return TermsOfUse.getFromJsonLDObjectAsList(this); + } + public RefreshService getRefreshService() { return RefreshService.getFromJsonLDObject(this); } - + public List getRefreshServiceAsList() { + return RefreshService.getFromJsonLDObjectAsList(this); + } } diff --git a/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentation.java b/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentation.java index 315d204..78b894c 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentation.java +++ b/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentation.java @@ -10,8 +10,7 @@ import java.io.Reader; import java.net.URI; -import java.util.List; -import java.util.Map; +import java.util.*; public class VerifiablePresentation extends JsonLDObject { @@ -36,8 +35,8 @@ protected VerifiablePresentation(Map jsonObject) { public static class Builder> extends JsonLDObject.Builder { private URI holder; - private VerifiableCredential verifiableCredential; - private LdProof ldProof; + private List verifiableCredential; + private List ldProof; public Builder(VerifiablePresentation jsonLdObject) { super(jsonLdObject); @@ -54,8 +53,8 @@ public VerifiablePresentation build() { // add JSON-LD properties if (this.holder != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_HOLDER, JsonLDUtils.uriToString(this.holder)); - if (this.verifiableCredential != null) this.verifiableCredential.addToJsonLDObject(this.jsonLdObject); - if (this.ldProof != null) this.ldProof.addToJsonLDObject(this.jsonLdObject); + if (this.verifiableCredential != null) this.verifiableCredential.forEach(verifiableCredential -> verifiableCredential.addToJsonLDObject(this.jsonLdObject)); + if (this.ldProof != null) this.ldProof.forEach(ldProof -> ldProof.addToJsonLDObject(this.jsonLdObject)); return (VerifiablePresentation) this.jsonLdObject; } @@ -66,12 +65,26 @@ public B holder(URI holder) { } public B verifiableCredential(VerifiableCredential verifiableCredential) { - this.verifiableCredential = verifiableCredential; + if (this.verifiableCredential == null) this.verifiableCredential = new ArrayList<>(); + this.verifiableCredential.add(verifiableCredential); + return (B) this; + } + + public B verifiableCredential(Set verifiableCredential) { + if (this.verifiableCredential == null) this.verifiableCredential = new ArrayList<>(); + this.verifiableCredential.addAll(verifiableCredential); return (B) this; } public B ldProof(LdProof ldProof) { - this.ldProof = ldProof; + if (this.ldProof == null) this.ldProof = new ArrayList<>(); + this.ldProof.add(ldProof); + return (B) this; + } + + public B ldProof(Set ldProof) { + if (this.ldProof == null) this.ldProof = new ArrayList<>(); + this.ldProof.addAll(ldProof); return (B) this; } } @@ -106,37 +119,13 @@ public static VerifiablePresentation getFromJsonLDObject(JsonLDObject jsonLdObje return JsonLDObject.getFromJsonLDObject(VerifiablePresentation.class, jsonLdObject); } - public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { - JsonLDObject.removeFromJsonLdObject(VerifiablePresentation.class, jsonLdObject); + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(VerifiablePresentation.class, jsonLdObject); } - /* - public static VerifiablePresentation fromVerifiableCredential(VerifiableCredential verifiableCredential, boolean validate) throws JsonGenerationException, IOException { - - LinkedHashMap jsonLdObject = new LinkedHashMap (); - - ArrayList contextList = new ArrayList (); - contextList.add(JSONLD_CONTEXT_CREDENTIALS); - - ArrayList typeList = new ArrayList (); - typeList.add(JSONLD_TYPE_VERIFIABLE_PRESENTATION); - - ArrayList verifiableCredentialList = new ArrayList (); - verifiableCredentialList.add(verifiableCredential.getJsonLdObject()); - - jsonLdObject = new LinkedHashMap (); - jsonLdObject.put(JsonLdConsts.CONTEXT, contextList); - jsonLdObject.put(JSONLD_TERM_TYPE, typeList); - jsonLdObject.put(JSONLD_TERM_VERIFIABLE_CREDENTIAL, verifiableCredentialList); - - return fromJsonLdObject(jsonLdObject, validate); - } - - public static VerifiablePresentation fromVerifiableCredential(VerifiableCredential verifiableCredential) throws JsonParseException, IOException { - - return fromVerifiableCredential(verifiableCredential, true); + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(VerifiablePresentation.class, jsonLdObject); } -*/ /* * Getters @@ -147,13 +136,11 @@ public URI getHolder() { } public VerifiableCredential getVerifiableCredential() { - Object verifiableCredentialObject = this.getJsonObject().get(VerifiableCredentialKeywords.JSONLD_TERM_VERIFIABLECREDENTIAL); - if ((verifiableCredentialObject instanceof List && ! ((List) verifiableCredentialObject).isEmpty() && ((List) verifiableCredentialObject).get(0) instanceof Map)) { - return VerifiableCredential.getFromJsonLDObject(this); - } else if (verifiableCredentialObject instanceof Map) { - return VerifiableCredential.getFromJsonLDObject(this); - } - return null; + return VerifiableCredential.getFromJsonLDObject(this); + } + + public List getVerifiableCredentialAsList() { + return VerifiableCredential.getFromJsonLDObjectAsList(this); } public String getJwtVerifiableCredentialString() { @@ -169,4 +156,8 @@ public String getJwtVerifiableCredentialString() { public LdProof getLdProof() { return LdProof.getFromJsonLDObject(this); } + + public List getLdProofAsList() { + return LdProof.getFromJsonLDObjectAsList(this); + } } diff --git a/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentationV2.java b/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentationV2.java new file mode 100644 index 0000000..47100c3 --- /dev/null +++ b/src/main/java/com/danubetech/verifiablecredentials/VerifiablePresentationV2.java @@ -0,0 +1,166 @@ +package com.danubetech.verifiablecredentials; + +import com.apicatalog.jsonld.loader.DocumentLoader; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; +import com.fasterxml.jackson.annotation.JsonCreator; +import foundation.identity.jsonld.JsonLDObject; +import foundation.identity.jsonld.JsonLDUtils; +import info.weboftrust.ldsignatures.LdProof; + +import java.io.Reader; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class VerifiablePresentationV2 extends JsonLDObject { + + public static final URI[] DEFAULT_JSONLD_CONTEXTS = { VerifiableCredentialContexts.JSONLD_CONTEXT_W3C_CREDENTIALS_V2 }; + public static final String[] DEFAULT_JSONLD_TYPES = { VerifiableCredentialKeywords.JSONLD_TERM_VERIFIABLE_PRESENTATION }; + public static final String DEFAULT_JSONLD_PREDICATE = null; + public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = VerifiableCredentialContexts.DOCUMENT_LOADER; + + @JsonCreator + public VerifiablePresentationV2() { + super(); + } + + protected VerifiablePresentationV2(Map jsonObject) { + super(jsonObject); + } + + /* + * Factory methods + */ + + public static class Builder> extends JsonLDObject.Builder { + + private URI holder; + private List verifiableCredential; + private List ldProof; + + public Builder(VerifiablePresentationV2 jsonLdObject) { + super(jsonLdObject); + this.forceContextsArray(true); + this.forceTypesArray(true); + this.defaultContexts(true); + this.defaultTypes(true); + } + + @Override + public VerifiablePresentationV2 build() { + + super.build(); + + // add JSON-LD properties + if (this.holder != null) JsonLDUtils.jsonLdAdd(this.jsonLdObject, VerifiableCredentialKeywords.JSONLD_TERM_HOLDER, JsonLDUtils.uriToString(this.holder)); + if (this.verifiableCredential != null) this.verifiableCredential.forEach(verifiableCredential -> verifiableCredential.addToJsonLDObject(this.jsonLdObject)); + if (this.ldProof != null) this.ldProof.forEach(ldProof -> ldProof.addToJsonLDObject(this.jsonLdObject)); + + return (VerifiablePresentationV2) this.jsonLdObject; + } + + public B holder(URI holder) { + this.holder = holder; + return (B) this; + } + + public B verifiableCredential(VerifiableCredentialV2 verifiableCredential) { + if (this.verifiableCredential == null) this.verifiableCredential = new ArrayList<>(); + this.verifiableCredential.add(verifiableCredential); + return (B) this; + } + + public B verifiableCredential(Set verifiableCredential) { + if (this.verifiableCredential == null) this.verifiableCredential = new ArrayList<>(); + this.verifiableCredential.addAll(verifiableCredential); + return (B) this; + } + + public B ldProof(LdProof ldProof) { + if (this.ldProof == null) this.ldProof = new ArrayList<>(); + this.ldProof.add(ldProof); + return (B) this; + } + + public B ldProof(Set ldProof) { + if (this.ldProof == null) this.ldProof = new ArrayList<>(); + this.ldProof.addAll(ldProof); + return (B) this; + } + } + + public static Builder> builder() { + return new Builder<>(new VerifiablePresentationV2()); + } + + public static VerifiablePresentationV2 fromJsonObject(Map jsonObject) { + return new VerifiablePresentationV2(jsonObject); + } + + public static VerifiablePresentationV2 fromJsonLDObject(JsonLDObject jsonLDObject) { return fromJsonObject(jsonLDObject.getJsonObject()); } + + public static VerifiablePresentationV2 fromJson(Reader reader) { + return new VerifiablePresentationV2(readJson(reader)); + } + + public static VerifiablePresentationV2 fromJson(String json) { + return new VerifiablePresentationV2(readJson(json)); + } + + public static VerifiablePresentationV2 fromMap(Map jsonObject) { + return new VerifiablePresentationV2(jsonObject); + } + + /* + * Adding, getting, and removing the JSON-LD object + */ + + public static VerifiablePresentationV2 getFromJsonLDObject(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObject(VerifiablePresentationV2.class, jsonLdObject); + } + + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(VerifiablePresentationV2.class, jsonLdObject); + } + + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { + JsonLDObject.removeFromJsonLdObject(VerifiablePresentationV2.class, jsonLdObject); + } + + /* + * Getters + */ + + public URI getHolder() { + return JsonLDUtils.stringToUri(JsonLDUtils.jsonLdGetStringOrObjectId(this.getJsonObject(), VerifiableCredentialKeywords.JSONLD_TERM_HOLDER)); + } + + public VerifiableCredentialV2 getVerifiableCredential() { + return VerifiableCredentialV2.getFromJsonLDObject(this); + } + + public List getVerifiableCredentialAsList() { + return VerifiableCredentialV2.getFromJsonLDObjectAsList(this); + } + + public String getJwtVerifiableCredentialString() { + Object verifiableCredentialObject = this.getJsonObject().get(VerifiableCredentialKeywords.JSONLD_TERM_VERIFIABLECREDENTIAL); + if (verifiableCredentialObject instanceof List && ! ((List) verifiableCredentialObject).isEmpty() && ((List) verifiableCredentialObject).get(0) instanceof String) { + return (String) ((List) verifiableCredentialObject).get(0); + } else if (verifiableCredentialObject instanceof String) { + return (String) verifiableCredentialObject; + } + return null; + } + + public LdProof getLdProof() { + return LdProof.getFromJsonLDObject(this); + } + + public List getLdProofAsList() { + return LdProof.getFromJsonLDObjectAsList(this); + } +} diff --git a/src/main/java/com/danubetech/verifiablecredentials/credentialstatus/CredentialStatus.java b/src/main/java/com/danubetech/verifiablecredentials/credentialstatus/CredentialStatus.java index dae814d..fc6abc8 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/credentialstatus/CredentialStatus.java +++ b/src/main/java/com/danubetech/verifiablecredentials/credentialstatus/CredentialStatus.java @@ -8,6 +8,7 @@ import java.io.Reader; import java.net.URI; +import java.util.List; import java.util.Map; public class CredentialStatus extends JsonLDObject { @@ -75,6 +76,10 @@ public static CredentialStatus getFromJsonLDObject(JsonLDObject jsonLdObject) { return JsonLDObject.getFromJsonLDObject(CredentialStatus.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(CredentialStatus.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(CredentialStatus.class, jsonLdObject); } diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java index 7f57eb8..46bd5b7 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/CredentialSchema.java @@ -1,17 +1,24 @@ package com.danubetech.verifiablecredentials.extensions; - +import com.apicatalog.jsonld.loader.DocumentLoader; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.fasterxml.jackson.annotation.JsonCreator; import foundation.identity.jsonld.JsonLDObject; - - import java.io.Reader; +import java.net.URI; +import java.util.List; import java.util.Map; public class CredentialSchema extends JsonLDObject { + public static final URI[] DEFAULT_JSONLD_CONTEXTS = { VerifiableCredentialContexts.JSONLD_CONTEXT_W3C_CREDENTIALS_V2 }; + public static final String[] DEFAULT_JSONLD_TYPES = { }; + public static final String DEFAULT_JSONLD_PREDICATE = VerifiableCredentialKeywords.JSONLD_TERM_CREDENTIALSCHEMA; + public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = VerifiableCredentialContexts.DOCUMENT_LOADER; + @JsonCreator public CredentialSchema() { super(); @@ -66,6 +73,10 @@ public static CredentialSchema getFromJsonLDObject(JsonLDObject jsonLdObject) { return JsonLDObject.getFromJsonLDObject(CredentialSchema.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(CredentialSchema.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(CredentialSchema.class, jsonLdObject); } diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java index b31ae53..27ecf3d 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/Evidence.java @@ -1,13 +1,23 @@ package com.danubetech.verifiablecredentials.extensions; +import com.apicatalog.jsonld.loader.DocumentLoader; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.fasterxml.jackson.annotation.JsonCreator; import foundation.identity.jsonld.JsonLDObject; import java.io.Reader; +import java.net.URI; +import java.util.List; import java.util.Map; public class Evidence extends JsonLDObject { + public static final URI[] DEFAULT_JSONLD_CONTEXTS = { VerifiableCredentialContexts.JSONLD_CONTEXT_W3C_CREDENTIALS_V2 }; + public static final String[] DEFAULT_JSONLD_TYPES = { }; + public static final String DEFAULT_JSONLD_PREDICATE = VerifiableCredentialKeywords.JSONLD_TERM_EVIDENCE; + public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = VerifiableCredentialContexts.DOCUMENT_LOADER; + @JsonCreator public Evidence() { super(); @@ -62,6 +72,10 @@ public static Evidence getFromJsonLDObject(JsonLDObject jsonLdObject) { return JsonLDObject.getFromJsonLDObject(Evidence.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(Evidence.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(Evidence.class, jsonLdObject); } diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java index c949ae3..c7f247b 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/RefreshService.java @@ -1,13 +1,23 @@ package com.danubetech.verifiablecredentials.extensions; +import com.apicatalog.jsonld.loader.DocumentLoader; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.fasterxml.jackson.annotation.JsonCreator; import foundation.identity.jsonld.JsonLDObject; import java.io.Reader; +import java.net.URI; +import java.util.List; import java.util.Map; public class RefreshService extends JsonLDObject { + public static final URI[] DEFAULT_JSONLD_CONTEXTS = { VerifiableCredentialContexts.JSONLD_CONTEXT_W3C_CREDENTIALS_V2 }; + public static final String[] DEFAULT_JSONLD_TYPES = { }; + public static final String DEFAULT_JSONLD_PREDICATE = VerifiableCredentialKeywords.JSONLD_TERM_REFRESHSERVICE; + public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = VerifiableCredentialContexts.DOCUMENT_LOADER; + @JsonCreator public RefreshService() { super(); @@ -64,6 +74,10 @@ public static RefreshService getFromJsonLDObject(JsonLDObject jsonLdObject) { return JsonLDObject.getFromJsonLDObject(RefreshService.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(RefreshService.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(RefreshService.class, jsonLdObject); } diff --git a/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java b/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java index c736194..8542c46 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java +++ b/src/main/java/com/danubetech/verifiablecredentials/extensions/TermsOfUse.java @@ -1,12 +1,23 @@ package com.danubetech.verifiablecredentials.extensions; +import com.apicatalog.jsonld.loader.DocumentLoader; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialContexts; +import com.danubetech.verifiablecredentials.jsonld.VerifiableCredentialKeywords; import com.fasterxml.jackson.annotation.JsonCreator; import foundation.identity.jsonld.JsonLDObject; import java.io.Reader; +import java.net.URI; +import java.util.List; import java.util.Map; public class TermsOfUse extends JsonLDObject { + + public static final URI[] DEFAULT_JSONLD_CONTEXTS = { VerifiableCredentialContexts.JSONLD_CONTEXT_W3C_CREDENTIALS_V2 }; + public static final String[] DEFAULT_JSONLD_TYPES = { }; + public static final String DEFAULT_JSONLD_PREDICATE = VerifiableCredentialKeywords.JSONLD_TERM_TERMSOFUSE; + public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = VerifiableCredentialContexts.DOCUMENT_LOADER; + @JsonCreator public TermsOfUse() { super(); @@ -63,6 +74,10 @@ public static TermsOfUse getFromJsonLDObject(JsonLDObject jsonLdObject) { return JsonLDObject.getFromJsonLDObject(TermsOfUse.class, jsonLdObject); } + public static List getFromJsonLDObjectAsList(JsonLDObject jsonLdObject) { + return JsonLDObject.getFromJsonLDObjectAsList(TermsOfUse.class, jsonLdObject); + } + public static void removeFromJsonLdObject(JsonLDObject jsonLdObject) { JsonLDObject.removeFromJsonLdObject(TermsOfUse.class, jsonLdObject); } From 4effba24be0da5a24328ab840fbccf53a56114b6 Mon Sep 17 00:00:00 2001 From: azuzi Date: Mon, 23 Dec 2024 11:31:58 +0100 Subject: [PATCH 11/11] fix: CredentialStatus validation --- .../verifiablecredentials/validation/Validation.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java b/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java index a3b9d14..c32e9b9 100644 --- a/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java +++ b/src/main/java/com/danubetech/verifiablecredentials/validation/Validation.java @@ -105,14 +105,13 @@ private static void validateIssuer(VerifiableCredentialV2 verifiableCredential) validateRun(() -> validateTrue(verifiableCredential.getIssuer() != null), "Bad or missing 'issuer'."); if(verifiableCredential.getIssuer() instanceof String )validateRun(() -> validateUrl(URI.create(verifiableCredential.getIssuer().toString())), "'issuer' must be a valid URI."); - else if(verifiableCredential.getIssuer() instanceof Map) validateRun(()-> validateUrl(URI.create(((Map)verifiableCredential.getIssuer()).get("id").toString())), "'issuer' must be a valid URI."); + else if(verifiableCredential.getIssuer() instanceof Map) validateRun(()-> validateUrl(URI.create(((Map)verifiableCredential.getIssuer()).get("id").toString())), "'issuer' must contain be a valid 'id'."); else validateRun(()-> validateTrue(false),"'issuer' must be a valid URI or object containing an 'id' property."); } private static void validateStatus(VerifiableCredentialV2 verifiableCredential) throws IllegalStateException { if(verifiableCredential.getCredentialStatus() == null) return; - if(verifiableCredential.getCredentialStatus() instanceof CredentialStatus) validateCredentialStatus((CredentialStatus) verifiableCredential.getCredentialStatus()); - else if (verifiableCredential.getCredentialStatus() instanceof List) ((List)verifiableCredential.getCredentialStatus()).forEach(Validation::validateCredentialStatus); + verifiableCredential.getCredentialStatusAsList().forEach(Validation::validateCredentialStatus); } private static void validateCredentialStatus(CredentialStatus credentialStatus) throws IllegalStateException {