Skip to content

Commit

Permalink
feat: update Iron VC to 0.14.0 (#4125)
Browse files Browse the repository at this point in the history
* feat: update Iron VC to 0.14.0

* sourcedoc, checkstyle

* DEPENDENCIES

* removed unneeded var

* fix test

* DEPENDENCIES [skip ci]

* trigger ci
  • Loading branch information
paullatzelsperger authored Apr 22, 2024
1 parent 5bae31c commit 4ed1f99
Show file tree
Hide file tree
Showing 75 changed files with 2,048 additions and 944 deletions.
9 changes: 5 additions & 4 deletions DEPENDENCIES
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
maven/mavencentral/com.apicatalog/carbon-did/0.0.2, Apache-2.0, approved, #9239
maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.8.1, Apache-2.0, approved, #11157
maven/mavencentral/com.apicatalog/iron-verifiable-credentials/0.8.1, Apache-2.0, approved, #9234
maven/mavencentral/com.apicatalog/carbon-did/0.3.0, Apache-2.0, approved, clearlydefined
maven/mavencentral/com.apicatalog/copper-multibase/0.5.0, , restricted, clearlydefined
maven/mavencentral/com.apicatalog/copper-multicodec/0.1.1, , restricted, clearlydefined
maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.14.0, , restricted, clearlydefined
maven/mavencentral/com.apicatalog/iron-verifiable-credentials/0.14.0, Apache-2.0, approved, clearlydefined
maven/mavencentral/com.apicatalog/titanium-json-ld/1.0.0, Apache-2.0, approved, clearlydefined
maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.1, Apache-2.0, approved, #8912
maven/mavencentral/com.apicatalog/titanium-json-ld/1.4.0, Apache-2.0, approved, #13683
maven/mavencentral/com.atomikos/atomikos-util/6.0.0, Apache-2.0, approved, #9326
maven/mavencentral/com.atomikos/transactions-api/6.0.0, Apache-2.0, approved, #10351
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ plugins {
}

dependencies {
api(project(":extensions:common:crypto:lib:jws2020-lib"))
implementation(project(":spi:common:json-ld-spi"))
implementation(project(":spi:common:identity-trust-spi"))
implementation(project(":core:common:lib:util-lib"))
implementation(project(":core:common:lib:util-lib")) //exposes SignatureSuite in its public API

api(project(":spi:common:identity-did-spi"))
// used for the Ed25519 Verifier in conjunction with OctetKeyPairs (OKP)
runtimeOnly(libs.tink)
Expand All @@ -35,6 +37,7 @@ dependencies {
// deps for test fixtures
testFixturesImplementation(project(":spi:common:json-ld-spi"))
testFixturesImplementation(project(":core:common:lib:json-ld-lib"))
testFixturesImplementation(project(":extensions:common:crypto:lib:jws2020-lib"))
testFixturesApi(libs.nimbus.jwt)
testFixturesApi(testFixtures(project(":extensions:common:crypto:lib:jws2020-lib")))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.verifiablecredentials.linkeddata;


import com.apicatalog.ld.signature.VerificationMethod;

import java.net.URI;
import java.util.Arrays;
import java.util.Objects;

/**
* Generic adapter object for a {@link VerificationMethod}
*/
class DataIntegrityKeyPair implements VerificationMethod {
private final URI id;
private final URI type;
private final URI controller;
private final byte[] privateKey;
private final byte[] publicKey;

DataIntegrityKeyPair(URI id, URI type, URI controller, byte[] privateKey, byte[] publicKey) {
super();
this.id = id;
this.type = type;
this.controller = controller;
this.privateKey = privateKey;
this.publicKey = publicKey;
}

DataIntegrityKeyPair(URI id, URI type, URI controller, byte[] privateKey) {
this(id, type, controller, privateKey, null);
}

@Override
public URI id() {
return id;
}

@Override
public URI type() {
return type;
}

@Override
public URI controller() {
return controller;
}

public byte[] privateKey() {
return privateKey;
}

public byte[] publicKey() {
return publicKey;
}

@Override
public int hashCode() {
return Objects.hash(id, type, controller, Arrays.hashCode(privateKey), Arrays.hashCode(publicKey));
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (DataIntegrityKeyPair) obj;
return Objects.equals(this.id, that.id) &&
Objects.equals(this.type, that.type) &&
Objects.equals(this.controller, that.controller) &&
Arrays.equals(this.privateKey, that.privateKey) &&
Arrays.equals(this.publicKey, that.publicKey);
}

@Override
public String toString() {
return "DataIntegrityKeyPair[" +
"id=" + id + ", " +
"type=" + type + ", " +
"controller=" + controller + ", " +
"privateKey=" + Arrays.toString(privateKey) + ", " +
"publicKey=" + Arrays.toString(publicKey) + ']';
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@

import com.apicatalog.jsonld.loader.DocumentLoader;
import com.apicatalog.ld.DocumentError;
import com.apicatalog.ld.signature.SignatureSuite;
import com.apicatalog.ld.signature.method.MethodResolver;
import com.apicatalog.ld.signature.method.VerificationMethod;
import com.apicatalog.vc.VcTag;
import com.apicatalog.vc.integrity.DataIntegrityKeyPair;
import com.apicatalog.ld.signature.VerificationMethod;
import com.apicatalog.vc.method.resolver.MethodResolver;
import com.apicatalog.vc.proof.Proof;
import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry;
import org.eclipse.edc.spi.EdcException;

Expand All @@ -38,19 +36,19 @@ public DidMethodResolver(DidResolverRegistry resolverRegistry) {
}

@Override
public VerificationMethod resolve(URI id, DocumentLoader loader, SignatureSuite suite) throws DocumentError {
public VerificationMethod resolve(URI id, DocumentLoader documentLoader, Proof proof) throws DocumentError {
var didDocument = resolverRegistry.resolve(id.toString())
.orElseThrow(failure -> new EdcException(failure.getFailureDetail()));

return didDocument.getVerificationMethod().stream()
.map(verificationMethod -> DataIntegrityKeyPair.createVerificationKey(
.map(verificationMethod -> new DataIntegrityKeyPair(
URI.create(verificationMethod.getId()),
URI.create(verificationMethod.getType()),
URI.create(verificationMethod.getController()),
verificationMethod.serializePublicKey())
)
.findFirst()
.orElseThrow(() -> new DocumentError(DocumentError.ErrorType.Unknown, suite.getSchema().tagged(VcTag.VerificationMethod.name()).term()));
.orElseThrow(() -> new DocumentError(DocumentError.ErrorType.Unknown, proof.method().type().toString()));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,15 @@

package org.eclipse.edc.verifiablecredentials.linkeddata;

import com.apicatalog.jsonld.JsonLdReader;
import com.apicatalog.jsonld.loader.DocumentLoader;
import com.apicatalog.jsonld.loader.SchemeRouter;
import com.apicatalog.ld.DocumentError;
import com.apicatalog.ld.signature.LinkedDataSignature;
import com.apicatalog.ld.signature.SigningError;
import com.apicatalog.ld.signature.key.KeyPair;
import com.apicatalog.ld.signature.proof.EmbeddedProof;
import com.apicatalog.ld.signature.proof.ProofOptions;
import com.apicatalog.vc.VcTag;
import com.apicatalog.vc.issuer.ProofDraft;
import com.apicatalog.vc.loader.StaticContextLoader;
import jakarta.json.Json;
import com.apicatalog.vc.suite.SignatureSuite;
import jakarta.json.JsonObject;
import jakarta.json.JsonValue;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.Result;
Expand All @@ -54,13 +49,14 @@ private LdpIssuer() {
* Sign a document using a given key pair and proof options. Effectively, this method adds a {@code proof}-object to the JSON document.
* The document is expanded internally, using the {@link JsonLd} interface.
*
* @param document The document to sign.
* @param keyPair The key pair used for signing.
* @param proofOptions The proof options.
* @param document The document to sign.
* @param keyPair The key pair used for signing.
* @param proofDraft The proof options.
* @return A result containing the signed document as a JsonObject, a failure otherwise.
* @throws NullPointerException If any of the parameters is null.
*/
public Result<JsonObject> signDocument(JsonObject document, KeyPair keyPair, ProofOptions proofOptions) {
public Result<JsonObject> signDocument(SignatureSuite signatureSuite, JsonObject document, KeyPair keyPair, ProofDraft proofDraft) {
Objects.requireNonNull(signatureSuite, "SignatureSuite must not be null");
Objects.requireNonNull(document, "Document must not be null");
Objects.requireNonNull(document, "KeyPair must not be null");
Objects.requireNonNull(document, "ProofOptions must not be null");
Expand All @@ -74,57 +70,24 @@ public Result<JsonObject> signDocument(JsonObject document, KeyPair keyPair, Pro
}

return jsonLdService.expand(document)
.compose(expanded -> signExpanded(expanded, keyPair, proofOptions));
.compose(expanded -> signExpanded(signatureSuite, expanded, keyPair, proofDraft));

}

private Result<JsonObject> signExpanded(JsonObject expanded, KeyPair keyPair, ProofOptions options) {
private Result<JsonObject> signExpanded(SignatureSuite signatureSuite, JsonObject expanded, KeyPair keyPair, ProofDraft proofDraft) {

var optionalObject = JsonLdReader.findFirstObject(expanded);
if (optionalObject.isEmpty()) {
return Result.failure("Error reading document: %s".formatted(DocumentError.ErrorType.Invalid));
}
var object = optionalObject.get();

if (options.getSuite() == null) {
return Result.failure("Unsupported Crypto Suite: %s".formatted(SigningError.Code.UnsupportedCryptoSuite));
}

var data = EmbeddedProof.removeProof(object);

var ldSignature = new LinkedDataSignature(options.getSuite().getCryptoSuite());

JsonObject proof;
try {
proof = options.getSuite().getSchema().write(options.toUnsignedProof());
} catch (DocumentError e) {
monitor.warning("Error writing proof", e);
return Result.failure("Error writing proof: %s".formatted(e.getMessage()));
}

var proofValueProperty = options.getSuite().getSchema().tagged(VcTag.ProofValue.name());

byte[] signature;
try {
signature = ldSignature.sign(data, keyPair, proof);
} catch (SigningError e) {
monitor.warning("Error signing data", e);
return Result.failure("Error signing data: %s".formatted(e.getMessage()));
var signed = signatureSuite.createIssuer(keyPair)
.loader(loader)
.base(base)
.useBundledContexts(bundledContexts)
.sign(expanded, proofDraft);
return Result.success(signed.expanded());
} catch (SigningError | DocumentError e) {
monitor.warning("Error signing document", e);
return Result.failure("Error signing document: " + e.getMessage());
}

JsonValue proofValue;
try {
proofValue = proofValueProperty.write(signature);
} catch (DocumentError e) {
monitor.warning("Error writing signature value to document", e);
return Result.failure("Error writing signature to document: %s".formatted(e.getCode()));
}

proof = Json.createObjectBuilder(proof)
.add(proofValueProperty.term().uri(), Json.createArrayBuilder().add(proofValue))
.build();

return Result.success(EmbeddedProof.addProof(object, proof));
}


Expand Down
Loading

0 comments on commit 4ed1f99

Please sign in to comment.