Skip to content

Commit

Permalink
Merge pull request #321 from Concordium/qualified-statement
Browse files Browse the repository at this point in the history
Qualified statement
  • Loading branch information
shjortConcordium authored Mar 4, 2024
2 parents 7bab2cc + 36dfa0a commit f913623
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;

import com.concordium.sdk.crypto.wallet.web3Id.Statement.RequestStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.QualifiedRequestStatement;

import lombok.Builder;
import lombok.Getter;
Expand All @@ -11,7 +11,7 @@
@Getter
@Builder
@Jacksonized
public class Request {
public class QualifiedRequest {
private final String challenge;
private final List<RequestStatement> credentialStatements;
private final List<QualifiedRequestStatement> credentialStatements;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME;

import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject;
import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException;
import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute;
import com.concordium.sdk.responses.accountinfo.credential.AttributeType;

@JsonTypeInfo(use = NAME, include = As.PROPERTY, property = "type", visible = true)
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type", visible = true)
@JsonSubTypes ({@Type (value = RevealStatement.class), @Type (value = RangeStatement.class), @Type (value = MembershipStatement.class), @Type (value = NonMembershipStatement.class)})
public abstract class AtomicStatement {
@JsonProperty("attributeTag")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

import lombok.Getter;

@Getter
@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type", visible = true)
@JsonSubTypes({ @Type(value = IdentityQualifier.class), @Type(value = VerifiableCredentialQualifier.class) })
public class IdQualifier {
@JsonUnwrapped
StatementType type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonTypeName;

import lombok.Getter;

@Getter
@JsonTypeName("cred")
public class IdentityQualifier extends IdQualifier {
private List<Long> issuers;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.RequestIdentifier;

import lombok.Getter;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;

@Getter
@SuperBuilder
@Jacksonized
public class QualifiedRequestStatement extends RequestStatement {
private RequestIdentifier id;

public StatementType getStatementType() {
return this.id.getType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,17 @@
import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.RequestIdentifier;
import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Builder;
import lombok.Getter;
import lombok.extern.jackson.Jacksonized;
import lombok.experimental.SuperBuilder;

@SuperBuilder
@Getter
@Builder
@Jacksonized
public class RequestStatement {
private RequestIdentifier id;
public abstract class RequestStatement {
@JsonProperty("type")
private List<String> verifiableCredentialTypes;
private List<AtomicStatement> statement;

public StatementType getStatementType() {
return this.id.getType();
}
public abstract StatementType getStatementType();

public List<AtomicStatement> getUnsatisfiedStatements(IdentityObject identityObject) {
if (!this.getStatementType().equals(StatementType.Credential)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import org.apache.commons.codec.binary.Hex;

import com.concordium.sdk.crypto.ed25519.ED25519PublicKey;
import com.concordium.sdk.crypto.wallet.Network;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.AccountRequestIdentifier;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.RequestIdentifier;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.Web3IssuerRequestIdentifier;
import com.concordium.sdk.transactions.CredentialRegistrationId;
import com.concordium.sdk.types.ContractAddress;

import lombok.Getter;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;

@Getter
@SuperBuilder
@Jacksonized
public class UnqualifiedRequestStatement extends RequestStatement {
private IdQualifier idQualifier;

@Override
public StatementType getStatementType() {
return this.idQualifier.type;
}

public QualifiedRequestStatement qualify(CredentialRegistrationId credId, Network network) {
if (!idQualifier.getType().equals(StatementType.Credential)) {
throw new IllegalArgumentException("Only an account statement may be qualified using a credentialId");
}
RequestIdentifier did = new AccountRequestIdentifier(network, credId);
return QualifiedRequestStatement.builder().id(did).statement(getStatement()).build();
}

public QualifiedRequestStatement qualify(ContractAddress contract, ED25519PublicKey publicKey, Network network) {
if (!idQualifier.getType().equals(StatementType.SmartContract)) {
throw new IllegalArgumentException(
"Only a verifiable credential statement may be qualified using a Contract Address");
}
if (!((VerifiableCredentialQualifier) idQualifier).getIssuers().contains(contract)) {
throw new IllegalArgumentException("The Contract Address must be one specified in the qualifier");
}

RequestIdentifier did = new Web3IssuerRequestIdentifier(network, contract, publicKey);
return QualifiedRequestStatement.builder().id(did).statement(getStatement()).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.concordium.sdk.crypto.wallet.web3Id.Statement;

import java.util.List;

import com.concordium.sdk.types.ContractAddress;
import com.fasterxml.jackson.annotation.JsonTypeName;

import lombok.Getter;

@Getter
@JsonTypeName("sci")
public class VerifiableCredentialQualifier extends IdQualifier {
private List<ContractAddress> issuers;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

import javax.annotation.Nullable;

import org.apache.commons.codec.binary.Hex;

import com.concordium.sdk.crypto.ed25519.ED25519PublicKey;
import com.concordium.sdk.crypto.wallet.Network;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.StatementType;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.concordium.sdk.crypto.wallet.web3Id;

import java.util.List;
import java.util.stream.Collectors;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.QualifiedRequestStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.UnqualifiedRequestStatement;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.jackson.Jacksonized;

@Getter
@Builder
@Jacksonized
public class UnqualifiedRequest {
private final String challenge;
private final List<UnqualifiedRequestStatement> credentialStatements;

/**
* Creates a qualified request, that can be used to generate a presentation.
* @param qualifier function to qualify the individual request statements.
* @return a QualifiedRequest with the same challenge, and with the statements
* transformed using the qualifier.
*/
public QualifiedRequest qualify(Qualifier qualifier) {
List<QualifiedRequestStatement> qualifiedStatements = credentialStatements.stream().map(qualifier::qualify)
.collect(Collectors.toList());
return QualifiedRequest.builder().challenge(challenge).credentialStatements(qualifiedStatements).build();
}

public static interface Qualifier {
QualifiedRequestStatement qualify(UnqualifiedRequestStatement statement);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@Builder
@Jacksonized
public class Web3IdProofInput {
private final Request request;
private final QualifiedRequest request;
private final List<CommitmentInput> commitmentInputs;
private final CryptographicParameters globalContext;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -17,17 +13,10 @@
import com.concordium.sdk.crypto.wallet.credential.CredentialDeploymentDetails;
import com.concordium.sdk.crypto.wallet.credential.CredentialDeploymentSerializationContext;
import com.concordium.sdk.crypto.wallet.credential.UnsignedCredentialDeploymentInfoWithRandomness;
import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject;
import com.concordium.sdk.responses.accountinfo.credential.AttributeType;
import com.concordium.sdk.responses.blocksummary.updates.queues.AnonymityRevokerInfo;
import com.concordium.sdk.responses.blocksummary.updates.queues.IdentityProviderInfo;
import com.concordium.sdk.responses.cryptographicparameters.CryptographicParameters;
import com.concordium.sdk.serializing.JsonMapper;
import com.concordium.sdk.transactions.CredentialPublicKeys;
import com.concordium.sdk.transactions.Expiry;
import com.concordium.sdk.transactions.Index;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;


public class CredentialTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@
import com.concordium.sdk.crypto.wallet.web3Id.Statement.AtomicStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.MembershipStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.NonMembershipStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.QualifiedRequestStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.RangeStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.RequestStatement;
import com.concordium.sdk.crypto.wallet.web3Id.Statement.RevealStatement;
import com.concordium.sdk.responses.accountinfo.credential.AttributeType;
import com.concordium.sdk.serializing.JsonMapper;
import com.fasterxml.jackson.core.type.TypeReference;

public class ProofTest {

static public Request loadRequest(String fileName) throws Exception {
static public QualifiedRequest loadRequest(String fileName) throws Exception {
return JsonMapper.INSTANCE.readValue(
FileHelpers.readFile("./src/test/testresources/wallet/web3Id/" + fileName, Charset.forName("UTF-8")),
Request.class
QualifiedRequest.class
);
}

Expand All @@ -40,11 +40,11 @@ public List<CommitmentInput> loadCommitmentInputs(String fileName) throws Except

@Test
public void testCanParseRequest() throws Exception {
Request request = loadRequest("accountRequest.json");
QualifiedRequest request = loadRequest("accountRequest.json");

assertEquals("beefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef", request.getChallenge());

RequestStatement credentialStatement = request.getCredentialStatements().get(0);
QualifiedRequestStatement credentialStatement = request.getCredentialStatements().get(0);
assertEquals("did:ccd:testnet:cred:a88a8214fc7a7f11aeda54661b76a1fd7c67e15278b83a85ec92cb799ef0abaa3b7c61a7e90ea6bb108fa2ca1a3ba217", credentialStatement.getId().toString());

Iterator<AtomicStatement> iter = credentialStatement.getStatement().iterator();
Expand Down Expand Up @@ -113,11 +113,11 @@ public void testCanCreateProofForAccountCredential() throws Exception {

@Test
public void testCanParseWeb3IdRequest() throws Exception {
Request request = loadRequest("web3IdRequest.json");
QualifiedRequest request = loadRequest("web3IdRequest.json");

assertEquals("5d50c6e18aca83e991af81e7d7e760f5dc753db7966dc19e9aa42f25aef1696b", request.getChallenge());

RequestStatement credentialStatement = request.getCredentialStatements().get(0);
QualifiedRequestStatement credentialStatement = request.getCredentialStatements().get(0);
assertEquals("did:ccd:testnet:sci:6105:0/credentialEntry/31163ba14e30b834f1e97b9544d86df94883fd4f2c77e1d1fac0b6189c9e7996", credentialStatement.getId().toString());

List<String> type = credentialStatement.getVerifiableCredentialTypes();
Expand Down
Loading

0 comments on commit f913623

Please sign in to comment.