Skip to content

Commit

Permalink
Improved verification of trust chain in identities
Browse files Browse the repository at this point in the history
  • Loading branch information
shifteverywhere committed Jan 26, 2023
1 parent cbdacfd commit 54d377c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 38 additions & 1 deletion src/main/java/io/dimeformat/Identity.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import io.dimeformat.enums.KeyCapability;
import io.dimeformat.keyring.IntegrityState;
import java.nio.charset.StandardCharsets;
import java.security.IdentityScope;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -104,6 +103,44 @@ public boolean isSelfIssued() {
return ((UUID) getClaim(Claim.SUB)).compareTo(getClaim(Claim.ISS)) == 0 && hasCapability(IdentityCapability.SELF);
}

/**
* Verifies the integrity and over all validity and trust of the item. The verification will be made using the public
* key in the provided identity. The verification will also check if the item has been issued by the provided
* identity, if the "iss" claim has been set. If the identity has a trust chain, then this will be taken into
* considerations while verifying.
* @param trustedIdentity A trusted identity to verify with, may be from anywhere in the trust chain.
* @param linkedItems A list of item where item links should be verified, may be null.
* @return The integrity state of the verification.
*/
@Override
public IntegrityState verify(Identity trustedIdentity, List<Item> linkedItems) {
IntegrityState state = IntegrityState.FAILED_NOT_TRUSTED;
Identity trustChain = getTrustChain();
if (trustChain != null) {
state = super.verify(trustChain, null);
if (state.isValid()) {
if (!trustChain.getClaim(Claim.SUB).equals(trustedIdentity.getClaim(Claim.SUB))) {
state = trustChain.verify(trustedIdentity, null);
} else {
if (trustedIdentity.isSelfIssued()) {
// If this is the end of the trust chain, then verify the final identity
return trustedIdentity.verify(trustedIdentity.getPublicKey());
} else {
// If this is a truncated trust chain, then verify only the dates
state = trustedIdentity.verifyDates();
return !state.isValid() ? state : IntegrityState.INTACT;
}
}
}
if (state.isValid() && linkedItems != null) {
state = verifyLinkedItems(linkedItems);
}
} else {
state = super.verify(trustedIdentity, linkedItems);
}
return state;
}

@Override
public IntegrityState verify(Key verifyKey, List<Item> linkedItems) {
Identity trustChain = getTrustChain();
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/io/dimeformat/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,21 +230,20 @@ public IntegrityState verify(Identity issuingIdentity) {
* Verifies the integrity and over all validity and trust of the item. The verification will be made using the public
* key in the provided identity. The verification will also check if the item has been issued by the provided
* identity, if the "iss" claim has been set.
* @param issuingIdentity The issuing identity to use when verifying.
* @param trustedIdentity A trusted identity to verify with.
* @param linkedItems A list of item where item links should be verified, may be null.
* @return The integrity state of the verification.
*/
public IntegrityState verify(Identity issuingIdentity, List<Item> linkedItems) {

public IntegrityState verify(Identity trustedIdentity, List<Item> linkedItems) {
UUID issuerId = getClaim(Claim.ISS);
if (issuerId != null && !issuerId.equals(issuingIdentity.getClaim(Claim.SUB))) {
if (issuerId != null && !issuerId.equals(trustedIdentity.getClaim(Claim.SUB))) {
return IntegrityState.FAILED_ISSUER_MISMATCH;
}
IntegrityState state = issuingIdentity.verifyDates();
IntegrityState state = trustedIdentity.verifyDates();
if (!state.isValid()) {
return state;
}
return verify(issuingIdentity.getPublicKey(), linkedItems);
return verify(trustedIdentity.getPublicKey(), linkedItems);
}

/**
Expand Down
22 changes: 13 additions & 9 deletions src/test/java/io/dimeformat/IdentityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.dimeformat.enums.Claim;
import io.dimeformat.enums.IdentityCapability;
import io.dimeformat.exceptions.CapabilityException;
import io.dimeformat.keyring.IntegrityState;
import org.junit.jupiter.api.Test;
import io.dimeformat.enums.KeyCapability;
import java.time.Instant;
Expand Down Expand Up @@ -308,18 +309,21 @@ void verifyTest8() {
Commons.initializeKeyRing();
IdentityCapability[] nodeCaps = new IdentityCapability[] { IdentityCapability.GENERIC, IdentityCapability.ISSUE };
Key key1 = Key.generateKey(List.of(KeyCapability.SIGN));
Identity node1 = IdentityIssuingRequest.generateIIR(key1, nodeCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_MINUTE, Commons.getTrustedKey(), Commons.getTrustedIdentity(), true, nodeCaps, nodeCaps);
Identity node1 = IdentityIssuingRequest.generateIIR(key1, nodeCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_HOUR, Commons.getTrustedKey(), Commons.getTrustedIdentity(), true, nodeCaps, nodeCaps);
Key key2 = Key.generateKey(List.of(KeyCapability.SIGN));
Identity node2 = IdentityIssuingRequest.generateIIR(key2, nodeCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_MINUTE, key1, node1, true, nodeCaps, nodeCaps);
Identity node2 = IdentityIssuingRequest.generateIIR(key2, nodeCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_HOUR, key1, node1, true, nodeCaps, nodeCaps);
Key key3 = Key.generateKey(List.of(KeyCapability.SIGN));
Identity node3 = IdentityIssuingRequest.generateIIR(key3, nodeCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_MINUTE, key2, node2, true, nodeCaps, nodeCaps);
Identity node3 = IdentityIssuingRequest.generateIIR(key3, nodeCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_HOUR, key2, node2, true, nodeCaps, nodeCaps);
IdentityCapability[] leafCaps = new IdentityCapability[] { IdentityCapability.GENERIC };
Identity leaf = IdentityIssuingRequest.generateIIR(Key.generateKey(List.of(KeyCapability.SIGN)), leafCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_MINUTE, key3, node3, true, leafCaps, leafCaps);
assertTrue(leaf.verify().isValid()); // Verify the whole trust chain and key ring
assertFalse(leaf.verify(node1).isValid());
assertFalse(leaf.verify(node2).isValid());
assertTrue(leaf.verify(node3).isValid()); // verify as issuer
assertFalse(leaf.verify(Commons.getIntermediateIdentity()).isValid()); // verify as issuer
Identity leaf = IdentityIssuingRequest.generateIIR(Key.generateKey(List.of(KeyCapability.SIGN)), leafCaps).issueIdentity(UUID.randomUUID(), Dime.VALID_FOR_1_HOUR, key3, node3, true, leafCaps, leafCaps);
IntegrityState state = leaf.verify();
assertSame(IntegrityState.COMPLETE, leaf.verify());
Commons.clearKeyRing();
assertFalse(leaf.verify().isValid());
assertSame(IntegrityState.INTACT, leaf.verify(node1));
assertSame(IntegrityState.INTACT, leaf.verify(node2));
assertSame(IntegrityState.INTACT, leaf.verify(node3));
assertFalse(leaf.verify(Commons.getIntermediateIdentity()).isValid());
} catch (Exception e) {
fail("Unexpected exception thrown: " + e);
}
Expand Down

0 comments on commit 54d377c

Please sign in to comment.