Skip to content

Commit

Permalink
Merge pull request #528 from catenax-ng/feature/TRI-1610-change-logic…
Browse files Browse the repository at this point in the history
…-and-logs

feat(impl):[TRI-1610] change logic and add logs
  • Loading branch information
ds-ext-kmassalski authored Sep 7, 2023
2 parents 397f9c5 + efc5fb9 commit f4f1a1c
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public static class ChildData {
private String childCatenaXId;
private Set<Reference> reference;

/**
*
* @param catenaXId filter
* @return Check if childCatenaXId matches argument
*/
public boolean childCatenaXIdMatches(final String catenaXId) {
return this.childCatenaXId.equals(catenaXId);
}

}

/**
Expand All @@ -64,5 +73,12 @@ public static class Reference {
private String hash;
private String signature;

/**
* @param aspectType filter
* @return Check if semanticModelUrn matches argument
*/
public boolean semanticModelUrnMatches(final String aspectType) {
return this.getSemanticModelUrn().equals(aspectType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private void addSubmodelToList(final EdcSubmodelFacade submodelFacade, final End
submodelFacade.getSubmodelRawPayload(connectorEndpoint, endpoint.getProtocolInformation().getHref(),
extractAssetId(endpoint.getProtocolInformation().getSubprotocolBody())));
} catch (ItemNotFoundInCatalogException e) {
log.info("Could not find asset in catalog. Requesting next endpoint.", e);
log.debug("Could not find asset in catalog. Requesting next endpoint.", e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,14 @@ private Optional<IntegrityAspect> getIntegrityAspect(final Endpoint endpoint, fi
itemId.getGlobalAssetId());
itemContainerBuilder.tombstone(
Tombstone.from(itemId.getGlobalAssetId(), endpoint.getProtocolInformation().getHref(),
"Can't get relationship without a BPN", retryCount, ProcessStep.DATA_INTEGRITY_CHECK));
"Can't get Data Integrity aspect without a BPN", retryCount, ProcessStep.DATA_INTEGRITY_CHECK));
return Optional.empty();
}

