Added support for VCDM 2.0

This commit is contained in:
Xavi Aracil 2024-03-21 17:25:15 +01:00
parent c97c455d09
commit be7e496d47
6 changed files with 395 additions and 321 deletions

View File

@ -13,7 +13,7 @@ public class Ed25519Signature2022LdVerifier extends LdVerifier<Ed25519Signature2
public Ed25519Signature2022LdVerifier(ByteVerifier verifier) {
super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer());
super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer(Eddsa2022LdProof.builder()));
}
public Ed25519Signature2022LdVerifier(byte[] publicKey) {

View File

@ -0,0 +1,53 @@
package org.oneedtech.inspect.vc.verification;
import com.danubetech.keyformats.crypto.ByteVerifier;
import com.danubetech.keyformats.crypto.impl.Ed25519_EdDSA_PublicKeyVerifier;
import com.danubetech.keyformats.jose.JWSAlgorithm;
import info.weboftrust.ldsignatures.LdProof;
import info.weboftrust.ldsignatures.verifier.LdVerifier;
import io.ipfs.multibase.Multibase;
import java.security.GeneralSecurityException;
public class Ed25519Signature2022VCDM20LdVerifier extends LdVerifier<Ed25519Signature2022SignatureSuite> {
public Ed25519Signature2022VCDM20LdVerifier(ByteVerifier verifier) {
super(SignatureSuites.SIGNATURE_SUITE_ED25519SIGNATURE2022, verifier, new URDNA2015Canonicalizer(Eddsa2022v2LdProof.builder()));
}
public Ed25519Signature2022VCDM20LdVerifier(byte[] publicKey) {
this(new Ed25519_EdDSA_PublicKeyVerifier(publicKey));
}
public Ed25519Signature2022VCDM20LdVerifier() {
this((ByteVerifier) null);
}
public static boolean verify(byte[] signingInput, LdProof ldProof, ByteVerifier verifier) throws GeneralSecurityException {
// verify
String proofValue = ldProof.getProofValue();
if (proofValue == null) throw new GeneralSecurityException("No 'proofValue' in proof.");
boolean verify;
byte[] bytes = Multibase.decode(proofValue);
verify = verifier.verify(signingInput, bytes, JWSAlgorithm.EdDSA);
// done
return verify;
}
@Override
public boolean verify(byte[] signingInput, LdProof ldProof) throws GeneralSecurityException {
return verify(signingInput, ldProof, this.getVerifier());
}
}

View File

@ -0,0 +1,49 @@
package org.oneedtech.inspect.vc.verification;
import java.net.URI;
import com.apicatalog.jsonld.loader.DocumentLoader;
import foundation.identity.jsonld.JsonLDObject;
import foundation.identity.jsonld.JsonLDUtils;
import info.weboftrust.ldsignatures.LdProof;
public class Eddsa2022v2LdProof extends LdProof {
public static final URI[] DEFAULT_JSONLD_CONTEXTS = { LDSecurityContexts.JSONLD_CONTEXT_W3ID_VC_V2 };
public static final DocumentLoader DEFAULT_DOCUMENT_LOADER = LDSecurityContexts.DOCUMENT_LOADER;
public static Builder<? extends Builder<?>> builder() {
return new Builder(new Eddsa2022v2LdProof());
}
/*
* Factory methods
*/
public static class Builder<B extends Builder<B>> extends LdProof.Builder<B> {
private boolean addCryptosuite = true;
public Builder(LdProof jsonLdObject) {
super(jsonLdObject);
}
@Override
public B base(JsonLDObject base) {
addCryptosuite = false;
return super.base(base);
}
@Override
public LdProof build() {
super.build();
if (addCryptosuite) {
JsonLDUtils.jsonLdAdd(this.jsonLdObject, "cryptosuite", "eddsa-rdfc-2022");
}
return (LdProof) this.jsonLdObject;
}
}
}

View File

@ -15,6 +15,7 @@ import foundation.identity.jsonld.ConfigurableDocumentLoader;
public class LDSecurityContexts {
public static final URI JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1 = URI.create("https://w3id.org/security/data-integrity/v1");
public static final URI JSONLD_CONTEXT_W3ID_VC_V2 = URI.create("https://www.w3.org/ns/credentials/v2");
public static final Map<URI, JsonDocument> CONTEXTS;
public static final DocumentLoader DOCUMENT_LOADER;
@ -29,6 +30,8 @@ public class LDSecurityContexts {
CONTEXTS.put(JSONLD_CONTEXT_W3ID_SUITES_ED25519_2022_V1,
JsonDocument.of(MediaType.JSON_LD, Resources.getResource("contexts/data-integrity-v1.jsonld").openStream()));
CONTEXTS.put(JSONLD_CONTEXT_W3ID_VC_V2,
JsonDocument.of(MediaType.JSON_LD, Resources.getResource("contexts/credentials-v2.jsonld").openStream()));
for (Map.Entry<URI, JsonDocument> context : CONTEXTS.entrySet()) {
context.getValue().setDocumentUrl(context.getKey());

View File

@ -1,28 +1,29 @@
package org.oneedtech.inspect.vc.verification;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;
import foundation.identity.jsonld.JsonLDException;
import foundation.identity.jsonld.JsonLDObject;
import info.weboftrust.ldsignatures.LdProof;
import info.weboftrust.ldsignatures.canonicalizer.Canonicalizer;
import info.weboftrust.ldsignatures.util.SHAUtil;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.List;
public class URDNA2015Canonicalizer extends Canonicalizer {
public URDNA2015Canonicalizer() {
private LdProof.Builder<?> proofBuilder;
public URDNA2015Canonicalizer(LdProof.Builder<?> proofBuilder) {
super(List.of("urdna2015"));
this.proofBuilder = proofBuilder;
}
@Override
public byte[] canonicalize(LdProof ldProof, JsonLDObject jsonLdObject) throws IOException, GeneralSecurityException, JsonLDException {
// construct the LD proof without proof values
LdProof ldProofWithoutProofValues = Eddsa2022LdProof.builder()
LdProof ldProofWithoutProofValues = proofBuilder
.base(ldProof)
.defaultContexts(true)
.build();

View File

@ -2,10 +2,8 @@
"@context": {
"@protected": true,
"@vocab": "https://www.w3.org/ns/credentials/issuer-dependent#",
"id": "@id",
"type": "@type",
"kid": {
"@id": "https://www.iana.org/assignments/jose#kid",
"@type": "@id"
@ -65,7 +63,6 @@
"...": {
"@id": "https://www.iana.org/assignments/jwt#..."
},
"digestSRI": {
"@id": "https://www.w3.org/2018/credentials#digestSRI",
"@type": "https://www.w3.org/2018/credentials#sriString"
@ -74,25 +71,18 @@
"@id": "https://w3id.org/security#digestMultibase",
"@type": "https://w3id.org/security#multibase"
},
"mediaType": {
"@id": "https://schema.org/encodingFormat"
},
"description": "https://schema.org/description",
"name": "https://schema.org/name",
"EnvelopedVerifiableCredential":
"https://www.w3.org/2018/credentials#EnvelopedVerifiableCredential",
"EnvelopedVerifiableCredential": "https://www.w3.org/2018/credentials#EnvelopedVerifiableCredential",
"VerifiableCredential": {
"@id": "https://www.w3.org/2018/credentials#VerifiableCredential",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"credentialSchema": {
"@id": "https://www.w3.org/2018/credentials#credentialSchema",
"@type": "@id"
@ -146,15 +136,12 @@
}
}
},
"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"
@ -176,36 +163,27 @@
}
}
},
"JsonSchemaCredential": "https://www.w3.org/2018/credentials#JsonSchemaCredential",
"JsonSchema": {
"@id": "https://www.w3.org/2018/credentials#JsonSchema",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"jsonSchema": {
"@id": "https://w3.org/2018/credentials#jsonSchema",
"@type": "@json"
}
}
},
"BitstringStatusListCredential": "https://www.w3.org/ns/credentials/status#BitstringStatusListCredential",
"BitstringStatusList": {
"@id": "https://www.w3.org/ns/credentials/status#BitstringStatusList",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"statusPurpose":
"https://www.w3.org/ns/credentials/status#statusPurpose",
"statusPurpose": "https://www.w3.org/ns/credentials/status#statusPurpose",
"encodedList": {
"@id": "https://www.w3.org/ns/credentials/status#encodedList",
"@type": "https://w3id.org/security#multibase"
@ -217,38 +195,28 @@
"@id": "https://www.w3.org/ns/credentials/status#statusMessage",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"status": "https://www.w3.org/ns/credentials/status#status",
"message": "https://www.w3.org/ns/credentials/status#message"
}
}
}
},
"BitstringStatusListEntry": {
"@id":
"https://www.w3.org/ns/credentials/status#BitstringStatusListEntry",
"@id": "https://www.w3.org/ns/credentials/status#BitstringStatusListEntry",
"@context": {
"@protected": true,
"id": "@id",
"type": "@type",
"statusPurpose":
"https://www.w3.org/ns/credentials/status#statusPurpose",
"statusListIndex":
"https://www.w3.org/ns/credentials/status#statusListIndex",
"statusPurpose": "https://www.w3.org/ns/credentials/status#statusPurpose",
"statusListIndex": "https://www.w3.org/ns/credentials/status#statusListIndex",
"statusListCredential": {
"@id":
"https://www.w3.org/ns/credentials/status#statusListCredential",
"@id": "https://www.w3.org/ns/credentials/status#statusListCredential",
"@type": "@id"
}
}
},
"DataIntegrityProof": {
"@id": "https://w3id.org/security#DataIntegrityProof",
"@context": {