From 80914437d8ff6822b243b7127fec46ef2656d370 Mon Sep 17 00:00:00 2001 From: Hjort Date: Thu, 15 Feb 2024 17:26:38 +0100 Subject: [PATCH 1/7] Add methods to check if statements are satisfied by an identity --- .../wallet/identityobject/IdentityObject.java | 10 ++++ .../MissingAttributeException.java | 14 +++++ .../wallet/web3Id/CredentialAttribute.java | 59 ++++++++++++++++++- .../web3Id/Statement/AtomicStatement.java | 15 +++++ .../web3Id/Statement/MembershipStatement.java | 13 ++++ .../Statement/NonMembershipStatement.java | 11 ++++ .../web3Id/Statement/RangeStatement.java | 14 ++++- .../web3Id/Statement/RequestStatement.java | 21 +++++++ .../web3Id/Statement/RevealStatement.java | 15 +++++ .../accountinfo/credential/AttributeType.java | 7 ++- 10 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/MissingAttributeException.java diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java index 216cb99b8..104f5ba7a 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java @@ -1,6 +1,9 @@ package com.concordium.sdk.crypto.wallet.identityobject; +import com.concordium.sdk.responses.accountinfo.credential.AttributeType; + import lombok.Getter; +import lombok.val; @Getter public class IdentityObject { @@ -9,4 +12,11 @@ public class IdentityObject { private PreIdentityObject preIdentityObject; private String signature; + public String getChosenAttribute(AttributeType attribute) throws MissingAttributeException { + val chosenAttributes = this.getAttributeList().getChosenAttributes(); + if (!chosenAttributes.containsKey(attribute)) { + throw new MissingAttributeException(attribute); + } + return chosenAttributes.get(attribute); + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/MissingAttributeException.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/MissingAttributeException.java new file mode 100644 index 000000000..f84f0e292 --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/MissingAttributeException.java @@ -0,0 +1,14 @@ +package com.concordium.sdk.crypto.wallet.identityobject; + +import com.concordium.sdk.responses.accountinfo.credential.AttributeType; + +import lombok.Getter; + +@Getter +public class MissingAttributeException extends Exception { + private AttributeType attribute; + + public MissingAttributeException(AttributeType attribute) { + this.attribute = attribute; + } +} diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java index 6505f8a46..6f881dbf7 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java @@ -1,6 +1,8 @@ package com.concordium.sdk.crypto.wallet.web3Id; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParseException; @@ -21,8 +23,8 @@ @JsonDeserialize(using = CredentialAttribute.CredentialAttributieTypeDeserializer.class) @Builder @Getter -public class CredentialAttribute { - enum CredentialAttributeType { +public final class CredentialAttribute { + public enum CredentialAttributeType { INT, STRING, TIMESTAMP; @@ -31,8 +33,59 @@ enum CredentialAttributeType { private String value; private CredentialAttributeType type; - static class CredentialAttributieTypeDeserializer extends JsonDeserializer { + private int compareStringAttributes(byte[] aBytes, byte[] bBytes) { + if (aBytes.length < bBytes.length) return -1; + if (aBytes.length > bBytes.length) return 1; + + for (int i = 0; i < aBytes.length; i++) { + byte aByte = aBytes[i]; + byte bByte = bBytes[i]; + + if (aByte == bByte) continue; + return aByte < bByte ? -1 : 1; + } + + return 0; + } + + public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) throws Exception { + if (!this.getType().equals(lower.getType()) || !this.getType().equals(upper.getType())) { + return false; // TODO should throw instead? + } + switch (this.type) { + case INT: { + long lowerVal = Long.parseLong(lower.getValue()); + long upperVal = Long.parseLong(upper.getValue()); + long val = Long.parseLong(this.getValue()); + return lowerVal <= val && val < upperVal; + } + case TIMESTAMP: { + LocalDateTime lowerVal = LocalDateTime.parse(lower.getValue()); + LocalDateTime upperVal = LocalDateTime.parse(upper.getValue()); + LocalDateTime val = LocalDateTime.parse(this.getValue()); + return !lowerVal.isAfter(val) && upperVal.isAfter(val); + } + case STRING: { + byte[] lowerVal = lower.getValue().getBytes(StandardCharsets.UTF_8); + byte[] upperVal = upper.getValue().getBytes(StandardCharsets.UTF_8); + byte[] val = this.getValue().getBytes(StandardCharsets.UTF_8); + return this.compareStringAttributes(val, lowerVal) >= 0 && this.compareStringAttributes(val, upperVal) < 0; + } + default: + throw new Exception(); // TODO better type + } + } + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CredentialAttribute)) { + return false; + } + CredentialAttribute cred = (CredentialAttribute) obj; + return this.type.equals(cred.type) && this.value.equals(cred.value); + } + + static class CredentialAttributieTypeDeserializer extends JsonDeserializer { @Override public CredentialAttribute deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java index 71359d68e..f0e545093 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java @@ -8,9 +8,24 @@ import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME; +import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; +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) @JsonSubTypes ({@Type (value = RevealStatement.class), @Type (value = RangeStatement.class), @Type (value = MembershipStatement.class), @Type (value = NonMembershipStatement.class)}) public abstract class AtomicStatement { @JsonProperty("attributeTag") public abstract String getAttributeTag(); + + // TODO: add overload for web3Id credential + protected CredentialAttribute getAttributeValue(IdentityObject identityObject) throws Exception { + AttributeType type = AttributeType.fromJSON(this.getAttributeTag()); + String raw = identityObject.getAttributeList().getChosenAttributes().get(type); + return CredentialAttribute.builder().value(raw).type(CredentialAttribute.CredentialAttributeType.STRING).build(); + + } + + // TODO: add overload for web3Id credential + public abstract boolean canBeProvedBy(IdentityObject identityObject) throws Exception; } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java index b2c13f225..bd08ae62b 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java @@ -2,6 +2,8 @@ import java.util.List; +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.fasterxml.jackson.annotation.JsonTypeName; @@ -12,4 +14,15 @@ public class MembershipStatement extends AtomicStatement { private String attributeTag; private List set; + + @Override + public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { + try { + CredentialAttribute value = this.getAttributeValue(identityObject); + return set.contains(value); + } catch (MissingAttributeException e) { + // If the identityObject does not have the relevant attribute, it does not satisfy the statement + return false; + } + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java index 5e391ccbb..c86ea4019 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java @@ -2,6 +2,7 @@ import java.util.List; +import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute; import com.fasterxml.jackson.annotation.JsonTypeName; @@ -12,4 +13,14 @@ public class NonMembershipStatement extends AtomicStatement { private String attributeTag; private List set; + + @Override + public boolean canBeProvedBy(IdentityObject identityObject) { + try { + CredentialAttribute value = this.getAttributeValue(identityObject); + return !set.contains(value); + } catch (Exception e) { + return false; + } + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java index 3f7ab7e12..4747ddd78 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java @@ -1,7 +1,8 @@ package com.concordium.sdk.crypto.wallet.web3Id.Statement; +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; import com.fasterxml.jackson.annotation.JsonTypeName; import lombok.Builder; @@ -16,4 +17,15 @@ public class RangeStatement extends AtomicStatement { private CredentialAttribute lower; private CredentialAttribute upper; private String attributeTag; + @Override + public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { + try { + CredentialAttribute value = getAttributeValue(identityObject); + return value.isBetween(lower, upper); + } catch (MissingAttributeException e) { + // If the identityObject does not have the relevant attribute, it does not satisfy the statement + return false; + } + + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java index 4560c3562..1503e48df 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java @@ -1,6 +1,9 @@ package com.concordium.sdk.crypto.wallet.web3Id.Statement; import java.util.List; +import java.util.stream.Collectors; + +import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; import lombok.Builder; import lombok.Getter; @@ -13,4 +16,22 @@ public class RequestStatement { private String id; private List type; private List statement; + + public List getUnsatisfiedStatements(IdentityObject identityObject) { + return statement.stream().filter(s -> { + try { + return !s.canBeProvedBy(identityObject); + } catch (Exception e) { + return false; + } + }).collect(Collectors.toList()); + } + + public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { + for (AtomicStatement s: this.statement) { + if (s.canBeProvedBy(identityObject)) continue; + return false; + } + return true; + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RevealStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RevealStatement.java index 705b1fad7..0ac9b7034 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RevealStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RevealStatement.java @@ -1,5 +1,7 @@ package com.concordium.sdk.crypto.wallet.web3Id.Statement; +import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; +import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException; import com.fasterxml.jackson.annotation.JsonTypeName; import lombok.Getter; @@ -8,4 +10,17 @@ @JsonTypeName("RevealAttribute") public class RevealStatement extends AtomicStatement { private String attributeTag; + + @Override + public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { + try { + // Attempt to get the attribute + this.getAttributeValue(identityObject); + } catch (MissingAttributeException e) { + // If the identityObject does not have the relevant attribute, it does not satisfy the statement + return false; + } + // With a reveal statement, the only requirement is that the identity has the attribute. + return true; + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java index 7901fb1d0..b2b6d4184 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java @@ -1,5 +1,6 @@ package com.concordium.sdk.responses.accountinfo.credential; +import com.concordium.sdk.serializing.JsonMapper; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -36,5 +37,9 @@ public enum AttributeType { @JsonProperty("taxIdNo") TAX_ID_NO, @JsonProperty("lei") - LEI + LEI; + + public static AttributeType fromJSON(String jsonStr) throws Exception { + return JsonMapper.INSTANCE.readValue(jsonStr, AttributeType.class); + } } From a96e85087559cb2dc47f492541e8c790f9a3429b Mon Sep 17 00:00:00 2001 From: Hjort Date: Mon, 19 Feb 2024 11:12:44 +0100 Subject: [PATCH 2/7] Add Tests --- .../accountinfo/credential/AttributeType.java | 2 +- .../sdk/crypto/wallet/web3Id/ProofTest.java | 2 +- .../wallet/web3Id/RequestStatementTest.java | 54 +++++++++++++++++++ .../wallet/web3Id/accountRequestUnder18.json | 38 +++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java create mode 100644 concordium-sdk/src/test/testresources/wallet/web3Id/accountRequestUnder18.json diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java index b2b6d4184..038ce4b2f 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java @@ -40,6 +40,6 @@ public enum AttributeType { LEI; public static AttributeType fromJSON(String jsonStr) throws Exception { - return JsonMapper.INSTANCE.readValue(jsonStr, AttributeType.class); + return JsonMapper.INSTANCE.readValue(String.format("\"%s\"", jsonStr), AttributeType.class); } } diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java index 134fbfaf8..e43721611 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java @@ -39,7 +39,7 @@ static String readFile(String path, Charset encoding) return new String(encoded, encoding); } - public Request loadRequest(String fileName) throws Exception { + static public Request loadRequest(String fileName) throws Exception { return JsonMapper.INSTANCE.readValue( readFile("./src/test/testresources/wallet/web3Id/" + fileName, Charset.forName("UTF-8")), Request.class diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java new file mode 100644 index 000000000..cc20b32ba --- /dev/null +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java @@ -0,0 +1,54 @@ +package com.concordium.sdk.crypto.wallet.web3Id; + +import static org.junit.Assert.assertEquals; +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.List; + +import org.junit.Test; + +import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; +import com.concordium.sdk.crypto.wallet.web3Id.Statement.AtomicStatement; +import com.concordium.sdk.crypto.wallet.web3Id.Statement.RequestStatement; +import com.concordium.sdk.serializing.JsonMapper; + + +public class RequestStatementTest { + + static String readFile(String path, Charset encoding) + throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + + private IdentityObject getIdentityObject() throws Exception { + return JsonMapper.INSTANCE.readValue( + readFile("./src/test/testresources/wallet/id_object.json", Charset.forName("UTF-8")), + IdentityObject.class); + } + + @Test + public void testCanIdentitySatisfyStatement() throws Exception { + IdentityObject identityObject = getIdentityObject(); + + List statements = ProofTest.loadRequest("accountRequest.json").getCredentialStatements(); + RequestStatement requestStatement1 = statements.get(0); + assertTrue(requestStatement1.canBeProvedBy(identityObject)); + } + + @Test + public void testGetsUnsatisfiedStatement() throws Exception { + IdentityObject identityObject = getIdentityObject(); + + List statements = ProofTest.loadRequest("accountRequestUnder18.json").getCredentialStatements(); + RequestStatement requestStatement1 = statements.get(0); + List unsatisfied = requestStatement1.getUnsatisfiedStatements(identityObject); + assertEquals(1, unsatisfied.size()); + assertEquals("dob", unsatisfied.get(0).getAttributeTag()); + assertEquals(requestStatement1.getStatement().get(0), unsatisfied.get(0)); + } +} diff --git a/concordium-sdk/src/test/testresources/wallet/web3Id/accountRequestUnder18.json b/concordium-sdk/src/test/testresources/wallet/web3Id/accountRequestUnder18.json new file mode 100644 index 000000000..90c4d1317 --- /dev/null +++ b/concordium-sdk/src/test/testresources/wallet/web3Id/accountRequestUnder18.json @@ -0,0 +1,38 @@ +{ + "challenge": "beefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef", + "credentialStatements": [ + { + "statement": [ + { + "type": "AttributeInRange", + "attributeTag": "dob", + "upper": "20060215", + "lower": "99990101" + }, + { + "type": "RevealAttribute", + "attributeTag": "firstName" + }, + { + "type": "AttributeInSet", + "attributeTag": "nationality", + "set": [ + "DK", + "FR", + "GB" + ] + }, + { + "type": "AttributeNotInSet", + "attributeTag": "countryOfResidence", + "set": [ + "FR", + "GB", + "DE" + ] + } + ], + "id": "did:ccd:testnet:cred:a88a8214fc7a7f11aeda54661b76a1fd7c67e15278b83a85ec92cb799ef0abaa3b7c61a7e90ea6bb108fa2ca1a3ba217" + } + ] +} From 5278162c3b674b91df6f0ca1274d3a304fbeb420 Mon Sep 17 00:00:00 2001 From: Hjort Date: Mon, 19 Feb 2024 12:52:05 +0100 Subject: [PATCH 3/7] Fix TODOs + formatting --- .../crypto/wallet/web3Id/CredentialAttribute.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java index 6f881dbf7..997242c88 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java @@ -48,9 +48,9 @@ private int compareStringAttributes(byte[] aBytes, byte[] bBytes) { return 0; } - public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) throws Exception { + public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) throws IllegalArgumentException { if (!this.getType().equals(lower.getType()) || !this.getType().equals(upper.getType())) { - return false; // TODO should throw instead? + throw new IllegalArgumentException("Attribute types must match"); } switch (this.type) { case INT: { @@ -60,10 +60,10 @@ public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) t return lowerVal <= val && val < upperVal; } case TIMESTAMP: { - LocalDateTime lowerVal = LocalDateTime.parse(lower.getValue()); - LocalDateTime upperVal = LocalDateTime.parse(upper.getValue()); + LocalDateTime lowerVal = LocalDateTime.parse(lower.getValue()); + LocalDateTime upperVal = LocalDateTime.parse(upper.getValue()); LocalDateTime val = LocalDateTime.parse(this.getValue()); - return !lowerVal.isAfter(val) && upperVal.isAfter(val); + return !lowerVal.isAfter(val) && upperVal.isAfter(val); } case STRING: { byte[] lowerVal = lower.getValue().getBytes(StandardCharsets.UTF_8); @@ -72,7 +72,7 @@ public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) t return this.compareStringAttributes(val, lowerVal) >= 0 && this.compareStringAttributes(val, upperVal) < 0; } default: - throw new Exception(); // TODO better type + throw new IllegalArgumentException("Unknown attribute type"); } } From 3f8a49c8655b93af6734f3a1d4ed67fd984a4a00 Mon Sep 17 00:00:00 2001 From: Hjort Date: Mon, 19 Feb 2024 13:09:17 +0100 Subject: [PATCH 4/7] cleanup in tests --- .../sdk/crypto/wallet/CredentialTest.java | 38 ++------------- .../sdk/crypto/wallet/FileHelpers.java | 48 +++++++++++++++++++ .../sdk/crypto/wallet/IdentityTest.java | 45 ++--------------- .../sdk/crypto/wallet/web3Id/ProofTest.java | 31 ++---------- .../wallet/web3Id/RequestStatementTest.java | 24 ++-------- 5 files changed, 65 insertions(+), 121 deletions(-) create mode 100644 concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/FileHelpers.java diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/CredentialTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/CredentialTest.java index 443d785be..2c1ad91b3 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/CredentialTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/CredentialTest.java @@ -32,36 +32,6 @@ public class CredentialTest { - static String readFile(String path, Charset encoding) - throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } - - private CryptographicParameters getCryptographicParameters() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/global.json", Charset.forName("UTF-8")), - CryptographicParameters.class); - } - - private IdentityProviderInfo getIdentityProviderInfo() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/ip_info.json", Charset.forName("UTF-8")), - IdentityProviderInfo.class); - } - - private Map getAnonymityRevokerInfos() throws Exception { - MapType mapType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, - AnonymityRevokerInfo.class); - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/ars_infos.json", Charset.forName("UTF-8")), mapType); - } - - private IdentityObject getIdentityObject() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/id_object.json", Charset.forName("UTF-8")), - IdentityObject.class); } - private static String TEST_SEED = "efa5e27326f8fa0902e647b52449bf335b7b605adc387015ec903f41d95080eb71361cbc7fb78721dcd4f3926a337340aa1406df83332c44c1cdcfe100603860"; @Test @@ -76,10 +46,10 @@ public void createUnsignedCredential() throws Exception { } UnsignedCredentialInput input = UnsignedCredentialInput.builder() - .ipInfo(getIdentityProviderInfo()) - .globalContext(getCryptographicParameters()) - .arsInfos(getAnonymityRevokerInfos()) - .idObject(getIdentityObject()) + .ipInfo(FileHelpers.getIdentityProviderInfo()) + .globalContext(FileHelpers.getCryptographicParameters()) + .arsInfos(FileHelpers.getAnonymityRevokerInfos()) + .idObject(FileHelpers.getIdentityObject()) .credNumber(credentialCounter) .attributeRandomness(attributeRandomness) .blindingRandomness(wallet.getSignatureBlindingRandomness(0, 0)) diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/FileHelpers.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/FileHelpers.java new file mode 100644 index 000000000..96421ccea --- /dev/null +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/FileHelpers.java @@ -0,0 +1,48 @@ +package com.concordium.sdk.crypto.wallet; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; +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.fasterxml.jackson.databind.type.MapType; +import com.fasterxml.jackson.databind.type.TypeFactory; + +public class FileHelpers { + public static String readFile(String path, Charset encoding) + throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + + public static CryptographicParameters getCryptographicParameters() throws Exception { + return JsonMapper.INSTANCE.readValue( + readFile("./src/test/testresources/wallet/global.json", Charset.forName("UTF-8")), + CryptographicParameters.class); + } + + public static IdentityProviderInfo getIdentityProviderInfo() throws Exception { + return JsonMapper.INSTANCE.readValue( + readFile("./src/test/testresources/wallet/ip_info.json", Charset.forName("UTF-8")), + IdentityProviderInfo.class); + } + + public static Map getAnonymityRevokerInfos() throws Exception { + MapType mapType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, + AnonymityRevokerInfo.class); + return JsonMapper.INSTANCE.readValue( + readFile("./src/test/testresources/wallet/ars_infos.json", Charset.forName("UTF-8")), mapType); + } + + public static IdentityObject getIdentityObject() throws Exception { + return JsonMapper.INSTANCE.readValue( + readFile("./src/test/testresources/wallet/id_object.json", Charset.forName("UTF-8")), + IdentityObject.class); } + +} diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/IdentityTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/IdentityTest.java index cef3959ef..0af9ea84e 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/IdentityTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/IdentityTest.java @@ -2,51 +2,14 @@ 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.Map; - import org.junit.Test; import com.concordium.sdk.crypto.bls.BLSSecretKey; -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.fasterxml.jackson.databind.type.MapType; -import com.fasterxml.jackson.databind.type.TypeFactory; public class IdentityTest { private static String TEST_SEED = "efa5e27326f8fa0902e647b52449bf335b7b605adc387015ec903f41d95080eb71361cbc7fb78721dcd4f3926a337340aa1406df83332c44c1cdcfe100603860"; - static String readFile(String path, Charset encoding) - throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } - - private CryptographicParameters getCryptographicParameters() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/global.json", Charset.forName("UTF-8")), - CryptographicParameters.class); - } - - private IdentityProviderInfo getIdentityProviderInfo() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/ip_info.json", Charset.forName("UTF-8")), - IdentityProviderInfo.class); - } - - private Map getAnonymityRevokerInfos() throws Exception { - MapType mapType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, - AnonymityRevokerInfo.class); - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/ars_infos.json", Charset.forName("UTF-8")), mapType); - } - @Test public void testCreatingIdentityRequest() throws Exception { ConcordiumHdWallet wallet = ConcordiumHdWallet.fromHex(TEST_SEED, Network.TESTNET); @@ -55,9 +18,9 @@ public void testCreatingIdentityRequest() throws Exception { String blindingRandomness = wallet.getSignatureBlindingRandomness(0, 0); IdentityRequestInput input = IdentityRequestInput.builder() - .globalContext(getCryptographicParameters()) - .ipInfo(getIdentityProviderInfo()) - .arsInfos(getAnonymityRevokerInfos()) + .globalContext(FileHelpers.getCryptographicParameters()) + .ipInfo(FileHelpers.getIdentityProviderInfo()) + .arsInfos(FileHelpers.getAnonymityRevokerInfos()) .arThreshold(2) .idCredSec(idCredSec) .prfKey(prfKey) @@ -73,7 +36,7 @@ public void testCreatingIdentityRequest() throws Exception { @Test public void testCreatingIdentityRecoveryRequest() throws Exception { IdentityRecoveryRequestInput input = IdentityRecoveryRequestInput.builder() - .globalContext(getCryptographicParameters()).ipInfo(getIdentityProviderInfo()).timestamp(0) + .globalContext(FileHelpers.getCryptographicParameters()).ipInfo(FileHelpers.getIdentityProviderInfo()).timestamp(0) .idCredSec(BLSSecretKey.from("7392eb0b4840c8a6f9314e99a8dd3e2c3663a1e615d8820851e3abd2965fab18")) .build(); diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java index e43721611..caabf2159 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java @@ -1,25 +1,17 @@ package com.concordium.sdk.crypto.wallet.web3Id; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.contains; import static org.junit.Assert.assertThat; -import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.is; - -import java.io.IOException; import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Iterator; import java.util.List; import org.junit.Test; -import com.concordium.sdk.Range; +import com.concordium.sdk.crypto.wallet.FileHelpers; 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; @@ -27,38 +19,25 @@ 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.responses.cryptographicparameters.CryptographicParameters; import com.concordium.sdk.serializing.JsonMapper; import com.fasterxml.jackson.core.type.TypeReference; public class ProofTest { - static String readFile(String path, Charset encoding) - throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } - static public Request loadRequest(String fileName) throws Exception { return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/web3Id/" + fileName, Charset.forName("UTF-8")), + FileHelpers.readFile("./src/test/testresources/wallet/web3Id/" + fileName, Charset.forName("UTF-8")), Request.class ); } public List loadCommitmentInputs(String fileName) throws Exception { return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/web3Id/" + fileName, Charset.forName("UTF-8")), + FileHelpers.readFile("./src/test/testresources/wallet/web3Id/" + fileName, Charset.forName("UTF-8")), new TypeReference>(){} ); } - private CryptographicParameters getCryptographicParameters() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/global.json", Charset.forName("UTF-8")), - CryptographicParameters.class); - } - @Test public void testCanParseRequest() throws Exception { Request request = loadRequest("accountRequest.json"); @@ -126,7 +105,7 @@ public void testCanCreateProofForAccountCredential() throws Exception { Web3IdProofInput input = Web3IdProofInput.builder() .request(loadRequest("accountRequest.json")) .commitmentInputs(loadCommitmentInputs("accountCommitments.json")) - .globalContext(getCryptographicParameters()) + .globalContext(FileHelpers.getCryptographicParameters()) .build(); String proof = Web3IdProof.getWeb3IdProof(input); assertNotNull(proof); @@ -170,7 +149,7 @@ public void testCanCreateProofForWeb3IdCredential() throws Exception { Web3IdProofInput input = Web3IdProofInput.builder() .request(loadRequest("web3IdRequest.json")) .commitmentInputs(loadCommitmentInputs("web3IdCommitments.json")) - .globalContext(getCryptographicParameters()) + .globalContext(FileHelpers.getCryptographicParameters()) .build(); String proof = Web3IdProof.getWeb3IdProof(input); assertNotNull(proof); diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java index cc20b32ba..79767e452 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java @@ -3,37 +3,21 @@ import static org.junit.Assert.assertEquals; 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.List; import org.junit.Test; +import com.concordium.sdk.crypto.wallet.FileHelpers; import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; import com.concordium.sdk.crypto.wallet.web3Id.Statement.AtomicStatement; import com.concordium.sdk.crypto.wallet.web3Id.Statement.RequestStatement; -import com.concordium.sdk.serializing.JsonMapper; public class RequestStatementTest { - - static String readFile(String path, Charset encoding) - throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); - } - - private IdentityObject getIdentityObject() throws Exception { - return JsonMapper.INSTANCE.readValue( - readFile("./src/test/testresources/wallet/id_object.json", Charset.forName("UTF-8")), - IdentityObject.class); - } - + @Test public void testCanIdentitySatisfyStatement() throws Exception { - IdentityObject identityObject = getIdentityObject(); + IdentityObject identityObject = FileHelpers.getIdentityObject(); List statements = ProofTest.loadRequest("accountRequest.json").getCredentialStatements(); RequestStatement requestStatement1 = statements.get(0); @@ -42,7 +26,7 @@ public void testCanIdentitySatisfyStatement() throws Exception { @Test public void testGetsUnsatisfiedStatement() throws Exception { - IdentityObject identityObject = getIdentityObject(); + IdentityObject identityObject = FileHelpers.getIdentityObject(); List statements = ProofTest.loadRequest("accountRequestUnder18.json").getCredentialStatements(); RequestStatement requestStatement1 = statements.get(0); From 095a0432c8df2ae15c394625764bdf4e7f6bf90b Mon Sep 17 00:00:00 2001 From: Hjort Date: Wed, 21 Feb 2024 16:07:08 +0100 Subject: [PATCH 5/7] Address Feedback --- .../concordium/sdk/crypto/wallet/Network.java | 11 +++ .../wallet/identityobject/IdentityObject.java | 5 +- .../wallet/web3Id/CredentialAttribute.java | 8 +-- .../web3Id/Statement/AtomicStatement.java | 8 ++- .../web3Id/Statement/MembershipStatement.java | 4 +- .../Statement/NonMembershipStatement.java | 8 ++- .../web3Id/Statement/RangeStatement.java | 4 +- .../web3Id/Statement/RequestStatement.java | 26 +++++-- .../web3Id/Statement/StatementType.java | 10 +++ .../did/AccountRequestIdentifier.java | 52 ++++++++++++++ .../Statement/did/RequestIdentifier.java | 45 +++++++++++++ .../did/Web3IssuerRequestIdentifier.java | 67 +++++++++++++++++++ .../accountinfo/credential/AttributeType.java | 4 +- .../web3Id/CredentialAttributeTest.java | 29 ++++++++ .../sdk/crypto/wallet/web3Id/ProofTest.java | 6 +- .../wallet/web3Id/RequestStatementTest.java | 1 - 16 files changed, 265 insertions(+), 23 deletions(-) create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/StatementType.java create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/AccountRequestIdentifier.java create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java create mode 100644 concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java create mode 100644 concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/Network.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/Network.java index 55df303a1..87c0d7e40 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/Network.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/Network.java @@ -11,4 +11,15 @@ public String getValue() { default: throw new IllegalArgumentException("An unsupported network was provided"); } } + + static public Network fromLowerCase(String value) { + switch (value) { + case "mainnet": + return MAINNET; + case "testnet": + return TESTNET; + default: + throw new IllegalArgumentException("An unsupported network was provided"); + } + } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java index 104f5ba7a..88998845b 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/identityobject/IdentityObject.java @@ -1,9 +1,10 @@ package com.concordium.sdk.crypto.wallet.identityobject; +import java.util.Map; + import com.concordium.sdk.responses.accountinfo.credential.AttributeType; import lombok.Getter; -import lombok.val; @Getter public class IdentityObject { @@ -13,7 +14,7 @@ public class IdentityObject { private String signature; public String getChosenAttribute(AttributeType attribute) throws MissingAttributeException { - val chosenAttributes = this.getAttributeList().getChosenAttributes(); + Map chosenAttributes = this.getAttributeList().getChosenAttributes(); if (!chosenAttributes.containsKey(attribute)) { throw new MissingAttributeException(attribute); } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java index 997242c88..b897e4866 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttribute.java @@ -54,10 +54,10 @@ public boolean isBetween(CredentialAttribute lower, CredentialAttribute upper) t } switch (this.type) { case INT: { - long lowerVal = Long.parseLong(lower.getValue()); - long upperVal = Long.parseLong(upper.getValue()); - long val = Long.parseLong(this.getValue()); - return lowerVal <= val && val < upperVal; + long lowerVal = Long.parseUnsignedLong(lower.getValue()); + long upperVal = Long.parseUnsignedLong(upper.getValue()); + long val = Long.parseUnsignedLong(this.getValue()); + return Long.compareUnsigned(lowerVal, val) <= 0 && Long.compareUnsigned(upperVal, val) > 0; } case TIMESTAMP: { LocalDateTime lowerVal = LocalDateTime.parse(lower.getValue()); diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java index f0e545093..eff93b8f1 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/AtomicStatement.java @@ -4,11 +4,14 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; +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; @@ -19,11 +22,10 @@ public abstract class AtomicStatement { public abstract String getAttributeTag(); // TODO: add overload for web3Id credential - protected CredentialAttribute getAttributeValue(IdentityObject identityObject) throws Exception { + protected CredentialAttribute getAttributeValue(IdentityObject identityObject) throws JsonProcessingException, JsonParseException, MissingAttributeException { AttributeType type = AttributeType.fromJSON(this.getAttributeTag()); - String raw = identityObject.getAttributeList().getChosenAttributes().get(type); + String raw = identityObject.getChosenAttribute(type); return CredentialAttribute.builder().value(raw).type(CredentialAttribute.CredentialAttributeType.STRING).build(); - } // TODO: add overload for web3Id credential diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java index bd08ae62b..e1e52316d 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/MembershipStatement.java @@ -6,6 +6,8 @@ import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException; import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute; import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; import lombok.Getter; @@ -16,7 +18,7 @@ public class MembershipStatement extends AtomicStatement { private List set; @Override - public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { + public boolean canBeProvedBy(IdentityObject identityObject) throws JsonParseException, JsonProcessingException { try { CredentialAttribute value = this.getAttributeValue(identityObject); return set.contains(value); diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java index c86ea4019..2c6cadd12 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/NonMembershipStatement.java @@ -3,8 +3,11 @@ import java.util.List; 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.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; import lombok.Getter; @@ -15,11 +18,12 @@ public class NonMembershipStatement extends AtomicStatement { private List set; @Override - public boolean canBeProvedBy(IdentityObject identityObject) { + public boolean canBeProvedBy(IdentityObject identityObject) throws JsonParseException, JsonProcessingException { try { CredentialAttribute value = this.getAttributeValue(identityObject); return !set.contains(value); - } catch (Exception e) { + } catch (MissingAttributeException e) { + // If the identityObject does not have the relevant attribute, it does not satisfy the statement return false; } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java index 4747ddd78..84e248511 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RangeStatement.java @@ -4,6 +4,8 @@ import com.concordium.sdk.crypto.wallet.identityobject.MissingAttributeException; import com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute; import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; import lombok.Builder; import lombok.Getter; @@ -18,7 +20,7 @@ public class RangeStatement extends AtomicStatement { private CredentialAttribute upper; private String attributeTag; @Override - public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { + public boolean canBeProvedBy(IdentityObject identityObject) throws JsonParseException, JsonProcessingException { try { CredentialAttribute value = getAttributeValue(identityObject); return value.isBetween(lower, upper); diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java index 1503e48df..0a8e2bfa3 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/RequestStatement.java @@ -4,6 +4,8 @@ import java.util.stream.Collectors; import com.concordium.sdk.crypto.wallet.identityobject.IdentityObject; +import com.concordium.sdk.crypto.wallet.web3Id.Statement.did.RequestIdentifier; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; import lombok.Getter; @@ -13,11 +15,20 @@ @Builder @Jacksonized public class RequestStatement { - private String id; - private List type; + private RequestIdentifier id; + @JsonProperty("type") + private List verifiableCredentialTypes; private List statement; + public StatementType getStatementType() { + return this.id.getType(); + } + public List getUnsatisfiedStatements(IdentityObject identityObject) { + if (!this.getStatementType().equals(StatementType.Credential)) { + throw new IllegalArgumentException("Only an account statement can be satisfied by an identity"); + } + return statement.stream().filter(s -> { try { return !s.canBeProvedBy(identityObject); @@ -28,10 +39,15 @@ public List getUnsatisfiedStatements(IdentityObject identityObj } public boolean canBeProvedBy(IdentityObject identityObject) throws Exception { - for (AtomicStatement s: this.statement) { - if (s.canBeProvedBy(identityObject)) continue; + if (!this.getStatementType().equals(StatementType.Credential)) { + throw new IllegalArgumentException("Only an account statement can by proven using a identity"); + } + + for (AtomicStatement s : this.statement) { + if (s.canBeProvedBy(identityObject)) + continue; return false; } - return true; + return true; } } diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/StatementType.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/StatementType.java new file mode 100644 index 000000000..4ac11d94e --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/StatementType.java @@ -0,0 +1,10 @@ +package com.concordium.sdk.crypto.wallet.web3Id.Statement; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public enum StatementType { + @JsonProperty("cred") + Credential, + @JsonProperty("sci") + SmartContract +} diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/AccountRequestIdentifier.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/AccountRequestIdentifier.java new file mode 100644 index 000000000..f766b1471 --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/AccountRequestIdentifier.java @@ -0,0 +1,52 @@ +package com.concordium.sdk.crypto.wallet.web3Id.Statement.did; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; + +import com.concordium.sdk.crypto.wallet.Network; +import com.concordium.sdk.crypto.wallet.web3Id.Statement.StatementType; +import com.concordium.sdk.transactions.CredentialRegistrationId; +import com.fasterxml.jackson.annotation.JsonValue; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class AccountRequestIdentifier extends RequestIdentifier { + private CredentialRegistrationId credId; + private static Pattern pattern = Pattern.compile( "^" + getDID("(mainnet|testnet)", "([a-zA-Z0-9]*)") + "$"); + + @Builder + public AccountRequestIdentifier(Network network, CredentialRegistrationId credId) { + super(network); + this.credId = credId; + } + + private static String getDID(String network, String credId) { + return "did:ccd:" + network + ":cred:" + credId; + } + + @JsonValue + @Override + public String toString() { + return getDID(network.getValue().toLowerCase(), credId.getEncoded()); + } + + @Nullable + public static AccountRequestIdentifier tryFromString(String did) { + Matcher matcher = pattern.matcher(did); + if (matcher.matches()) { + Network network = Network.fromLowerCase(matcher.group(1)); + CredentialRegistrationId credId = CredentialRegistrationId.from(matcher.group(2)); + return new AccountRequestIdentifier(network, credId); + } + return null; + } + + @Override + public StatementType getType() { + return StatementType.Credential; + } +} diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java new file mode 100644 index 000000000..1780170d9 --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java @@ -0,0 +1,45 @@ +package com.concordium.sdk.crypto.wallet.web3Id.Statement.did; + +import java.io.IOException; +import com.concordium.sdk.crypto.wallet.Network; +import com.concordium.sdk.crypto.wallet.web3Id.Statement.StatementType; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +@JsonDeserialize(using = RequestIdentifierDeserializer.class) +public abstract class RequestIdentifier { + Network network; + + public abstract StatementType getType(); +} + +class RequestIdentifierDeserializer extends JsonDeserializer { + @Override + public RequestIdentifier deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + System.out.println("Test"); + JsonNode reference = p.getCodec().readTree(p); + if (!reference.isTextual()) { + throw new JsonParseException(p, "RequestIdentifier must be deserialize from a String"); + } + String did = reference.asText(); + + AccountRequestIdentifier accountDID = AccountRequestIdentifier.tryFromString(did); + if (accountDID != null) { + return accountDID; + } + Web3IssuerRequestIdentifier web3DID = Web3IssuerRequestIdentifier.tryFromString(did); + if (web3DID != null) { + return web3DID; + } + throw new JsonParseException(p, "Given string is not a valid request statement did"); + } +} diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java new file mode 100644 index 000000000..2481e7248 --- /dev/null +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java @@ -0,0 +1,67 @@ +package com.concordium.sdk.crypto.wallet.web3Id.Statement.did; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +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; +import com.concordium.sdk.types.ContractAddress; +import com.fasterxml.jackson.annotation.JsonValue; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class Web3IssuerRequestIdentifier extends RequestIdentifier { + private ContractAddress address; + private ED25519PublicKey publicKey; + private static Pattern pattern = Pattern.compile("^" + getDID("(mainnet|testnet)", "([0-9]*)", "([0-9]*)", "([a-zA-Z0-9]*)") + "$", Pattern.CASE_INSENSITIVE); + + @Builder + public Web3IssuerRequestIdentifier(Network network, ContractAddress address, ED25519PublicKey publicKey) { + super(network); + this.address = address; + this.publicKey = publicKey; + } + + private static String getDID(String network, String index, String subindex, String publicKey) { + return "did:ccd:" + + network + + ":sci:" + + index + + ":" + + subindex + + "/credentialEntry/" + + publicKey; + } + + @JsonValue + @Override + public String toString() { + return getDID(network.getValue().toLowerCase(), Long.toUnsignedString(address.getIndex()), Long.toUnsignedString(address.getSubIndex()), + Hex.encodeHexString(publicKey.getRawBytes())); + } + + @Nullable + public static Web3IssuerRequestIdentifier tryFromString(String did) { + Matcher matcher = pattern.matcher(did); + if (matcher.matches()) { + Network network = Network.fromLowerCase(matcher.group(1)); + long index = Long.parseUnsignedLong(matcher.group(2)); + long subindex = Long.parseUnsignedLong(matcher.group(3)); + ED25519PublicKey publicKey = ED25519PublicKey.from(matcher.group(4)); + return new Web3IssuerRequestIdentifier(network, ContractAddress.from(index, subindex), publicKey); + } + return null; + } + + @Override + public StatementType getType() { + return StatementType.SmartContract; + } +} diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java index 038ce4b2f..4ec565ba9 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/responses/accountinfo/credential/AttributeType.java @@ -2,6 +2,8 @@ import com.concordium.sdk.serializing.JsonMapper; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; /** * Identity attributes of which a {@link Commitment} is generated for by the identity provider. @@ -39,7 +41,7 @@ public enum AttributeType { @JsonProperty("lei") LEI; - public static AttributeType fromJSON(String jsonStr) throws Exception { + public static AttributeType fromJSON(String jsonStr) throws JsonMappingException, JsonProcessingException { return JsonMapper.INSTANCE.readValue(String.format("\"%s\"", jsonStr), AttributeType.class); } } diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java new file mode 100644 index 000000000..950f7a3ca --- /dev/null +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java @@ -0,0 +1,29 @@ +package com.concordium.sdk.crypto.wallet.web3Id; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import static com.concordium.sdk.crypto.wallet.web3Id.CredentialAttribute.CredentialAttributeType.INT; + +public class CredentialAttributeTest { + @Test + public void testIsBetweenForNumberAttributes() { + CredentialAttribute low = new CredentialAttribute("9", INT); + CredentialAttribute middle = new CredentialAttribute("10", INT); + CredentialAttribute high = new CredentialAttribute("11", INT); + assertTrue(!low.isBetween(middle, high)); + assertTrue(middle.isBetween(low, high)); + assertTrue(!high.isBetween(low, middle)); + } + + @Test + public void testIsBetweenHandles64BitNumbers() { + CredentialAttribute low = new CredentialAttribute("1", INT); + CredentialAttribute middle = new CredentialAttribute("18446744073709551600", INT); + CredentialAttribute high = new CredentialAttribute("18446744073709551615", INT); + assertTrue(!low.isBetween(middle, high)); + assertTrue(middle.isBetween(low, high)); + assertTrue(!high.isBetween(low, middle)); + } +} diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java index caabf2159..d86e7bcd3 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/ProofTest.java @@ -45,7 +45,7 @@ public void testCanParseRequest() throws Exception { assertEquals("beefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeefbeef", request.getChallenge()); RequestStatement credentialStatement = request.getCredentialStatements().get(0); - assertEquals("did:ccd:testnet:cred:a88a8214fc7a7f11aeda54661b76a1fd7c67e15278b83a85ec92cb799ef0abaa3b7c61a7e90ea6bb108fa2ca1a3ba217", credentialStatement.getId()); + assertEquals("did:ccd:testnet:cred:a88a8214fc7a7f11aeda54661b76a1fd7c67e15278b83a85ec92cb799ef0abaa3b7c61a7e90ea6bb108fa2ca1a3ba217", credentialStatement.getId().toString()); Iterator iter = credentialStatement.getStatement().iterator(); @@ -118,9 +118,9 @@ public void testCanParseWeb3IdRequest() throws Exception { assertEquals("5d50c6e18aca83e991af81e7d7e760f5dc753db7966dc19e9aa42f25aef1696b", request.getChallenge()); RequestStatement credentialStatement = request.getCredentialStatements().get(0); - assertEquals("did:ccd:testnet:sci:6105:0/credentialEntry/31163ba14e30b834f1e97b9544d86df94883fd4f2c77e1d1fac0b6189c9e7996", credentialStatement.getId()); + assertEquals("did:ccd:testnet:sci:6105:0/credentialEntry/31163ba14e30b834f1e97b9544d86df94883fd4f2c77e1d1fac0b6189c9e7996", credentialStatement.getId().toString()); - List type = credentialStatement.getType(); + List type = credentialStatement.getVerifiableCredentialTypes(); assert(type.stream().anyMatch(item -> item.equals("VerifiableCredential"))); assert(type.stream().anyMatch(item -> item.equals("ConcordiumVerifiableCredential"))); assert(type.stream().anyMatch(item -> item.equals("UniversityDegreeCredential"))); diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java index 79767e452..babc0a781 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/RequestStatementTest.java @@ -12,7 +12,6 @@ import com.concordium.sdk.crypto.wallet.web3Id.Statement.AtomicStatement; import com.concordium.sdk.crypto.wallet.web3Id.Statement.RequestStatement; - public class RequestStatementTest { @Test From 9e417adf4a5be2dab3c31c608e2a1c0da443e2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Hjort?= <87635671+shjortConcordium@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:02:51 +0100 Subject: [PATCH 6/7] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakob Ørhøj <57264157+orhoj@users.noreply.github.com> --- .../crypto/wallet/web3Id/Statement/did/RequestIdentifier.java | 3 +-- .../web3Id/Statement/did/Web3IssuerRequestIdentifier.java | 2 +- .../sdk/crypto/wallet/web3Id/CredentialAttributeTest.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java index 1780170d9..3264bea0e 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/RequestIdentifier.java @@ -25,10 +25,9 @@ public abstract class RequestIdentifier { class RequestIdentifierDeserializer extends JsonDeserializer { @Override public RequestIdentifier deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - System.out.println("Test"); JsonNode reference = p.getCodec().readTree(p); if (!reference.isTextual()) { - throw new JsonParseException(p, "RequestIdentifier must be deserialize from a String"); + throw new JsonParseException(p, "RequestIdentifier must be deserialized from a String"); } String did = reference.asText(); diff --git a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java index 2481e7248..1609dadba 100644 --- a/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java +++ b/concordium-sdk/src/main/java/com/concordium/sdk/crypto/wallet/web3Id/Statement/did/Web3IssuerRequestIdentifier.java @@ -44,7 +44,7 @@ private static String getDID(String network, String index, String subindex, Stri @Override public String toString() { return getDID(network.getValue().toLowerCase(), Long.toUnsignedString(address.getIndex()), Long.toUnsignedString(address.getSubIndex()), - Hex.encodeHexString(publicKey.getRawBytes())); + publicKey.toString()); } @Nullable diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java index 950f7a3ca..1c5d49c80 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java @@ -22,7 +22,7 @@ public void testIsBetweenHandles64BitNumbers() { CredentialAttribute low = new CredentialAttribute("1", INT); CredentialAttribute middle = new CredentialAttribute("18446744073709551600", INT); CredentialAttribute high = new CredentialAttribute("18446744073709551615", INT); - assertTrue(!low.isBetween(middle, high)); + assertFalse(low.isBetween(middle, high)); assertTrue(middle.isBetween(low, high)); assertTrue(!high.isBetween(low, middle)); } From 4f5e42d388e5d0fca9c9ca0461a69f721aa49647 Mon Sep 17 00:00:00 2001 From: Hjort Date: Wed, 28 Feb 2024 16:29:41 +0100 Subject: [PATCH 7/7] Use assertFalse --- .../sdk/crypto/wallet/web3Id/CredentialAttributeTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java index 1c5d49c80..753b3ac1f 100644 --- a/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java +++ b/concordium-sdk/src/test/java/com/concordium/sdk/crypto/wallet/web3Id/CredentialAttributeTest.java @@ -1,5 +1,6 @@ package com.concordium.sdk.crypto.wallet.web3Id; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -12,9 +13,9 @@ public void testIsBetweenForNumberAttributes() { CredentialAttribute low = new CredentialAttribute("9", INT); CredentialAttribute middle = new CredentialAttribute("10", INT); CredentialAttribute high = new CredentialAttribute("11", INT); - assertTrue(!low.isBetween(middle, high)); + assertFalse(low.isBetween(middle, high)); assertTrue(middle.isBetween(low, high)); - assertTrue(!high.isBetween(low, middle)); + assertFalse(high.isBetween(low, middle)); } @Test @@ -24,6 +25,6 @@ public void testIsBetweenHandles64BitNumbers() { CredentialAttribute high = new CredentialAttribute("18446744073709551615", INT); assertFalse(low.isBetween(middle, high)); assertTrue(middle.isBetween(low, high)); - assertTrue(!high.isBetween(low, middle)); + assertFalse(high.isBetween(low, middle)); } }