try {
final String submodelRawPayload = requestSubmodelAsString(submodelFacade, connectorEndpointsService,
endpoint, itemId.getBpn());
log.debug("Found DataIntegrity aspect for item: {}", itemId.getGlobalAssetId());

return Optional.ofNullable(jsonUtil.fromString(submodelRawPayload, IntegrityAspect.class));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
Expand All @@ -58,6 +57,7 @@
@Slf4j
public class DataIntegrityService {

private static final String SHA3_256 = "SHA3-256";
private AsymmetricKeyParameter publicKey;

public DataIntegrityService(@Value("${integrity.publicKeyCert:}") final String publicKeyCert) {
Expand All @@ -76,38 +76,41 @@ public DataIntegrityService(@Value("${integrity.publicKeyCert:}") final String p
* @return flag indicates if chain is valid
*/
public IntegrityState chainDataIntegrityIsValid(final ItemContainer itemContainer) {
final long numberOfValidSubmodels = itemContainer.getSubmodels().stream().takeWhile(submodel -> {
try {
return submodelDataIntegrityIsValid(submodel, itemContainer.getIntegrities());
} catch (NoSuchElementException | NoSuchAlgorithmException exc) {
log.error("DataIntegrity aspect is missing. Integrity of data chain cannot be determined.");
return false;
}
}).count();
log.debug("Starting validation of Data Chain Integrity with {} integrity aspects.", itemContainer.getIntegrities().size());
final long numberOfValidSubmodels = itemContainer.getSubmodels()
.stream()
.takeWhile(submodel -> submodelDataIntegrityIsValid(submodel, itemContainer.getIntegrities()))
.count();

return IntegrityState.from(numberOfValidSubmodels, totalNumberOfSubmodels(itemContainer));
}

private boolean submodelDataIntegrityIsValid(final Submodel submodel, final Set<IntegrityAspect> integrities)
throws NoSuchAlgorithmException {
final IntegrityAspect.ChildData childData = integrities.stream()
.map(IntegrityAspect::getChildParts)
.flatMap(Set::stream)
.filter(findIntegrityChildPart(submodel.getCatenaXId()))
.findFirst()
.orElseThrow();

final IntegrityAspect.Reference reference = childData.getReference()
.stream()
.filter(findReference(submodel.getAspectType()))
.findFirst()
.orElseThrow();

final String calculatedHash = calculateHashForRawSubmodelPayload(submodel.getPayload());
log.debug("Comparing hashes and signatures Data integrity of Submodel id: {}", submodel.getIdentification());

return hashesEquals(reference.getHash(), calculatedHash)
&& signaturesEquals(reference.getSignature(), bytesOf(submodel.getPayload()));
private boolean submodelDataIntegrityIsValid(final Submodel submodel, final Set<IntegrityAspect> integrities) {
final Optional<IntegrityAspect.Reference> reference = findIntegrityAspectReferenceForSubmodel(submodel, integrities);

if (reference.isPresent()) {
log.debug("Calculating hash of Submodel id: {}", submodel.getIdentification());
final String calculatedHash = calculateHashForRawSubmodelPayload(submodel.getPayload());

log.debug("Comparing hashes and signatures Data integrity of Submodel id: {}", submodel.getIdentification());
return hashesEquals(reference.get().getHash(), calculatedHash)
&& signaturesEquals(reference.get().getSignature(), bytesOf(submodel.getPayload()));
} else {
log.debug("Integrity of Data chain cannot be determined, as Data Integrity Aspect Reference was not found for Submodel: {}, {}", submodel.getIdentification(), submodel.getAspectType());
return false;
}
}

private Optional<IntegrityAspect.Reference> findIntegrityAspectReferenceForSubmodel(final Submodel submodel, final Set<IntegrityAspect> integrities) {
return integrities.stream()
.map(IntegrityAspect::getChildParts)
.flatMap(Set::stream)
.filter(childData -> childData.childCatenaXIdMatches(submodel.getCatenaXId()))
.findFirst()
.flatMap(childData -> childData.getReference()
.stream()
.filter(reference -> reference.semanticModelUrnMatches(submodel.getAspectType()))
.findFirst());
}

private static boolean hashesEquals(final String hashReference, final String calculatedHash) {
Expand All @@ -126,24 +129,19 @@ private int totalNumberOfSubmodels(final ItemContainer itemContainer) {
return itemContainer.getSubmodels().size();
}

private String calculateHashForRawSubmodelPayload(final Map<String, Object> payload)
throws NoSuchAlgorithmException {
log.debug("Calculating hash for payload '{}", payload);
private String calculateHashForRawSubmodelPayload(final Map<String, Object> payload) {
final byte[] digest = bytesOf(payload);
log.debug("Returning hash '{}'", Hex.toHexString(digest));
return Hex.toHexString(digest);
}

private byte[] bytesOf(final Map<String, Object> payload) throws NoSuchAlgorithmException {
return MessageDigest.getInstance("SHA3-256").digest(mapToString(payload).getBytes(StandardCharsets.UTF_8));
}

private Predicate<? super IntegrityAspect.Reference> findReference(final String aspectType) {
return reference -> reference.getSemanticModelUrn().equals(aspectType);
}

private Predicate<? super IntegrityAspect.ChildData> findIntegrityChildPart(final String catenaXId) {
return integrityChildPart -> integrityChildPart.getChildCatenaXId().equals(catenaXId);
private byte[] bytesOf(final Map<String, Object> payload) {
try {
return MessageDigest.getInstance(SHA3_256).digest(mapToString(payload).getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException exc) {
log.error("Integrity of Data chain cannot be determined, cant retrieve bytes from payload.", exc);
return new byte[0];
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ private void validateAspectTypeValues(final List<String> aspectTypeValues) {
try {
final HashSet<AspectModel> availableModels = new HashSet<>(
semanticsHubFacade.getAllAspectModels().models());
log.info("Available AspectModels: '{}'", availableModels);
log.info("Provided AspectModels: '{}'", aspectTypeValues);
log.debug("Available AspectModels: '{}'", availableModels);
log.debug("Provided AspectModels: '{}'", aspectTypeValues);
final Set<String> availableNames = new HashSet<>(availableModels.stream().map(AspectModel::name).toList());
final Set<String> availableUrns = new HashSet<>(availableModels.stream().map(AspectModel::urn).toList());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ public static RegisterJob registerJob(final String globalAssetId, final Integer
registerJob.setCollectAspects(collectAspects);
registerJob.setDirection(direction);
registerJob.setLookupBPNs(lookupBPNs);
registerJob.setIntegrityCheck(false);

return registerJob;
}
Expand Down

0 comments on commit f4f1a1c

Please sign in to comment.