diff --git a/pgpainless-wot/build.gradle b/pgpainless-wot/build.gradle new file mode 100644 index 00000000..f61a337c --- /dev/null +++ b/pgpainless-wot/build.gradle @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2021 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +plugins { + id 'java-library' +} + +group 'org.pgpainless' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" + + // Logging + testImplementation "ch.qos.logback:logback-classic:$logbackVersion" + + implementation(project(":pgpainless-core")) + + // Certificate store + api "org.pgpainless:pgp-certificate-store:$certDJavaVersion" +} + +test { + useJUnitPlatform() +} diff --git a/pgpainless-wot/src/main/java/org/pgpainless/wot/CertificateAuthority.java b/pgpainless-wot/src/main/java/org/pgpainless/wot/CertificateAuthority.java new file mode 100644 index 00000000..84f796bb --- /dev/null +++ b/pgpainless-wot/src/main/java/org/pgpainless/wot/CertificateAuthority.java @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2022 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.wot; + +import org.bouncycastle.openpgp.PGPPublicKeyRing; + +public interface CertificateAuthority { + + /** + * Returns
true
, if the given binding (certificate and user-id) is correct. + * Correct means, that the binding is trustworthy. + * + * @param certificate OpenPGP certificate + * @param userId user-id + * @return binding correctness + */ + boolean isAuthorized(PGPPublicKeyRing certificate, String userId); + +} diff --git a/pgpainless-wot/src/main/java/org/pgpainless/wot/WebOfTrust.java b/pgpainless-wot/src/main/java/org/pgpainless/wot/WebOfTrust.java new file mode 100644 index 00000000..926baec2 --- /dev/null +++ b/pgpainless-wot/src/main/java/org/pgpainless/wot/WebOfTrust.java @@ -0,0 +1,29 @@ +package org.pgpainless.wot; + +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import pgp.certificate_store.Certificate; +import pgp.certificate_store.exception.BadDataException; + +import java.io.IOException; + +public class WebOfTrust implements CertificateAuthority { + + private final WebOfTrustCertificateStore certificateStore; + + public WebOfTrust(WebOfTrustCertificateStore certificateStore) { + this.certificateStore = certificateStore; + } + + /** + * Do the heavy lifting of calculating the web of trust. + */ + public void initialize() throws BadDataException, IOException { + Certificate trustRoot = certificateStore.getTrustRoot(); + + } + + @Override + public boolean isAuthorized(PGPPublicKeyRing certificate, String userId) { + return false; + } +} diff --git a/pgpainless-wot/src/main/java/org/pgpainless/wot/WebOfTrustCertificateStore.java b/pgpainless-wot/src/main/java/org/pgpainless/wot/WebOfTrustCertificateStore.java new file mode 100644 index 00000000..20d9450d --- /dev/null +++ b/pgpainless-wot/src/main/java/org/pgpainless/wot/WebOfTrustCertificateStore.java @@ -0,0 +1,74 @@ +package org.pgpainless.wot; + +import pgp.certificate_store.Certificate; +import pgp.certificate_store.CertificateDirectory; +import pgp.certificate_store.MergeCallback; +import pgp.certificate_store.exception.BadDataException; +import pgp.certificate_store.exception.BadNameException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +public class WebOfTrustCertificateStore implements CertificateDirectory { + + private final CertificateDirectory certificateDirectory; + + public WebOfTrustCertificateStore(CertificateDirectory certificateDirectory) { + this.certificateDirectory = certificateDirectory; + } + + public Certificate getTrustRoot() throws BadDataException, IOException { + try { + return getCertificate("trust-root"); + } catch (BadNameException e) { + throw new AssertionError("The underlying certificate directory MUST support getting a trust-root certificate."); + } + } + + @Override + public Certificate getCertificate(String identifier) + throws IOException, BadNameException, BadDataException { + return certificateDirectory.getCertificate(identifier); + } + + @Override + public Certificate getCertificateIfChanged(String identifier, String tag) + throws IOException, BadNameException, BadDataException { + return certificateDirectory.getCertificateIfChanged(identifier, tag); + } + + @Override + public Certificate insertCertificate(InputStream data, MergeCallback merge) + throws IOException, InterruptedException, BadDataException { + return certificateDirectory.insertCertificate(data, merge); + } + + @Override + public Certificate tryInsertCertificate(InputStream data, MergeCallback merge) + throws IOException, BadDataException { + return certificateDirectory.tryInsertCertificate(data, merge); + } + + @Override + public Certificate insertCertificateBySpecialName(String specialName, InputStream data, MergeCallback merge) + throws IOException, InterruptedException, BadDataException, BadNameException { + return certificateDirectory.insertCertificateBySpecialName(specialName, data, merge); + } + + @Override + public Certificate tryInsertCertificateBySpecialName(String specialName, InputStream data, MergeCallback merge) + throws IOException, BadDataException, BadNameException { + return certificateDirectory.tryInsertCertificateBySpecialName(specialName, data, merge); + } + + @Override + public Iterator getCertificates() { + return certificateDirectory.getCertificates(); + } + + @Override + public Iterator getFingerprints() { + return certificateDirectory.getFingerprints(); + } +} diff --git a/wot-dijkstra/QUESTIONS.md b/wot-dijkstra/QUESTIONS.md new file mode 100644 index 00000000..e2867890 --- /dev/null +++ b/wot-dijkstra/QUESTIONS.md @@ -0,0 +1,19 @@ +# Questions + +## Graph of Certificates or Graph of Subkeys? + +## Persistable Graph or Dynamic Recalculation? + +https://de.wikipedia.org/wiki/Dijkstra-Algorithmus +Dijkstra: Outgoing edges "live" in origin, WoT: Incoming edges "live" in target + +When processing incoming edges on certificate (node): origin of incoming nodes (signing key) might not be known -> cannot verify. + +multi-step process: +Firstly create intermediate graph with unverified edges, invert edge such that origin owns edges to targets +Secondly for edges where origin and target exist, verify signatures + +What information from signatures to cache? Creation date, expiration? Regex, depth, amount! + +What are then nodes? Certs? Bindings? + diff --git a/wot-dijkstra/build.gradle b/wot-dijkstra/build.gradle new file mode 100644 index 00000000..0ab21296 --- /dev/null +++ b/wot-dijkstra/build.gradle @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2021 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +plugins { + id 'java-library' +} + +group 'org.pgpainless' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" + + // Logging + testImplementation "ch.qos.logback:logback-classic:$logbackVersion" + + // @Nullable, @Nonnull annotations + implementation "com.google.code.findbugs:jsr305:3.0.2" + + implementation(project(":pgpainless-core")) +} + +test { + useJUnitPlatform() +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Cost.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Cost.java new file mode 100644 index 00000000..e8ca7de9 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Cost.java @@ -0,0 +1,72 @@ +package org.pgpainless.wot.dijkstra; + +public class Cost { + + public static class SimpleCost extends Cost { + + private final double weight; + + public SimpleCost(double weight) { + this.weight = weight; + } + + public double getWeight() { + return weight; + } + + @Override + public String toString() { + return Double.toString(getWeight()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (!(obj instanceof SimpleCost)) { + return false; + } + SimpleCost other = (SimpleCost) obj; + return getWeight() == other.getWeight(); + } + + @Override + public int hashCode() { + return (int) getWeight(); + } + } + + public static class TrustCost extends Cost { + + private final int depth; + private final int amount; + private final String regex; + + public TrustCost(int depth, int amount, String regex) { + this.depth = depth; + this.amount = amount; + this.regex = regex; + } + + public int getDepth() { + return depth; + } + + public int getAmount() { + return amount; + } + + public String getRegex() { + return regex; + } + + @Override + public String toString() { + return "d=" + getDepth() + ",a=" + getAmount() + (regex == null ? "" : ",r=" + getRegex()); + } + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Dijkstra.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Dijkstra.java new file mode 100644 index 00000000..7f340c2d --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Dijkstra.java @@ -0,0 +1,8 @@ +package org.pgpainless.wot.dijkstra; + +import javax.annotation.Nullable; + +public abstract class Dijkstra, C extends Cost> { + @Nullable + public abstract Path, C, E> findPath(Node to); +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Edge.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Edge.java new file mode 100644 index 00000000..2f6d9256 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Edge.java @@ -0,0 +1,26 @@ +package org.pgpainless.wot.dijkstra; + +public abstract class Edge implements Comparable { + + protected final Node from; + protected final Node to; + protected final C cost; + + public Edge(Node from, Node to, C cost) { + this.from = from; + this.to = to; + this.cost = cost; + } + + public Node getFrom() { + return from; + } + + public Node getTo() { + return to; + } + + public C getCost() { + return cost; + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Graph.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Graph.java new file mode 100644 index 00000000..3069c92f --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Graph.java @@ -0,0 +1,22 @@ +package org.pgpainless.wot.dijkstra; + +import java.util.Collection; + +public class Graph, E extends Edge, C extends Cost> { + + private final Collection nodes; + private final Collection edges; + + public Graph(Collection nodes, Collection edges) { + this.nodes = nodes; + this.edges = edges; + } + + public Collection getNodes() { + return nodes; + } + + public Collection getEdges() { + return edges; + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Node.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Node.java new file mode 100644 index 00000000..5d125301 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Node.java @@ -0,0 +1,40 @@ +package org.pgpainless.wot.dijkstra; + +public class Node { + + private final T item; + + public Node(T item) { + this.item = item; + } + + private T getItem() { + return item; + } + + @Override + public String toString() { + return "(" + getItem().toString() + ")"; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (!(obj instanceof Node)) { + return false; + } + + Node other = (Node) obj; + return getItem().equals(other.getItem()); + } + + @Override + public int hashCode() { + return getItem().hashCode(); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Path.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Path.java new file mode 100644 index 00000000..10469d12 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/Path.java @@ -0,0 +1,59 @@ +package org.pgpainless.wot.dijkstra; + +import java.util.Arrays; +import java.util.List; + +public class Path, C extends Cost, E extends Edge> { + + private final N from; + private final N to; + + private final List edges; + + public Path(N from, N to, List edges) { + this.from = from; + this.to = to; + this.edges = edges; + } + + public Node getFrom() { + return from; + } + + public Node getTo() { + return to; + } + + public List getEdges() { + return edges; + } + + @Override + public String toString() { + return Arrays.toString(getEdges().toArray()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (!(obj instanceof Path)) { + return false; + } + Path other = (Path) obj; + return getFrom().equals(other.getFrom()) + && getTo().equals(other.getTo()) + && getEdges().equals(other.getEdges()); + } + + @Override + public int hashCode() { + return getFrom().hashCode() + + 13 * getTo().hashCode() + + 31 * getEdges().hashCode(); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/ShortestPathDijkstra.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/ShortestPathDijkstra.java new file mode 100644 index 00000000..6d2436d9 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/ShortestPathDijkstra.java @@ -0,0 +1,110 @@ +package org.pgpainless.wot.dijkstra; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ShortestPathDijkstra extends Dijkstra, Cost.SimpleCost> { + + private final Node root; + private final Graph, SimpleEdge, Cost.SimpleCost> graph; + private final List> queue = new ArrayList<>(); + + private final Map, Double> distances = new HashMap<>(); + private final Map, SimpleEdge> precursors = new HashMap<>(); + + public ShortestPathDijkstra(Graph, SimpleEdge, Cost.SimpleCost> graph, Node root) { + // INITIALIZE + this.graph = graph; + this.root = root; + for (Node node : graph.getNodes()) { + // dist[v] := infinity + distances.put(node, Double.MAX_VALUE); + + // precursor[v] := null + precursors.put(node, null); + } + // dist[root] := 0 + distances.put(root, 0d); + + // Q := set of all nodes in graph + queue.addAll(graph.getNodes()); + + while (!queue.isEmpty()) { + Node closest = closest(); + queue.remove(closest); + + for (SimpleEdge edge : graph.getEdges()) { + if (!closest.equals(edge.getFrom())) { + // Skip non-neighbors + continue; + } + + if (queue.contains(edge.getTo())) { + distUpdate(closest, edge.getTo()); + } + } + } + } + + private Node closest() { + Double minDist = Double.MAX_VALUE; + int index = 0; + Double dist; + for (int i = 0; i < queue.size(); i++) { + if ((dist = distances.get(queue.get(i))) <= minDist) { + index = i; + minDist = dist; + } + } + return queue.get(index); + } + + private void distUpdate(Node from, Node to) { + SimpleEdge edge = getEdgeBetween(from, to); + if (edge == null) { + // No direct path + return; + } + + Double distance = distances.get(from) + edge.getCost().getWeight(); + if (distance < distances.get(to)) { + distances.put(to, distance); + precursors.put(to, edge); + } + } + + private SimpleEdge getEdgeBetween(Node from, Node to) { + for (SimpleEdge edge : graph.getEdges()) { + if (!from.equals(edge.getFrom())) { + continue; + } + + if (to.equals(edge.getTo())) { + return edge; + } + } + return null; + } + + @Override + @Nullable + public Path, Cost.SimpleCost, SimpleEdge> findPath(Node to) { + List> pathEdges = new ArrayList<>(); + Node waypoint = to; + + SimpleEdge edge; + while ((edge = precursors.get(waypoint)) != null) { + waypoint = precursors.get(waypoint).getFrom(); + pathEdges.add(0, edge); + } + + if (pathEdges.isEmpty()) { + return null; + } + + return new Path<>(root, to, pathEdges); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/SimpleEdge.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/SimpleEdge.java new file mode 100644 index 00000000..4b8d5900 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/SimpleEdge.java @@ -0,0 +1,41 @@ +package org.pgpainless.wot.dijkstra; + +public class SimpleEdge extends Edge { + + public SimpleEdge(Node from, Node to, Double edgeWeight) { + super(from, to, new Cost.SimpleCost(edgeWeight)); + } + + @Override + public String toString() { + return getFrom().toString() + " " + getCost() + "> " + getTo().toString(); + } + + @Override + public int compareTo(Cost.SimpleCost o) { + return Double.compare(getCost().getWeight(), o.getWeight()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (!(obj instanceof SimpleEdge)) { + return false; + } + SimpleEdge other = (SimpleEdge) obj; + + return getFrom().equals(other.getFrom()) + && getTo().equals(other.getTo()) + && getCost().equals(other.getCost()); + } + + @Override + public int hashCode() { + return getFrom().hashCode() + 13 * getTo().hashCode() + 17 * getCost().hashCode(); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/TrustEdge.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/TrustEdge.java new file mode 100644 index 00000000..753fceec --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/TrustEdge.java @@ -0,0 +1,19 @@ +package org.pgpainless.wot.dijkstra; + +import javax.annotation.Nonnull; + +public class TrustEdge extends Edge { + + public TrustEdge(Node from, Node to, Cost.TrustCost cost) { + super(from, to, cost); + } + + @Override + public int compareTo(@Nonnull Cost.TrustCost o) { + int depthCompare = Double.compare(cost.getDepth(), o.getDepth()); + if (depthCompare != 0) { + return - depthCompare; + } + return Double.compare(cost.getAmount(), o.getAmount()); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/WotDijkstra.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/WotDijkstra.java new file mode 100644 index 00000000..5a63d3b8 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/WotDijkstra.java @@ -0,0 +1,13 @@ +package org.pgpainless.wot.dijkstra; + +import javax.annotation.Nullable; + +public class WotDijkstra extends Dijkstra, Cost.TrustCost> { + + @Override + @Nullable + public Path, Cost.TrustCost, TrustEdge> findPath(Node to) { + return null; + } +} + diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/CertSynopsis.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/CertSynopsis.java new file mode 100644 index 00000000..f7f8d9c7 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/CertSynopsis.java @@ -0,0 +1,70 @@ +package org.pgpainless.wot.dijkstra.sq; + +import org.pgpainless.algorithm.RevocationState; +import org.pgpainless.key.OpenPgpFingerprint; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +public class CertSynopsis { + + private final OpenPgpFingerprint fingerprint; + private final Date expirationTime; + private final RevocationState revocationState; + private final Set userIds; + + /** + * Create a new {@link CertSynopsis}. + * + * @param fingerprint fingerprint of the certificate + * @param expirationTime expiration time + * @param revocationState revocation state of the certificate + * @param userIds set of user-ids + */ + public CertSynopsis(OpenPgpFingerprint fingerprint, + Date expirationTime, + RevocationState revocationState, + Set userIds) { + this.fingerprint = fingerprint; + this.expirationTime = expirationTime; + this.revocationState = revocationState; + this.userIds = userIds; + } + + /** + * Return the fingerprint of the certificate. + * + * @return fingerprint + */ + public OpenPgpFingerprint getFingerprint() { + return fingerprint; + } + + /** + * Get the certificates expiration time. + * + * @return expiration time + */ + public Date getExpirationTime() { + return expirationTime; + } + + /** + * Get the revocation status of the certificate. + * + * @return revocation state + */ + public RevocationState getRevocationState() { + return revocationState; + } + + /** + * Get a {@link Set} containing all user-ids of the certificate. + * + * @return user-ids + */ + public Set userIds() { + return new HashSet<>(userIds); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Certification.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Certification.java new file mode 100644 index 00000000..91615c04 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Certification.java @@ -0,0 +1,165 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.util.Date; +import java.util.List; + +import org.bouncycastle.bcpg.sig.Exportable; +import org.bouncycastle.bcpg.sig.RegularExpression; +import org.bouncycastle.bcpg.sig.TrustSignature; +import org.bouncycastle.openpgp.PGPSignature; +import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; + +public class Certification { + + private final CertSynopsis issuer; + private final CertSynopsis target; + private final Optional userId; + + private final Date creationTime; + private final Optional expirationTime; + private final boolean exportable; + private final int trustAmount; + private final Depth trustDepth; + private final RegexSet regex; + + public Certification( + CertSynopsis issuer, + CertSynopsis target, + Optional userId, + Date creationTime, + Optional expirationTime, + boolean exportable, + int trustAmount, + Depth trustDepth, + RegexSet regex) { + this.issuer = issuer; + this.target = target; + this.userId = userId; + this.creationTime = creationTime; + this.expirationTime = expirationTime; + this.exportable = exportable; + this.trustAmount= trustAmount; + this.trustDepth = trustDepth; + this.regex = regex; + } + + public Certification(CertSynopsis issuer, + Optional targetUserId, + CertSynopsis target, + Date creationTime) { + this.issuer = issuer; + this.target = target; + this.userId = targetUserId; + this.creationTime = creationTime; + + this.expirationTime = Optional.empty(); + this.exportable = true; + this.trustDepth = Depth.limited(0); + this.trustAmount = 120; + this.regex = RegexSet.wildcard(); + } + + public Certification(CertSynopsis issuer, + Optional targetUserId, + CertSynopsis target, + PGPSignature signature) { + this.issuer = issuer; + this.target = target; + this.userId = targetUserId; + this.creationTime = SignatureSubpacketsUtil.getSignatureCreationTime(signature).getTime(); + this.expirationTime = Optional.maybe(SignatureSubpacketsUtil.getSignatureExpirationTimeAsDate(signature)); + Exportable exportablePacket = SignatureSubpacketsUtil.getExportableCertification(signature); + this.exportable = exportablePacket == null || exportablePacket.isExportable(); + TrustSignature trustSignaturePacket = SignatureSubpacketsUtil.getTrustSignature(signature); + if (trustSignaturePacket == null) { + this.trustDepth = Depth.limited(0); + this.trustAmount = 120; + } else { + this.trustDepth = Depth.auto(trustSignaturePacket.getDepth()); + this.trustAmount = trustSignaturePacket.getTrustAmount(); + } + List regularExpressionList = SignatureSubpacketsUtil.getRegularExpressions(signature); + this.regex = RegexSet.fromList(regularExpressionList); + } + + /** + * Get the issuer of the certification. + * + * @return issuer + */ + public CertSynopsis getIssuer() { + return issuer; + } + + /** + * Get the target of the certification. + * + * @return target + */ + public CertSynopsis getTarget() { + return target; + } + + /** + * Get the target user-id. + * + * @return user-id + */ + public Optional getUserId() { + return userId; + } + + /** + * Get the creation time of the certification, + * + * @return creation time + */ + public Date getCreationTime() { + return creationTime; + } + + /** + * Get the (optional) expiration time of the certification. + * + * @return optional expiration time + */ + public Optional getExpirationTime() { + return expirationTime; + } + + /** + * Return true if the certification is marked as exportable. + * + * @return exportable + */ + public boolean isExportable() { + return exportable; + } + + /** + * Get the trust amount of the certification. + * + * @return trust amount + */ + public int getTrustAmount() { + return trustAmount; + } + + /** + * Get the trust depth of the certification. + * + * @return trust depth + */ + public Depth getTrustDepth() { + return trustDepth; + } + + /** + * Return the set of regular expressions. + * + * @return regex set + */ + public RegexSet getRegexes() { + return regex; + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/CertificationSet.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/CertificationSet.java new file mode 100644 index 00000000..a74c28e2 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/CertificationSet.java @@ -0,0 +1,109 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bouncycastle.openpgp.PGPSignature; + +import javax.annotation.Nonnull; + +public class CertificationSet { + + private final CertSynopsis issuer; + private final CertSynopsis target; + + private final Map, List> certifications; + + /** + * Create an empty {@link CertificationSet}. + * + * @param issuer issuer + * @param target target + * @return empty set + */ + public static CertificationSet empty(CertSynopsis issuer, CertSynopsis target) { + return new CertificationSet(issuer, target, new HashMap<>()); + } + + /** + * Create a {@link CertificationSet} from a single certification. + * + * @param issuer issuer + * @param target target + * @param userId user-id + * @param certification certification + * @return singleton set + */ + public static CertificationSet fromCertification( + CertSynopsis issuer, + CertSynopsis target, + Optional userId, + PGPSignature certification) { + + Map, List> certificationMap = new HashMap<>(); + List certificationList = new ArrayList<>(); + certificationList.add(new Certification(issuer, userId, target, certification)); + certificationMap.put(userId, certificationList); + + return new CertificationSet(issuer, target, certificationMap); + } + + private CertificationSet(CertSynopsis issuer, + CertSynopsis target, + Map, List> certifications) { + this.issuer = issuer; + this.target = target; + this.certifications = new HashMap<>(certifications); + } + + /** + * Merge this {@link CertificationSet} with another instance. + * After the operation, this will contain {@link Certification Certifications} from both sets. + * + * @param other other {@link CertificationSet} + */ + public void merge(@Nonnull CertificationSet other) { + if (other == this) { + return; + } + + if (!issuer.getFingerprint().equals(other.issuer.getFingerprint())) { + throw new IllegalArgumentException("Issuer fingerprint mismatch."); + } + + if (!target.getFingerprint().equals(other.target.getFingerprint())) { + throw new IllegalArgumentException("Target fingerprint mismatch."); + } + + for (Map.Entry, List> entry : other.certifications.entrySet()) { + for (Certification certification : entry.getValue()) { + add(certification); + } + } + } + + /** + * Add a {@link Certification} into this {@link CertificationSet}. + * + * @param certification certification + */ + public void add(@Nonnull Certification certification) { + if (!issuer.getFingerprint().equals(certification.getIssuer().getFingerprint())) { + throw new IllegalArgumentException("Issuer fingerprint mismatch."); + } + if (!target.getFingerprint().equals(certification.getTarget().getFingerprint())) { + throw new IllegalArgumentException("Target fingerprint mismatch."); + } + + List certificationsForUserId = certifications.get(certification.getUserId()); + //noinspection Java8MapApi + if (certificationsForUserId == null) { + certificationsForUserId = new ArrayList<>(); + certifications.put(certification.getUserId(), certificationsForUserId); + } + // TODO: Prevent duplicates, only keep newest timestamped sig? + certificationsForUserId.add(certification); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Depth.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Depth.java new file mode 100644 index 00000000..78cf0238 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Depth.java @@ -0,0 +1,76 @@ +package org.pgpainless.wot.dijkstra.sq; + +import javax.annotation.Nonnull; + +public class Depth implements Comparable { + + private final Optional depth; + + private Depth(Optional depth) { + this.depth = depth; + if (!isUnconstrained() && (getLimit().get() < 0 || getLimit().get() > 255)) { + throw new IllegalArgumentException("Depth must be a value between 0 and 255"); + } + } + + public static Depth unconstrained() { + return new Depth(Optional.empty()); + } + + public static Depth limited(int depth) { + return new Depth(Optional.just(depth)); + } + + public static Depth auto(int depth) { + return depth == 255 ? unconstrained() : limited(depth); + } + + public Optional getLimit() { + return depth; + } + + public boolean isUnconstrained() { + return getLimit().isEmpty(); + } + + public Depth decrease(int value) { + if (isUnconstrained()) { + return unconstrained(); + } + if (getLimit().get() >= value) { + return limited(getLimit().get() - value); + } + throw new IllegalArgumentException("Depth cannot be decreased."); + } + + @Override + public int compareTo(@Nonnull Depth o) { + if (isUnconstrained()) { + if (o.isUnconstrained()) { + return 0; + } else { + return 1; + } + } else { + if (o.isUnconstrained()) { + return -1; + } else { + return Integer.compare(getLimit().get(), o.getLimit().get()); + } + } + } + + @Override + public String toString() { + return isUnconstrained() ? "unconstrained" : getLimit().get().toString(); + } + + public Depth min(Depth other) { + if (compareTo(other) <= 0) { + return this; + } else { + return other; + } + } + +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Network.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Network.java new file mode 100644 index 00000000..e237f9ce --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Network.java @@ -0,0 +1,154 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; + +import org.bouncycastle.bcpg.sig.RevocationReason; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSignature; +import org.pgpainless.algorithm.KeyFlag; +import org.pgpainless.algorithm.RevocationState; +import org.pgpainless.algorithm.RevocationStateType; +import org.pgpainless.key.OpenPgpFingerprint; +import org.pgpainless.key.info.KeyRingInfo; +import org.pgpainless.key.util.RevocationAttributes; +import org.pgpainless.policy.Policy; +import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil; + +public class Network { + + private final Map nodes; + private final Map> edges; + private final Map> reverseEdges; + private final ReferenceTime referenceTime; + + public Network(Map nodes, + Map> edges, + Map> reverseEdges, + ReferenceTime referenceTime) { + this.nodes = nodes; + this.edges = edges; + this.reverseEdges = reverseEdges; + this.referenceTime = referenceTime; + } + + /** + * Create an empty {@link Network}. + * + * @param referenceTime reference time for evaluation + * @return network + */ + public static Network empty(@Nonnull ReferenceTime referenceTime) { + return new Network( + new HashMap<>(), + new HashMap<>(), + new HashMap<>(), + referenceTime); + } + + /** + * Create a {@link Network} from a set of certificates. + * + * @param certificates set of certificates + * @param policy evaluation policy + * @param optReferenceTime reference time for evaluation + * @return network + */ + public static Network fromCertificates( + Iterable certificates, + Policy policy, + Optional optReferenceTime) { + ReferenceTime referenceTime = optReferenceTime.isPresent() ? optReferenceTime.get() : ReferenceTime.now(); + List validCerts = new ArrayList<>(); + for (PGPPublicKeyRing cert : certificates) { + KeyRingInfo info = new KeyRingInfo(cert, policy, referenceTime.getTimestamp()); + if (info.getValidUserIds().isEmpty()) { + // Ignore invalid cert + } else { + validCerts.add(info); + } + } + + return fromValidCertificates( + validCerts, + referenceTime + ); + } + + /** + * Create a {@link Network} from a set of validated certificates. + * + * @param validatedCertificates set of validated certificates + * @param referenceTime reference time + * @return network + */ + public static Network fromValidCertificates( + Iterable validatedCertificates, + ReferenceTime referenceTime) { + + Map byFingerprint = new HashMap<>(); + Map> byKeyId = new HashMap<>(); + + Map certSynopsisMap = new HashMap<>(); + + for (KeyRingInfo cert : validatedCertificates) { + //noinspection Java8MapApi + if (byFingerprint.get(cert.getFingerprint()) == null) { + byFingerprint.put(cert.getFingerprint(), cert); + } + List byKeyIdEntry = byKeyId.get(cert.getKeyId()); + + //noinspection Java8MapApi + if (byKeyIdEntry == null) { + byKeyIdEntry = new ArrayList<>(); + byKeyId.put(cert.getKeyId(), byKeyIdEntry); + } + byKeyIdEntry.add(cert); + + certSynopsisMap.put(cert.getFingerprint(), + new CertSynopsis(cert.getFingerprint(), + cert.getExpirationDateForUse(KeyFlag.CERTIFY_OTHER), + revocationStateFromSignature(cert.getRevocationSelfSignature()), + new HashSet<>(cert.getValidUserIds()))); + } + + Map> edges = new HashMap<>(); + Map> reverseEdges = new HashMap<>(); + + return new Network(certSynopsisMap, edges, reverseEdges, referenceTime); + } + + public Map getNodes() { + return new HashMap<>(nodes); + } + + public Map> getEdges() { + return new HashMap<>(edges); + } + + public Map> getReverseEdges() { + return new HashMap<>(reverseEdges); + } + + public ReferenceTime getReferenceTime() { + return referenceTime; + } + + private static RevocationState revocationStateFromSignature(PGPSignature revocation) { + if (revocation == null) { + return RevocationState.notRevoked(); + } + + RevocationReason revocationReason = SignatureSubpacketsUtil.getRevocationReason(revocation); + if (revocationReason == null) { + return RevocationState.hardRevoked(); + } + + return RevocationAttributes.Reason.isHardRevocation(revocationReason.getRevocationReason()) ? + RevocationState.hardRevoked() : RevocationState.softRevoked(revocation.getCreationTime()); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Optional.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Optional.java new file mode 100644 index 00000000..c0457fd1 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Optional.java @@ -0,0 +1,74 @@ +package org.pgpainless.wot.dijkstra.sq; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class Optional { + + private final T item; + + public static Optional empty() { + return new Optional<>(); + } + + public static Optional just(@Nonnull T item) { + return new Optional<>(item); + } + + public static Optional maybe(@Nullable T item) { + return item == null ? empty() : just(item); + } + + private Optional() { + this.item = null; + } + + private Optional(@Nonnull T item) { + this.item = item; + } + + public boolean isEmpty() { + return item == null; + } + + public boolean isPresent() { + return item != null; + } + + public @Nonnull T get() { + if (item == null) { + throw new NullPointerException("Item is null."); + } + return item; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + + if (!(obj instanceof Optional)) { + return false; + } + + Optional other = (Optional) obj; + if (isEmpty() && other.isEmpty()) { + return true; + } + + if (isPresent() && isPresent()) { + return get().equals(other.get()); + } + + return false; + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Path.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Path.java new file mode 100644 index 00000000..69f3526a --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Path.java @@ -0,0 +1,90 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.util.ArrayList; +import java.util.List; + +public class Path { + + private CertSynopsis root; + private List edges; + private Depth residualDepth; + + public Path(CertSynopsis root) { + this.root = root; + this.edges = new ArrayList<>(); + this.residualDepth = Depth.unconstrained(); + } + + public CertSynopsis getRoot() { + return root; + } + + public CertSynopsis getTarget() { + if (edges.isEmpty()) { + return getRoot(); + } else { + return edges.get(edges.size() - 1).getTarget(); + } + } + + public List getCertificates() { + List certs = new ArrayList<>(); + certs.add(getRoot()); + for (Certification edge : edges) { + certs.add(edge.getTarget()); + } + return certs; + } + + public int getLength() { + return edges.size() + 1; + } + + public List getCertifications() { + return new ArrayList<>(edges); + } + + public Depth getResidualDepth() { + return residualDepth; + } + + public int getAmount() { + if (edges.isEmpty()) { + return 120; + } + int min = 255; + for (Certification edge : edges) { + min = Math.min(min, edge.getTrustAmount()); + } + return min; + } + + public void append(Certification certification) { + if (!getTarget().getFingerprint().equals(certification.getIssuer().getFingerprint())) { + throw new IllegalArgumentException("Cannot append certification to path: Path's tail is not issuer of the certification."); + } + + if (!residualDepth.isUnconstrained() && residualDepth.getLimit().get() == 0) { + throw new IllegalArgumentException("Not enough depth."); + } + + boolean cyclic = getRoot().getFingerprint().equals(certification.getTarget().getFingerprint()); + for (int i = 0; i < edges.size() && !cyclic; i++) { + Certification edge = edges.get(i); + + if (edge.getTarget().getFingerprint().equals(certification.getTarget().getFingerprint())) { + if (i == edges.size() - 1) { + cyclic = edge.getUserId().equals(certification.getUserId()); + } else { + cyclic = true; + } + } + } + if (cyclic) { + throw new IllegalArgumentException("Adding the certification to the path would create a cycle."); + } + + residualDepth = certification.getTrustDepth().min(residualDepth.decrease(1)); + edges.add(certification); + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Paths.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Paths.java new file mode 100644 index 00000000..928564a5 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/Paths.java @@ -0,0 +1,46 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.util.ArrayList; +import java.util.List; + +public class Paths { + + private final List paths = new ArrayList<>(); + + public List getPaths() { + return new ArrayList<>(paths); + } + + public void add(Path path, int amount) { + if (amount <= path.getAmount()) { + throw new AssertionError(); + } + this.paths.add(new Item(path, amount)); + } + + public int getAmount() { + int sum = 0; + for (Item item : paths) { + sum += item.amount; + } + return sum; + } + + public static class Item { + private final Path path; + private final int amount; + + public Item(Path path, int amount) { + this.path = path; + this.amount = amount; + } + + public Path getPath() { + return path; + } + + public int getAmount() { + return amount; + } + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/ReferenceTime.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/ReferenceTime.java new file mode 100644 index 00000000..1e525891 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/ReferenceTime.java @@ -0,0 +1,30 @@ +package org.pgpainless.wot.dijkstra.sq; + +import javax.annotation.Nonnull; +import java.util.Date; + +public interface ReferenceTime { + + @Nonnull Date getTimestamp(); + + static ReferenceTime now() { + final Date now = new Date(); + return new ReferenceTime() { + @Override + @Nonnull + public Date getTimestamp() { + return now; + } + }; + } + + static ReferenceTime timestamp(@Nonnull Date timestamp) { + return new ReferenceTime() { + @Override + @Nonnull + public Date getTimestamp() { + return timestamp; + } + }; + } +} diff --git a/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/RegexSet.java b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/RegexSet.java new file mode 100644 index 00000000..3af6a578 --- /dev/null +++ b/wot-dijkstra/src/main/java/org/pgpainless/wot/dijkstra/sq/RegexSet.java @@ -0,0 +1,51 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nonnull; + +import org.bouncycastle.bcpg.sig.RegularExpression; + +public class RegexSet { + + private final Set regexStrings; + + private RegexSet(Set regexStrings) { + this.regexStrings = regexStrings; + } + + public static RegexSet fromList(@Nonnull List regexList) { + Set regexStringSet = new HashSet<>(); + for (RegularExpression regex : regexList) { + regexStringSet.add(regex.getRegex()); + } + return new RegexSet(regexStringSet); + } + + public static RegexSet fromRegex(@Nonnull RegularExpression regex) { + return fromList(Collections.singletonList(regex)); + } + + public static RegexSet wildcard() { + return fromList(Collections.emptyList()); + } + + public boolean matches(String string) { + if (regexStrings.isEmpty()) { + return true; + } + + for (String regex : regexStrings) { + Matcher matcher = Pattern.compile(regex).matcher(string); + if (matcher.matches()) { + return true; + } + } + + return false; + } +} diff --git a/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/BasicShortestPathDijkstraTest.java b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/BasicShortestPathDijkstraTest.java new file mode 100644 index 00000000..00a7fc8c --- /dev/null +++ b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/BasicShortestPathDijkstraTest.java @@ -0,0 +1,152 @@ +package org.pgpainless.wot.dijkstra; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +public class BasicShortestPathDijkstraTest { + + /** + * Generate a test graph from a string definition. + * The definition might look like this: + *
+     *     Alice
+     *     Bob -1> Charlie
+     *     Charlie -4> Dieter -1> Alice
+     *     Dieter -2> Charlie
+     * 
+ * @param definition definition + * @return graph + */ + private Graph, SimpleEdge, Cost.SimpleCost> generate(String definition) { + Set> nodes = new HashSet<>(); + Set> edges = new HashSet<>(); + String[] lines = definition.split("\n"); + for (String line : lines) { + line = line.trim(); + if (line.isEmpty()) { + continue; + } + + String[] fromTo = line.split(" -\\d+> "); + if (fromTo.length == 1) { + // Unconnected node + nodes.add(new Node<>(fromTo[0])); + continue; + } + + int searchOffset = 0; + for (int i = 0; i < fromTo.length - 1; i++) { + Node from = new Node<>(fromTo[i]); + nodes.add(from); + searchOffset += fromTo[i].length() + " -".length(); + int costStop = line.indexOf("> ", searchOffset); + String costString = line.substring(searchOffset, costStop); + Double cost = Double.parseDouble(costString); + searchOffset += costString.length() + "> ".length(); + Node to = new Node<>(fromTo[i + 1]); + nodes.add(to); + + edges.add(new SimpleEdge<>(from, to, cost)); + } + } + + return new Graph<>(nodes, edges); + } + + private Path, Cost.SimpleCost, SimpleEdge> path(String definition) { + definition = definition.trim(); + String[] fromTo = definition.split(" -\\d+> "); + if (fromTo.length == 1) { + // Unconnected node + Node node = new Node<>(fromTo[0]); + return new Path<>(node, node, Collections.singletonList(new SimpleEdge<>(node, node, 0d))); + } + + Node start = null; + Node end = null; + List> edges = new ArrayList<>(); + int searchOffset = 0; + for (int i = 0; i < fromTo.length - 1; i++) { + Node from = new Node<>(fromTo[i]); + if (start == null) { + start = from; + } + searchOffset += fromTo[i].length() + " -".length(); + int costStop = definition.indexOf("> ", searchOffset); + String costString = definition.substring(searchOffset, costStop); + Double cost = Double.parseDouble(costString); + searchOffset += costString.length() + "> ".length(); + Node to = new Node<>(fromTo[i + 1]); + edges.add(new SimpleEdge<>(from, to, cost)); + end = to; + } + + Path, Cost.SimpleCost, SimpleEdge> path = new Path<>(start, end, edges); + return path; + } + + @Test + public void exampleGraphTest() { + Graph, SimpleEdge, Cost.SimpleCost> g = generate( + "Alice\n" + + "Bob -1> Charlie\n" + + "Bob -3> Dieter -1> Marlene\n" + + "Dieter -1> Alice\n" + + "Mallory\n"); + + Set> expectedNodes = new HashSet<>(); + expectedNodes.add(new Node<>("Alice")); + expectedNodes.add(new Node<>("Bob")); + expectedNodes.add(new Node<>("Charlie")); + expectedNodes.add(new Node<>("Dieter")); + expectedNodes.add(new Node<>("Marlene")); + expectedNodes.add(new Node<>("Mallory")); + + assertEquals(expectedNodes, g.getNodes()); + + Set> expectedEdges = new HashSet<>(); + expectedEdges.add(new SimpleEdge<>(new Node<>("Bob"), new Node<>("Charlie"), 1d)); + expectedEdges.add(new SimpleEdge<>(new Node<>("Bob"), new Node<>("Dieter"), 3d)); + expectedEdges.add(new SimpleEdge<>(new Node<>("Dieter"), new Node<>("Marlene"), 1d)); + expectedEdges.add(new SimpleEdge<>(new Node<>("Dieter"), new Node<>("Alice"), 1d)); + + assertEquals(g.getEdges(), expectedEdges); + } + + @Test + public void emptyNetworkTest() { + Graph, SimpleEdge, Cost.SimpleCost> graph = generate(""); + + Node root = new Node<>("root"); + Node target = new Node<>("target"); + ShortestPathDijkstra dijkstra = new ShortestPathDijkstra<>(graph, root); + Path, Cost.SimpleCost, SimpleEdge> path = dijkstra.findPath(target); + + assertNull(path); + } + + @Test + public void pathFindingTest() { + Graph, SimpleEdge, Cost.SimpleCost> graph = generate( + "Pablo\n" + + "Root -2> Alice -3> Alexandra\n" + + "Root -1> Karlos -1> Alexandra\n" + + "Karlos -2> Malte -4> Sven"); + + ShortestPathDijkstra dijkstra = new ShortestPathDijkstra<>(graph, new Node<>("Root")); + assertEquals(path("Root -1> Karlos -2> Malte -4> Sven"), dijkstra.findPath(new Node<>("Sven"))); + assertEquals(path("Root -1> Karlos"), dijkstra.findPath(new Node<>("Karlos"))); + assertEquals(path("Root -1> Karlos -1> Alexandra"), dijkstra.findPath(new Node<>("Alexandra"))); + + dijkstra = new ShortestPathDijkstra<>(graph, new Node<>("Karlos")); + assertEquals(path("Karlos -2> Malte -4> Sven"), dijkstra.findPath(new Node<>("Sven"))); + } +} diff --git a/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/NodeTest.java b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/NodeTest.java new file mode 100644 index 00000000..8cd5e886 --- /dev/null +++ b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/NodeTest.java @@ -0,0 +1,31 @@ +package org.pgpainless.wot.dijkstra; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class NodeTest { + + @Test + public void equalsTest() { + Node n1 = new Node<>("foo"); + Node n1_ = new Node<>("foo"); + Node n2 = new Node<>("bar"); + + assertEquals(n1, n1_); + assertEquals(n1, n1); + assertNotEquals(n1, n2); + + Map, String> map = new HashMap<>(); + map.put(n1, "foo"); + map.put(n2, "bar"); + + assertEquals("foo", map.get(n1)); + assertEquals("bar", map.get(n2)); + assertEquals("foo", map.get(n1_)); + } +} diff --git a/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/DepthTest.java b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/DepthTest.java new file mode 100644 index 00000000..fe89a858 --- /dev/null +++ b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/DepthTest.java @@ -0,0 +1,95 @@ +package org.pgpainless.wot.dijkstra.sq; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class DepthTest { + + @Test + public void testUnlimitedItem() { + Depth depth = Depth.unconstrained(); + assertTrue(depth.isUnconstrained()); + assertFalse(depth.getLimit().isPresent()); + } + + @Test + public void testLimitedItem() { + Depth limited = Depth.limited(2); + assertFalse(limited.isUnconstrained()); + assertTrue(limited.getLimit().isPresent()); + assertEquals(2, limited.getLimit().get()); + } + + @Test + public void testDecreaseUnconstrainedYieldsUnconstrained() { + Depth unconstrained = Depth.unconstrained(); + Depth decreased = unconstrained.decrease(20); + assertTrue(decreased.isUnconstrained()); + } + + @Test + public void testDecreaseLimitedYieldsDecreasedLimited() { + Depth limited = Depth.limited(1); + Depth decreased = limited.decrease(1); + assertFalse(decreased.isUnconstrained()); + assertEquals(0, decreased.getLimit().get()); + } + + @Test + public void testDecreaseLimitedTooMuchYieldsException() { + Depth limited = Depth.limited(0); + assertThrows(IllegalArgumentException.class, () -> limited.decrease(1)); + } + + @Test + public void testCompareTo() { + Depth unlimited = Depth.unconstrained(); + Depth unlimited2 = Depth.unconstrained(); + Depth depth2 = Depth.limited(2); + Depth depth2_ = Depth.limited(2); + Depth depth5 = Depth.limited(5); + + assertEquals(0, unlimited.compareTo(unlimited2)); + assertTrue(unlimited.compareTo(depth2) > 0); + assertTrue(unlimited.compareTo(depth5) > 0); + assertTrue(depth2.compareTo(unlimited) < 0); + assertTrue(depth2.compareTo(depth5) < 0); + assertTrue(depth5.compareTo(depth2) > 0); + assertEquals(0, depth2.compareTo(depth2_)); + } + + @Test + public void testAutoUnconstrained() { + Depth depth = Depth.auto(255); + assertTrue(depth.isUnconstrained()); + } + + @Test + public void testAutoLimited() { + Depth depth = Depth.auto(120); + assertFalse(depth.isUnconstrained()); + assertEquals(120, depth.getLimit().get()); + } + + @Test + public void testOutOfBounds() { + assertThrows(IllegalArgumentException.class, () -> Depth.limited(-1)); + assertThrows(IllegalArgumentException.class, () -> Depth.limited(256)); + assertThrows(IllegalArgumentException.class, () -> Depth.auto(-1)); + assertThrows(IllegalArgumentException.class, () -> Depth.auto(256)); + } + + @Test + public void testToStringUnconstrained() { + assertEquals("unconstrained", Depth.unconstrained().toString()); + } + + @Test + public void testToStringLimited() { + assertEquals("1", Depth.limited(1).toString()); + } +} diff --git a/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/NetworkTest.java b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/NetworkTest.java new file mode 100644 index 00000000..f95d116a --- /dev/null +++ b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/NetworkTest.java @@ -0,0 +1,35 @@ +package org.pgpainless.wot.dijkstra.sq; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.junit.jupiter.api.Test; +import org.pgpainless.PGPainless; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; + +public class NetworkTest { + + @Test + public void testEmptyNetworkIsEmpty() { + ReferenceTime referenceTime = ReferenceTime.now(); + Network network = Network.empty(referenceTime); + + assertTrue(network.getNodes().isEmpty()); + assertTrue(network.getEdges().isEmpty()); + assertTrue(network.getReverseEdges().isEmpty()); + assertEquals(referenceTime, network.getReferenceTime()); + } + + @Test + public void testNetworkFromCertificates() { + ReferenceTime referenceTime = ReferenceTime.now(); + } + + +} diff --git a/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/WotTestVectors.java b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/WotTestVectors.java new file mode 100644 index 00000000..a7ab9813 --- /dev/null +++ b/wot-dijkstra/src/test/java/org/pgpainless/wot/dijkstra/sq/WotTestVectors.java @@ -0,0 +1,275 @@ +package org.pgpainless.wot.dijkstra.sq; + +import java.io.IOException; +import java.io.InputStream; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.pgpainless.PGPainless; +import org.pgpainless.algorithm.Trustworthiness; +import org.pgpainless.key.protection.SecretKeyRingProtector; +import org.pgpainless.signature.subpackets.CertificationSubpackets; +import org.pgpainless.util.Passphrase; + +public class WotTestVectors { + + private static WotTestVectors INSTANCE = null; + + public static WotTestVectors getTestVectors() { + if (INSTANCE == null) { + INSTANCE = new WotTestVectors(); + } + return INSTANCE; + } + + public PGPSecretKeyRing getFreshFooBankCaKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCaKey.asc")); + } + + public PGPPublicKeyRing getFreshFooBankCaCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCaCert.asc")); + } + + public String getFooBankCaPassphrase() { + return "superS3cureP4ssphrase"; + } + + public SecretKeyRingProtector getFooBankCaProtector() { + return SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(getFooBankCaPassphrase())); + } + + public PGPSecretKeyRing getFreshFooBankEmployeeKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankEmployeeKey.asc")); + } + + public PGPPublicKeyRing getFreshFooBankEmployeeCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankEmployeeCert.asc")); + } + + public String getFooBankEmployeePassphrase() { + return "iLoveWorking@FooBank"; + } + + public SecretKeyRingProtector getFooBankEmployeeProtector() { + return SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(getFooBankEmployeePassphrase())); + } + + public PGPSecretKeyRing getFreshFooBankAdminKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankAdminKey.asc")); + } + + public PGPPublicKeyRing getFreshFooBankAdminCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankAdminCert.asc")); + } + + public String getFooBankAdminPassphrase() { + return "keepFooBankSecure"; + } + + public SecretKeyRingProtector getFooBankAdminProtector() { + return SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(getFooBankAdminPassphrase())); + } + + public PGPSecretKeyRing getFreshFooBankCustomerKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCustomerKey.asc")); + } + + public PGPPublicKeyRing getFreshFooBankCustomerCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCustomerCert.asc")); + } + + public PGPSecretKeyRing getFreshBarBankCaKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankCaKey.asc")); + } + + public PGPPublicKeyRing getFreshBarBankCaCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankCaCert.asc")); + } + + public PGPSecretKeyRing getFreshBarBankEmployeeKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankEmployeeKey.asc")); + } + + public PGPPublicKeyRing getFreshBarBankEmployeeCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankEmployeeCert.asc")); + } + + public PGPSecretKeyRing getFreshFakeFooBankEmployeeKey() throws IOException { + return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/fakeFoobankEmployeeKey.asc")); + } + + public PGPPublicKeyRing getFreshFakeFooBankEmployeeCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/fakeFoobankEmployeeCert.asc")); + } + + public PGPPublicKeyRing getCrossSignedBarBankCaCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/barbankCaCert.asc")); + } + + public PGPPublicKeyRing getCrossSignedBarBankEmployeeCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/barbankEmployeeCert.asc")); + } + + public PGPPublicKeyRing getCrossSignedFooBankAdminCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/foobankAdminCert.asc")); + } + + public PGPPublicKeyRing getCrossSignedFooBankCaCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/foobankCaCert.asc")); + } + + public PGPPublicKeyRing getCrossSignedFooBankEmployeeCert() throws IOException { + return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/foobankEmployeeCert.asc")); + } + + // Generate cross signed test vectors from freshly generated + public void crossSign() throws IOException, PGPException { + PGPSecretKeyRing freshFooBankCaKey = getFreshFooBankCaKey(); + PGPPublicKeyRing freshFooBankCaCert = getFreshFooBankCaCert(); + + PGPSecretKeyRing freshFooBankEmployeeKey = getFreshFooBankEmployeeKey(); + PGPPublicKeyRing freshFooBankEmployeeCert = getFreshFooBankEmployeeCert(); + + PGPSecretKeyRing freshFooBankAdminKey = getFreshFooBankAdminKey(); + PGPPublicKeyRing freshFooBankAdminCert = getFreshFooBankAdminCert(); + + PGPSecretKeyRing freshFooBankCustomerKey = getFreshFooBankCustomerKey(); + PGPPublicKeyRing freshFooBankCustomerCert = getFreshFooBankCustomerCert(); + + PGPSecretKeyRing freshBarBankCaKey = getFreshBarBankCaKey(); + PGPPublicKeyRing freshBarBankCaCert = getFreshBarBankCaCert(); + + PGPSecretKeyRing freshBarBankEmployeeKey = getFreshBarBankEmployeeKey(); + PGPPublicKeyRing freshBarBankEmployeeCert = getFreshBarBankEmployeeCert(); + + PGPSecretKeyRing freshFakeFooBankEmployeeKey = getFreshFakeFooBankEmployeeKey(); + PGPPublicKeyRing freshFakeFooBankEmployeeCert = getFreshFakeFooBankEmployeeCert(); + + final String fooBankRegex = "<[^>]+[@.]foobank\\.com>$"; + final String barBankRegex = "<[^>]+[@.]barbank\\.com>$"; + + // Foo CA signs Foo Employee + PGPPublicKeyRing caCertifiedFooBankEmployeeCert = PGPainless.certify() + .userIdOnCertificate("Foo Bank Employee ", freshFooBankEmployeeCert) + .withKey(freshFooBankCaKey, getFooBankCaProtector()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.addNotationData(false, "affiliation@foobank.com", "employee"); + } + }) + .getCertifiedCertificate(); + + // Foo CA signs Foo Admin + PGPPublicKeyRing caCertifiedFooBankAdminCert = PGPainless.certify() + .userIdOnCertificate("Foo Bank Admin ", freshFooBankAdminCert) + .withKey(freshFooBankCaKey, getFooBankCaProtector()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.addNotationData(false, "affiliation@foobank.com", "administrator"); + } + }) + .getCertifiedCertificate(); + + // Foo Employee delegates trust to Foo CA + PGPPublicKeyRing employeeDelegatedCaCert = PGPainless.certify() + .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankEmployeeKey, getFooBankEmployeeProtector()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.setRegularExpression(fooBankRegex); + } + }) + .getCertifiedCertificate(); + + // Foo Admin delegates trust to Foo CA + PGPPublicKeyRing adminDelegatedCaCert = PGPainless.certify() + .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankAdminKey, getFooBankAdminProtector()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.setRegularExpression(fooBankRegex); + } + }) + .getCertifiedCertificate(); + + // Customer delegates trust to Foo CA + PGPPublicKeyRing customerDelegatedCaCert = PGPainless.certify() + .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankCustomerKey, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.setRegularExpression(fooBankRegex); + } + }) + .getCertifiedCertificate(); + + PGPPublicKeyRing mergedFooCa = PGPPublicKeyRing.join(employeeDelegatedCaCert, adminDelegatedCaCert); + mergedFooCa = PGPPublicKeyRing.join(mergedFooCa, customerDelegatedCaCert); + + // Foo Admin delegates trust to Bar CA + PGPPublicKeyRing fooAdminDelegatedBarCa = PGPainless.certify() + .certificate(freshBarBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankAdminKey, getFooBankAdminProtector()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.setRegularExpression("<[^>]+[@.]barbank\\.com>$"); + } + }).getCertifiedCertificate(); + + // Bar Employee delegates Bar CA + PGPPublicKeyRing barEmployeeDelegatesBarCa = PGPainless.certify() + .certificate(freshBarBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshBarBankEmployeeKey, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.setRegularExpression(barBankRegex); + } + }) + .getCertifiedCertificate(); + + PGPPublicKeyRing mergedBarCa = PGPPublicKeyRing.join(fooAdminDelegatedBarCa, barEmployeeDelegatesBarCa); + + // Bar CA signs Bar Employee + PGPPublicKeyRing barCaCertifiedEmployeeCert = PGPainless.certify() + .userIdOnCertificate("Bar Bank Employee ", freshBarBankEmployeeCert) + .withKey(freshBarBankCaKey, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(new CertificationSubpackets.Callback() { + @Override + public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { + hashedSubpackets.addNotationData(false, "affiliation@barbank.com", "employee"); + } + }) + .getCertifiedCertificate(); + + System.out.println("Foo Employee"); + System.out.println(PGPainless.asciiArmor(caCertifiedFooBankEmployeeCert)); + + System.out.println("Foo Admin"); + System.out.println(PGPainless.asciiArmor(caCertifiedFooBankAdminCert)); + + System.out.println("Foo CA"); + System.out.println(PGPainless.asciiArmor(mergedFooCa)); + + System.out.println("Bar CA"); + System.out.println(PGPainless.asciiArmor(mergedBarCa)); + + System.out.println("Bar Employee"); + System.out.println(PGPainless.asciiArmor(barCaCertifiedEmployeeCert)); + } + + private static InputStream getTestResourceInputStream(String resource) { + InputStream inputStream = WotTestVectors.class.getClassLoader().getResourceAsStream(resource); + if (inputStream == null) { + throw new IllegalArgumentException(String.format("Unknown resource %s", resource)); + } + return inputStream; + } +} diff --git a/wot-dijkstra/src/test/resources/test_vectors/README.md b/wot-dijkstra/src/test/resources/test_vectors/README.md new file mode 100644 index 00000000..3d8f00b2 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/README.md @@ -0,0 +1,47 @@ + +# Test Vectors + +## Freshly Generated Vectors + +The `freshly_generated/` directory contains freshly generated test vectors. +Those are keys and certificates without any third-party signatures. + +```mermaid +graph LR; +a[Foo Bank CA <ca@foobank.com>]; +b[Foo Bank Employee <employee@foobank.com>]; +c[Foo Bank Admin <admin@foobank.com>]; + +d[Customer <customer@example.com>]; +e[Bar Bank CA <ca@barbank.com>]; +f[Bar Bank Employee <employee@barbank.com>]; +g[Foo Bank Employee (Attacker) <employee@foobank.com>]; +``` + +## Cross Signed Vectors +The `cross_signed/` directory contains test vectors that model the following interconnectivity: + +```mermaid +graph TD; +a[Foo Bank CA <ca@foobank.com>]; +b[Foo Bank Employee <employee@foobank.com>]; +c[Foo Bank Admin <admin@foobank.com>]; + +d[Customer <customer@example.com>]; +e[Bar Bank CA <ca@barbank.com>]; +f[Bar Bank Employee <employee@barbank.com>]; +g[Foo Bank Employee (Attacker) <employee@foobank.com>]; + +a -- generic certification --> b & c; +b & c & d == 1:120:"<[^>]+[@.]foobank\.com>$" ==> a; +e -- generic certification --> f; +c == 1:120:"<[^>]+[@.]barbank\.com>$" ==> e; +``` + +## Useful Resources: +* https://mateam.net/html-escape-characters/ +* https://docs.sequoia-pgp.org/sequoia_openpgp/regex/index.html#caveat-emptor \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/cross_signed/barbankCaCert.asc b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/barbankCaCert.asc new file mode 100644 index 00000000..27082c5d --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/barbankCaCert.asc @@ -0,0 +1,28 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: CEE5 FB5D C524 84A6 9B73 9FAD 7DA0 2993 D86B 0355 +Comment: Bar Bank CA + +mDMEYs1BgxYJKwYBBAHaRw8BAQdA3hOlkHAVyvTwePiifKnwLhkcJnswNidJ7dWo +UKEQlZWIlAQfFgoARgUCYs1MVwkQ9fHjtTaNbKcWIQSmiOyyabOBYdpNc4/18eO1 +No1spxoGPFtePl0rW0AuXWJhcmJhbmtcLmNvbT4kAAOFAXgAAOfiAQCJIhMid48+ +8FS9IO76ELTYMsy0q/kBd4z3Gs+OYqM3ZQEAjyqoEKT8OHNC3zPkneE4bhsB21CH +PMBe+pYcUE3tZAmIlAQfFgoARgUCYs1MVwkQitIzV+t4uwgWIQREeoKqA/fXpLHa +TXyK0jNX63i7CBoGPFtePl0rW0AuXWJhcmJhbmtcLmNvbT4kAAOFAXgAAHb5AP99 +3BHUJhkpc6S0NiTsT1OKifmAuI9bRT++TIqEB6p7uwEA09k6Y59pjZhnISG4+KiK +Y+ZhGKx6bbyGIXirwlssMQK0HEJhciBCYW5rIENBIDxjYUBiYXJiYW5rLmNvbT6I +jwQTFgoAQQUCYs1BgwkQfaApk9hrA1UWIQTO5ftdxSSEpptzn619oCmT2GsDVQKe +AQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAABltgEA4Ob86bhjLa6Xg4wnzYIGH21W +EUlc37BBaqwr4qvfsA4A/0BzOdTy3Wty5DkdMiA2yPOxIVuHbTD8pgqpne2yoegN +uDgEYs1BgxIKKwYBBAGXVQEFAQEHQDVHLNRE4Gtg9/BzwSUMW3psBD7OUm4Df0gg +ilvLZhMcAwEIB4h1BBgWCgAdBQJizUGDAp4BApsMBRYCAwEABAsJCAcFFQoJCAsA +CgkQfaApk9hrA1WrYAEAsZsEoUfAPIG6d9gtK7Zmm3zt+xiTELW08E/pwjmFTmEB +AODICUhsEelkdXrbIkL2oWAKoxlsbkyA6mNXBt5UXQcJuDMEYs1BgxYJKwYBBAHa +Rw8BAQdARHF/sgSTB38osF0+XA9N2htsMIrb322j3LQdrk0M77SI1QQYFgoAfQUC +Ys1BgwKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmLNQYMACgkQtEK9 +w/vjcduqJwD+KW23+689GXtu4k3PW60GPsiue22lMGwZY7hsWvZB1hkBAPER8PMs +0MJAQzcs2u6bYPMDI921umqX8Yvsob1kzs0FAAoJEH2gKZPYawNVdKwBAKz5zfwE +KZ2dGPCsUJzAXfPxe0LmATcvS5g/LvAreD0KAQDfpfMFO2EqQu6wDt+e5MH3YCjG +saYwvjB1elj1zhblAg== +=O9uk +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/cross_signed/barbankEmployeeCert.asc b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/barbankEmployeeCert.asc new file mode 100644 index 00000000..04b3f5ac --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/barbankEmployeeCert.asc @@ -0,0 +1,25 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 447A 82AA 03F7 D7A4 B1DA 4D7C 8AD2 3357 EB78 BB08 +Comment: Bar Bank Employee + +mDMEYs1CXRYJKwYBBAHaRw8BAQdAeMjyfqInb8aZppFsKHdndoeL3j08Z5CtagKz +KPb6YGO0KEJhciBCYW5rIEVtcGxveWVlIDxlbXBsb3llZUBiYXJiYW5rLmNvbT6I +jwQTFgoAQQUCYs1CXQkQitIzV+t4uwgWIQREeoKqA/fXpLHaTXyK0jNX63i7CAKe +AQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAACgcgD7Bk2Hu+Lu3aA+IyzFyTQOw8zQ +RUeA/X8neEIezYDTC+MA/jGFyiKW7b+6W3zgdIgiHMeWhG3Wx2oOC1izW2+tP2cJ +iJ4EEBYKAFAFAmLNTFcJEH2gKZPYawNVFiEEzuX7XcUkhKabc5+tfaApk9hrA1Uo +FIAAAAAAFwAIYWZmaWxpYXRpb25AYmFyYmFuay5jb21lbXBsb3llZQAAG4ABAMF2 +yTTckIjHNIyv7M8mcUx/zW++oJMxnhztT73cQeNxAQDVoyHqRgLpWR4lKw2b5IwE +gw9KT9zIA9jveWufwgIvD7g4BGLNQl0SCisGAQQBl1UBBQEBB0Bq216nP4pw9r1F +8OMcUWisYUvOePUeULPLYV+jX8UdBgMBCAeIdQQYFgoAHQUCYs1CXQKeAQKbDAUW +AgMBAAQLCQgHBRUKCQgLAAoJEIrSM1freLsIo5QA/A9zDz8XrjtbJIK60J3kmwvY +jynF9IkzyFTj4sNeHhJTAP92dTWvbogEwzPhBbofwzOT7PXg7laQ8v9eTqr50lWf +B7gzBGLNQl0WCSsGAQQB2kcPAQEHQEV9SpoogW2HrVIaU953W31ceDvDmBWMFBQQ +a3Qsz6IBiNUEGBYKAH0FAmLNQl0CngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkW +CgAGBQJizUJdAAoJENG3C+ldSVbaPsAA/2giZHcGT0nyAojPds1IfIE97dyAlVgj +fbTH3H4QNVsAAP9dpakDZya/q8M/wnZOyOBf+dHiUrvDbxiBo4tj2ANJBgAKCRCK +0jNX63i7CMPgAP4ofxoiit/7nqvndk50NkiM9Ab0yTcLnjY+b28YMDLacwEApoEl +I15NDk/uTXQRKtXrHKoORwSK3XRPSSGYgMOhkwQ= +=LiUn +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankAdminCert.asc b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankAdminCert.asc new file mode 100644 index 00000000..085cd61b --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankAdminCert.asc @@ -0,0 +1,25 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: A688 ECB2 69B3 8161 DA4D 738F F5F1 E3B5 368D 6CA7 +Comment: Foo Bank Admin + +mDMEYrcZeRYJKwYBBAHaRw8BAQdABkxvWXwHDD6B3hXYQehQkil3e3Gcg5mNbOdS +9DSeny20IkZvbyBCYW5rIEFkbWluIDxhZG1pbkBmb29iYW5rLmNvbT6IjwQTFgoA +QQUCYrcZeQkQ9fHjtTaNbKcWIQSmiOyyabOBYdpNc4/18eO1No1spwKeAQKbAQUW +AgMBAAQLCQgHBRUKCQgLApkBAABPGwEAv0TWDMkJV6QiIgm8V4b9uIEzMpQku4UM +FBHvMKXh0W8A/1pocJBG+K9srn8NJlPBul7duoNbkzzHANkytFVEBOgEiKMEEBYK +AFUFAmLNTFYJEKFJBrdXMI7wFiEEMUVo/QiegSvLRR4roUkGt1cwjvAtFIAAAAAA +FwANYWZmaWxpYXRpb25AZm9vYmFuay5jb21hZG1pbmlzdHJhdG9yAADddwEAkcJU +aQfRbAkUvOp1zPUddQq6+a5C1y33d5s2n9gLqucBALy/kkbN5moNxEtcqTD5K1uD +OFfEVEIOEAGE7ic1dWcMuDgEYrcZeRIKKwYBBAGXVQEFAQEHQDd1fqNPF27j+Z8B +PtbyoU6sp63UQfBhJrUKNFjpWNZrAwEIB4h1BBgWCgAdBQJitxl5Ap4BApsMBRYC +AwEABAsJCAcFFQoJCAsACgkQ9fHjtTaNbKdmNwEAzTQAJ/ML5puyGHR9zCbuAonD +B0lKoXlJeWX7YpsLSugA/3M4YgzpBfoRNbehCbc2hcd/hbW9gKQs2k2iCUYDoPIN +uDMEYrcZeRYJKwYBBAHaRw8BAQdAIF2e85PlS4PWquE3NLE59A1tr9KPxEznQ0Ej +G/DfefiI1QQYFgoAfQUCYrcZeQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYK +AAYFAmK3GXkACgkQUqp0e41/iO+PswD+I+dgdOrj/jflr3D0Th8cugj9zFzwFYn9 +aaGmiee5wv8A/RvvJoiwHMTi3QPvR4zGdF5pibOccbWr/dggFjKXTmoFAAoJEPXx +47U2jWynVbEBANEjxzV8KnujGor79Mc1ag9wxyDgihXRowsoKEnSkyHQAQD6n0Pf +1q8fl7BxbreVeY+0HN2swKlO9TvO303a3X6/BQ== +=WtDJ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankCaCert.asc b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankCaCert.asc new file mode 100644 index 00000000..476aad4e --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankCaCert.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 3145 68FD 089E 812B CB45 1E2B A149 06B7 5730 8EF0 +Comment: Foo Bank CA + +mDMEYrcXbxYJKwYBBAHaRw8BAQdAPIIGHwbBzEIExd70jtw7uDvOymt0nU83uLqR +4Og+cxCIlAQfFgoARgUCYs1MVgkQIa3PO58zSf4WIQQ7JP05RzLWqc9uBx4hrc87 +nzNJ/hoGPFtePl0rW0AuXWZvb2JhbmtcLmNvbT4kAAOFAXgAAD4CAPwIMuVG2f+b +UfDsrtbQx8UO8TUnoRVHhwW/ogsp9Mop6AD/SoMIK1aNxzha56NOgCmAHo3hvdVp +gflXu5SlMpDcBgyIlAQfFgoARgUCYs1MVwkQ9fHjtTaNbKcWIQSmiOyyabOBYdpN +c4/18eO1No1spxoGPFtePl0rW0AuXWZvb2JhbmtcLmNvbT4kAAOFAXgAADS+AQD5 +L1q6IO6xnG7pz4iammO7yM5jseDKsnd06q1qXTOxRQEAsYz2dx0owhU+4qZwfEME +kLIewdsBcjJurlXYDZJSkAuIlAQfFgoARgUCYs1MVwkQ+LtlEBaP0r8WIQQsTMpM +iRd/0ZHuo+D4u2UQFo/SvxoGPFtePl0rW0AuXWZvb2JhbmtcLmNvbT4kAAOFAXgA +AKlYAQDO0czTk2j+CRpYLwH24UT0NZQGcImx/xW+XHUz40y/mgEAmvkBkS0yaDET +94Nq1FpCL0oaheEybrXPzVT5+67Q2QW0HEZvbyBCYW5rIENBIDxjYUBmb29iYW5r +LmNvbT6IjwQTFgoAQQUCYrcXbwkQoUkGt1cwjvAWIQQxRWj9CJ6BK8tFHiuhSQa3 +VzCO8AKeAQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAAD+HwEAzElDjL9DRUnWd4yK +jNoB+yT6RAQ9kD6BgRs/vKyQtqcBANfIysKFneE0B4lExhh6hB2cGoMR/YMhJHSd +9zorxH4KuDgEYrcXbxIKKwYBBAGXVQEFAQEHQMmhBx59elwIbvvv3UOCLZn2VJDE +gkOGq1DOpYRNXe8FAwEIB4h1BBgWCgAdBQJitxdvAp4BApsMBRYCAwEABAsJCAcF +FQoJCAsACgkQoUkGt1cwjvDeBgEA9rsAaBuE5QWoZSH6FxHGpq5XY1rFpmvFKn7g +hZ33p6ABAJZJx0RQZGDaI5f46Pjph2U7pvLm18mXNd5cYPQtcFoFuDMEYrcXcBYJ +KwYBBAHaRw8BAQdAwdROT7LazWiJsEWF/bXjcAybl7TE3avv7GTVUT00MK2I1QQY +FgoAfQUCYrcXcAKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3F3AA +CgkQKvTwayMtR7nA+wEAzKlKeGvOSUtp5R07BTmOchkP0T3sZ0L4MvBBtpAuU5YA +/jNm1162I/ceEEtKgyKp0wC5pqYR0b+AWgB0tPaMfaoJAAoJEKFJBrdXMI7w608A +/0nV1NXH/U0pRzmNNeRJWAMlFXUdxhhYSlqrqYf2GQRlAP9NR9iMwpA0gFP+Uey3 +bCNC8MxtZLKhPkz2Rz4pnnfaDA== +=y1eO +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankEmployeeCert.asc b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankEmployeeCert.asc new file mode 100644 index 00000000..649a2d56 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/cross_signed/foobankEmployeeCert.asc @@ -0,0 +1,25 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 3B24 FD39 4732 D6A9 CF6E 071E 21AD CF3B 9F33 49FE +Comment: Foo Bank Employee + +mDMEYrcZeRYJKwYBBAHaRw8BAQdAl9j10kv/7NRAZe+yATf7kkXOoHwkxaKkHzM3 +wMihWlu0KEZvbyBCYW5rIEVtcGxveWVlIDxlbXBsb3llZUBmb29iYW5rLmNvbT6I +jwQTFgoAQQUCYrcZeQkQIa3PO58zSf4WIQQ7JP05RzLWqc9uBx4hrc87nzNJ/gKe +AQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAAA1aAEAthiiVUcYiKVyzfzbrZLkQlTW +NR6fu85fR5rPns2NUdwA/2vkrneDmkE04osRwUGLMh30iQzduQ3aFW0hEe2OmDUO +iJ4EEBYKAFAFAmLNTFYJEKFJBrdXMI7wFiEEMUVo/QiegSvLRR4roUkGt1cwjvAo +FIAAAAAAFwAIYWZmaWxpYXRpb25AZm9vYmFuay5jb21lbXBsb3llZQAAVjoBAOqF +r5tscY9sx4sxEjgDJ+v4+Jd4KxU8bNljzde4BG+AAP9Dj2IhrpNe8CJJlncV2TC1 +55IXAr/DLYcKwzqEJrVxBLg4BGK3GXkSCisGAQQBl1UBBQEBB0ArMHy+cSuGxSdZ +ScGncoxzB9ZLioxTRlR5Mqd/M2rNGAMBCAeIdQQYFgoAHQUCYrcZeQKeAQKbDAUW +AgMBAAQLCQgHBRUKCQgLAAoJECGtzzufM0n+vDoA/A3p3LMYSUcvELY9Af3nC6/4 +71r5B3MDnURShddOtcRyAP96J1i5ExKnC+Ltw36/QtyxfyHp9Pr9Fw6BX/zq4EFo +CrgzBGK3GXkWCSsGAQQB2kcPAQEHQPlVJ9tosjkDY81zIKll52Gh00rhhXY1jFEx +x248kkrjiNUEGBYKAH0FAmK3GXkCngECmwIFFgIDAQAECwkIBwUVCgkIC18gBBkW +CgAGBQJitxl5AAoJEJxjnlk3tCvcxesBAIf5xQYgRFfDeQlr63uglNCsvOXMa8BN +LzgObT2nn8LrAQC+sqoWycLRFdFqg29E4OjhZd3iRvFWDoIfs67d9ywBDgAKCRAh +rc87nzNJ/jWHAP4zs2k1MtV2eOcjUzdt8cfMsiHcD29uJsv6O628gqVdqgD/dvb5 +LPKxFPnfhSGOip0q2USrbBZLgupBjsNuVVu2IgM= +=DqW1 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankCaCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankCaCert.asc new file mode 100644 index 00000000..a3b185a9 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankCaCert.asc @@ -0,0 +1,22 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: CEE5 FB5D C524 84A6 9B73 9FAD 7DA0 2993 D86B 0355 +Comment: Bar Bank CA + +mDMEYs1BgxYJKwYBBAHaRw8BAQdA3hOlkHAVyvTwePiifKnwLhkcJnswNidJ7dWo +UKEQlZW0HEJhciBCYW5rIENBIDxjYUBiYXJiYW5rLmNvbT6IjwQTFgoAQQUCYs1B +gwkQfaApk9hrA1UWIQTO5ftdxSSEpptzn619oCmT2GsDVQKeAQKbAQUWAgMBAAQL +CQgHBRUKCQgLApkBAABltgEA4Ob86bhjLa6Xg4wnzYIGH21WEUlc37BBaqwr4qvf +sA4A/0BzOdTy3Wty5DkdMiA2yPOxIVuHbTD8pgqpne2yoegNuDgEYs1BgxIKKwYB +BAGXVQEFAQEHQDVHLNRE4Gtg9/BzwSUMW3psBD7OUm4Df0ggilvLZhMcAwEIB4h1 +BBgWCgAdBQJizUGDAp4BApsMBRYCAwEABAsJCAcFFQoJCAsACgkQfaApk9hrA1Wr +YAEAsZsEoUfAPIG6d9gtK7Zmm3zt+xiTELW08E/pwjmFTmEBAODICUhsEelkdXrb +IkL2oWAKoxlsbkyA6mNXBt5UXQcJuDMEYs1BgxYJKwYBBAHaRw8BAQdARHF/sgST +B38osF0+XA9N2htsMIrb322j3LQdrk0M77SI1QQYFgoAfQUCYs1BgwKeAQKbAgUW +AgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmLNQYMACgkQtEK9w/vjcduqJwD+KW23 ++689GXtu4k3PW60GPsiue22lMGwZY7hsWvZB1hkBAPER8PMs0MJAQzcs2u6bYPMD +I921umqX8Yvsob1kzs0FAAoJEH2gKZPYawNVdKwBAKz5zfwEKZ2dGPCsUJzAXfPx +e0LmATcvS5g/LvAreD0KAQDfpfMFO2EqQu6wDt+e5MH3YCjGsaYwvjB1elj1zhbl +Ag== +=Xlkn +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankCaKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankCaKey.asc new file mode 100644 index 00000000..638a655e --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankCaKey.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: CEE5 FB5D C524 84A6 9B73 9FAD 7DA0 2993 D86B 0355 +Comment: Bar Bank CA + +lFgEYs1BgxYJKwYBBAHaRw8BAQdA3hOlkHAVyvTwePiifKnwLhkcJnswNidJ7dWo +UKEQlZUAAQD94AUX6NT0z3kvWb1CXxgZacF3w/r2IWV0lSc6WZDcQRBTtBxCYXIg +QmFuayBDQSA8Y2FAYmFyYmFuay5jb20+iI8EExYKAEEFAmLNQYMJEH2gKZPYawNV +FiEEzuX7XcUkhKabc5+tfaApk9hrA1UCngECmwEFFgIDAQAECwkIBwUVCgkICwKZ +AQAAZbYBAODm/Om4Yy2ul4OMJ82CBh9tVhFJXN+wQWqsK+Kr37AOAP9AcznU8t1r +cuQ5HTIgNsjzsSFbh20w/KYKqZ3tsqHoDZxdBGLNQYMSCisGAQQBl1UBBQEBB0A1 +RyzUROBrYPfwc8ElDFt6bAQ+zlJuA39IIIpby2YTHAMBCAcAAP9FU6uepd97vJ4y +VTcvtzPXG9jvpgNw50pDfV90z6VAwBEaiHUEGBYKAB0FAmLNQYMCngECmwwFFgID +AQAECwkIBwUVCgkICwAKCRB9oCmT2GsDVatgAQCxmwShR8A8gbp32C0rtmabfO37 +GJMQtbTwT+nCOYVOYQEA4MgJSGwR6WR1etsiQvahYAqjGWxuTIDqY1cG3lRdBwmc +WARizUGDFgkrBgEEAdpHDwEBB0BEcX+yBJMHfyiwXT5cD03aG2wwitvfbaPctB2u +TQzvtAABAJJiLD7fXGdr/liZ//EOhJ4YicrcxXahud6q3OYA1QUJEYSI1QQYFgoA +fQUCYs1BgwKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmLNQYMACgkQ +tEK9w/vjcduqJwD+KW23+689GXtu4k3PW60GPsiue22lMGwZY7hsWvZB1hkBAPER +8PMs0MJAQzcs2u6bYPMDI921umqX8Yvsob1kzs0FAAoJEH2gKZPYawNVdKwBAKz5 +zfwEKZ2dGPCsUJzAXfPxe0LmATcvS5g/LvAreD0KAQDfpfMFO2EqQu6wDt+e5MH3 +YCjGsaYwvjB1elj1zhblAg== +=owuy +-----END PGP PRIVATE KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankEmployeeCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankEmployeeCert.asc new file mode 100644 index 00000000..cf98edba --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankEmployeeCert.asc @@ -0,0 +1,22 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 447A 82AA 03F7 D7A4 B1DA 4D7C 8AD2 3357 EB78 BB08 +Comment: Bar Bank Employee + +mDMEYs1CXRYJKwYBBAHaRw8BAQdAeMjyfqInb8aZppFsKHdndoeL3j08Z5CtagKz +KPb6YGO0KEJhciBCYW5rIEVtcGxveWVlIDxlbXBsb3llZUBiYXJiYW5rLmNvbT6I +jwQTFgoAQQUCYs1CXQkQitIzV+t4uwgWIQREeoKqA/fXpLHaTXyK0jNX63i7CAKe +AQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAACgcgD7Bk2Hu+Lu3aA+IyzFyTQOw8zQ +RUeA/X8neEIezYDTC+MA/jGFyiKW7b+6W3zgdIgiHMeWhG3Wx2oOC1izW2+tP2cJ +uDgEYs1CXRIKKwYBBAGXVQEFAQEHQGrbXqc/inD2vUXw4xxRaKxhS8549R5Qs8th +X6NfxR0GAwEIB4h1BBgWCgAdBQJizUJdAp4BApsMBRYCAwEABAsJCAcFFQoJCAsA +CgkQitIzV+t4uwijlAD8D3MPPxeuO1skgrrQneSbC9iPKcX0iTPIVOPiw14eElMA +/3Z1Na9uiATDM+EFuh/DM5Ps9eDuVpDy/15OqvnSVZ8HuDMEYs1CXRYJKwYBBAHa +Rw8BAQdARX1KmiiBbYetUhpT3ndbfVx4O8OYFYwUFBBrdCzPogGI1QQYFgoAfQUC +Ys1CXQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmLNQl0ACgkQ0bcL +6V1JVto+wAD/aCJkdwZPSfICiM92zUh8gT3t3ICVWCN9tMfcfhA1WwAA/12lqQNn +Jr+rwz/Cdk7I4F/50eJSu8NvGIGji2PYA0kGAAoJEIrSM1freLsIw+AA/ih/GiKK +3/ueq+d2TnQ2SIz0BvTJNwueNj5vbxgwMtpzAQCmgSUjXk0OT+5NdBEq1escqg5H +BIrddE9JIZiAw6GTBA== +=F0kp +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankEmployeeKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankEmployeeKey.asc new file mode 100644 index 00000000..ff723c7a --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/barbankEmployeeKey.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: 447A 82AA 03F7 D7A4 B1DA 4D7C 8AD2 3357 EB78 BB08 +Comment: Bar Bank Employee + +lFgEYs1CXRYJKwYBBAHaRw8BAQdAeMjyfqInb8aZppFsKHdndoeL3j08Z5CtagKz +KPb6YGMAAP0WnOME3m2zmC6ujA1r5s1RLCtIsrWnkX62ICDCJzIWLA8ftChCYXIg +QmFuayBFbXBsb3llZSA8ZW1wbG95ZWVAYmFyYmFuay5jb20+iI8EExYKAEEFAmLN +Ql0JEIrSM1freLsIFiEERHqCqgP316Sx2k18itIzV+t4uwgCngECmwEFFgIDAQAE +CwkIBwUVCgkICwKZAQAAoHIA+wZNh7vi7t2gPiMsxck0DsPM0EVHgP1/J3hCHs2A +0wvjAP4xhcoilu2/ult84HSIIhzHloRt1sdqDgtYs1tvrT9nCZxdBGLNQl0SCisG +AQQBl1UBBQEBB0Bq216nP4pw9r1F8OMcUWisYUvOePUeULPLYV+jX8UdBgMBCAcA +AP9AYnLs0zkVSsWMxZDMTCoW1fjrgjzOMGeZRtsvrcUA2BF2iHUEGBYKAB0FAmLN +Ql0CngECmwwFFgIDAQAECwkIBwUVCgkICwAKCRCK0jNX63i7CKOUAPwPcw8/F647 +WySCutCd5JsL2I8pxfSJM8hU4+LDXh4SUwD/dnU1r26IBMMz4QW6H8Mzk+z14O5W +kPL/Xk6q+dJVnwecWARizUJdFgkrBgEEAdpHDwEBB0BFfUqaKIFth61SGlPed1t9 +XHg7w5gVjBQUEGt0LM+iAQAA/3fH0f3QPCOEpByws3f4Ovqjc+IzwFmA6mmwlxN2 +9wNpEs6I1QQYFgoAfQUCYs1CXQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYK +AAYFAmLNQl0ACgkQ0bcL6V1JVto+wAD/aCJkdwZPSfICiM92zUh8gT3t3ICVWCN9 +tMfcfhA1WwAA/12lqQNnJr+rwz/Cdk7I4F/50eJSu8NvGIGji2PYA0kGAAoJEIrS +M1freLsIw+AA/ih/GiKK3/ueq+d2TnQ2SIz0BvTJNwueNj5vbxgwMtpzAQCmgSUj +Xk0OT+5NdBEq1escqg5HBIrddE9JIZiAw6GTBA== +=7A42 +-----END PGP PRIVATE KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/fakeFoobankEmployeeCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/fakeFoobankEmployeeCert.asc new file mode 100644 index 00000000..7a6a78d1 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/fakeFoobankEmployeeCert.asc @@ -0,0 +1,22 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: E5C1 A41B E6BF 8E3D 595B 7214 2284 3AF5 6677 E9B0 +Comment: Foo Bank Employee (Attacker) + +mDMEYs1CoBYJKwYBBAHaRw8BAQdAKjGuG4PPeUX1utitGGofxfcD5Sqf7c9CtyFA +qXA/gd60M0ZvbyBCYW5rIEVtcGxveWVlIChBdHRhY2tlcikgPGVtcGxveWVlQGZv +b2JhbmsuY29tPoiPBBMWCgBBBQJizUKgCRAihDr1ZnfpsBYhBOXBpBvmv449WVty +FCKEOvVmd+mwAp4BApsBBRYCAwEABAsJCAcFFQoJCAsCmQEAAAorAP9E0cnmX26P +zIcvmYXqCH4gfkH/18efgKAtLxFwz3yxuwD+KFj4xDxWy/KTmFRhJmFDBhJsNUiH +tNEbVpBV1GiVLQ24OARizUKgEgorBgEEAZdVAQUBAQdAU05+Xcun+77TCwhuwW/Y +zdKexCD+6u4EPUXyDKo0rjMDAQgHiHUEGBYKAB0FAmLNQqACngECmwwFFgIDAQAE +CwkIBwUVCgkICwAKCRAihDr1ZnfpsHH/AQDsxQe/sYVqwgtSFbOxw/hmGMEmMOwx +E5B+Pk7lLGcC3gEAuaFwRb4UgOeadQQ7eerxE0djYjL+wpqYLkYZrWI1dAy4MwRi +zUKgFgkrBgEEAdpHDwEBB0Dc1odFo5f84ciLYjkWoH0jAMlZxc/TLMS1yi5lrohX +M4jVBBgWCgB9BQJizUKgAp4BApsCBRYCAwEABAsJCAcFFQoJCAtfIAQZFgoABgUC +Ys1CoAAKCRDcHi36XF9/A/pLAQD7tDyLsbP+s6jV4ZloujljLdxIlhg+g/87ruhc +ISPRKQD/bTubvAzC8ixoYAWGPZOEut03b+zJ4g1l8SHXVCb+HwkACgkQIoQ69WZ3 +6bAdwgEAhZb7c0u07FlgxXkEIPIt45DwZbML37hxaVjF08NlwssBAJInWO4Gcj8T +L0GLRaWEF+8dpPp+WtgklVkFel7f2XoK +=UN4g +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/fakeFoobankEmployeeKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/fakeFoobankEmployeeKey.asc new file mode 100644 index 00000000..634eee72 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/fakeFoobankEmployeeKey.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: E5C1 A41B E6BF 8E3D 595B 7214 2284 3AF5 6677 E9B0 +Comment: Foo Bank Employee (Attacker) + +lFgEYs1CoBYJKwYBBAHaRw8BAQdAKjGuG4PPeUX1utitGGofxfcD5Sqf7c9CtyFA +qXA/gd4AAP4vJXkVBVsASvS7pwIJXVuqKDb7yeCaR6Bjh9ihE1tZQw49tDNGb28g +QmFuayBFbXBsb3llZSAoQXR0YWNrZXIpIDxlbXBsb3llZUBmb29iYW5rLmNvbT6I +jwQTFgoAQQUCYs1CoAkQIoQ69WZ36bAWIQTlwaQb5r+OPVlbchQihDr1ZnfpsAKe +AQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAAAKKwD/RNHJ5l9uj8yHL5mF6gh+IH5B +/9fHn4CgLS8RcM98sbsA/ihY+MQ8Vsvyk5hUYSZhQwYSbDVIh7TRG1aQVdRolS0N +nF0EYs1CoBIKKwYBBAGXVQEFAQEHQFNOfl3Lp/u+0wsIbsFv2M3SnsQg/uruBD1F +8gyqNK4zAwEIBwAA/2grdpHBu9eI82YNrx+/ljb69FIYK2ttBVmL5awfh9rgEWiI +dQQYFgoAHQUCYs1CoAKeAQKbDAUWAgMBAAQLCQgHBRUKCQgLAAoJECKEOvVmd+mw +cf8BAOzFB7+xhWrCC1IVs7HD+GYYwSYw7DETkH4+TuUsZwLeAQC5oXBFvhSA55p1 +BDt56vETR2NiMv7CmpguRhmtYjV0DJxYBGLNQqAWCSsGAQQB2kcPAQEHQNzWh0Wj +l/zhyItiORagfSMAyVnFz9MsxLXKLmWuiFczAAEA+xMd+XrMwFJisctVMfZaaPDR +QZ7EAVeCZU2UAe0u1ssQ2ojVBBgWCgB9BQJizUKgAp4BApsCBRYCAwEABAsJCAcF +FQoJCAtfIAQZFgoABgUCYs1CoAAKCRDcHi36XF9/A/pLAQD7tDyLsbP+s6jV4Zlo +ujljLdxIlhg+g/87ruhcISPRKQD/bTubvAzC8ixoYAWGPZOEut03b+zJ4g1l8SHX +VCb+HwkACgkQIoQ69WZ36bAdwgEAhZb7c0u07FlgxXkEIPIt45DwZbML37hxaVjF +08NlwssBAJInWO4Gcj8TL0GLRaWEF+8dpPp+WtgklVkFel7f2XoK +=saRS +-----END PGP PRIVATE KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankAdminCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankAdminCert.asc new file mode 100644 index 00000000..d47cb888 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankAdminCert.asc @@ -0,0 +1,22 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: A688 ECB2 69B3 8161 DA4D 738F F5F1 E3B5 368D 6CA7 +Comment: Foo Bank Admin + +mDMEYrcZeRYJKwYBBAHaRw8BAQdABkxvWXwHDD6B3hXYQehQkil3e3Gcg5mNbOdS +9DSeny20IkZvbyBCYW5rIEFkbWluIDxhZG1pbkBmb29iYW5rLmNvbT6IjwQTFgoA +QQUCYrcZeQkQ9fHjtTaNbKcWIQSmiOyyabOBYdpNc4/18eO1No1spwKeAQKbAQUW +AgMBAAQLCQgHBRUKCQgLApkBAABPGwEAv0TWDMkJV6QiIgm8V4b9uIEzMpQku4UM +FBHvMKXh0W8A/1pocJBG+K9srn8NJlPBul7duoNbkzzHANkytFVEBOgEuDgEYrcZ +eRIKKwYBBAGXVQEFAQEHQDd1fqNPF27j+Z8BPtbyoU6sp63UQfBhJrUKNFjpWNZr +AwEIB4h1BBgWCgAdBQJitxl5Ap4BApsMBRYCAwEABAsJCAcFFQoJCAsACgkQ9fHj +tTaNbKdmNwEAzTQAJ/ML5puyGHR9zCbuAonDB0lKoXlJeWX7YpsLSugA/3M4Ygzp +BfoRNbehCbc2hcd/hbW9gKQs2k2iCUYDoPINuDMEYrcZeRYJKwYBBAHaRw8BAQdA +IF2e85PlS4PWquE3NLE59A1tr9KPxEznQ0EjG/DfefiI1QQYFgoAfQUCYrcZeQKe +AQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3GXkACgkQUqp0e41/iO+P +swD+I+dgdOrj/jflr3D0Th8cugj9zFzwFYn9aaGmiee5wv8A/RvvJoiwHMTi3QPv +R4zGdF5pibOccbWr/dggFjKXTmoFAAoJEPXx47U2jWynVbEBANEjxzV8KnujGor7 +9Mc1ag9wxyDgihXRowsoKEnSkyHQAQD6n0Pf1q8fl7BxbreVeY+0HN2swKlO9TvO +303a3X6/BQ== +=CESR +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankAdminKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankAdminKey.asc new file mode 100644 index 00000000..1907ded5 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankAdminKey.asc @@ -0,0 +1,27 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: A688 ECB2 69B3 8161 DA4D 738F F5F1 E3B5 368D 6CA7 +Comment: Foo Bank Admin + +lIYEYrcZeRYJKwYBBAHaRw8BAQdABkxvWXwHDD6B3hXYQehQkil3e3Gcg5mNbOdS +9DSeny3+CQMCmWVHhM7xa9pgkX1Z8T7FcGWpMD91IgrF+7Bh97UtTFw8a71ixXww +pH/86zqEE9mry/95KvxsiCSPYwKhS0j4S20mZfQriWvpM3gCZSbhMrQiRm9vIEJh +bmsgQWRtaW4gPGFkbWluQGZvb2JhbmsuY29tPoiPBBMWCgBBBQJitxl5CRD18eO1 +No1spxYhBKaI7LJps4Fh2k1zj/Xx47U2jWynAp4BApsBBRYCAwEABAsJCAcFFQoJ +CAsCmQEAAE8bAQC/RNYMyQlXpCIiCbxXhv24gTMylCS7hQwUEe8wpeHRbwD/Wmhw +kEb4r2yufw0mU8G6Xt26g1uTPMcA2TK0VUQE6ASciwRitxl5EgorBgEEAZdVAQUB +AQdAN3V+o08XbuP5nwE+1vKhTqynrdRB8GEmtQo0WOlY1msDAQgH/gkDApllR4TO +8WvaYNfxPfMWsBQLze2hTDxhCds/kO7WSwJw0cN3IzGlCrv+KSId5n6Rfz4NtlWN +yBOIecPZbzK4H0RSIc7jqiNRMqznpclwNYGIdQQYFgoAHQUCYrcZeQKeAQKbDAUW +AgMBAAQLCQgHBRUKCQgLAAoJEPXx47U2jWynZjcBAM00ACfzC+abshh0fcwm7gKJ +wwdJSqF5SXll+2KbC0roAP9zOGIM6QX6ETW3oQm3NoXHf4W1vYCkLNpNoglGA6Dy +DZyGBGK3GXkWCSsGAQQB2kcPAQEHQCBdnvOT5UuD1qrhNzSxOfQNba/Sj8RM50NB +Ixvw33n4/gkDApllR4TO8WvaYFyjXSJ54rtghVxVYEUd4OFWaGmKO5+KMEgqCqv4 +TWhfaqT+wV5hKJbx/IkgZFS9viFTK7BEEhaApslO/TuE6nFSoi7gVw+I1QQYFgoA +fQUCYrcZeQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3GXkACgkQ +Uqp0e41/iO+PswD+I+dgdOrj/jflr3D0Th8cugj9zFzwFYn9aaGmiee5wv8A/Rvv +JoiwHMTi3QPvR4zGdF5pibOccbWr/dggFjKXTmoFAAoJEPXx47U2jWynVbEBANEj +xzV8KnujGor79Mc1ag9wxyDgihXRowsoKEnSkyHQAQD6n0Pf1q8fl7BxbreVeY+0 +HN2swKlO9TvO303a3X6/BQ== +=4xhi +-----END PGP PRIVATE KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCaCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCaCert.asc new file mode 100644 index 00000000..ecdf40cd --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCaCert.asc @@ -0,0 +1,23 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 3145 68FD 089E 812B CB45 1E2B A149 06B7 5730 8EF0 +Comment: Foo Bank CA +Comment: Freshly generated cert + +mDMEYrcXbxYJKwYBBAHaRw8BAQdAPIIGHwbBzEIExd70jtw7uDvOymt0nU83uLqR +4Og+cxC0HEZvbyBCYW5rIENBIDxjYUBmb29iYW5rLmNvbT6IjwQTFgoAQQUCYrcX +bwkQoUkGt1cwjvAWIQQxRWj9CJ6BK8tFHiuhSQa3VzCO8AKeAQKbAQUWAgMBAAQL +CQgHBRUKCQgLApkBAAD+HwEAzElDjL9DRUnWd4yKjNoB+yT6RAQ9kD6BgRs/vKyQ +tqcBANfIysKFneE0B4lExhh6hB2cGoMR/YMhJHSd9zorxH4KuDgEYrcXbxIKKwYB +BAGXVQEFAQEHQMmhBx59elwIbvvv3UOCLZn2VJDEgkOGq1DOpYRNXe8FAwEIB4h1 +BBgWCgAdBQJitxdvAp4BApsMBRYCAwEABAsJCAcFFQoJCAsACgkQoUkGt1cwjvDe +BgEA9rsAaBuE5QWoZSH6FxHGpq5XY1rFpmvFKn7ghZ33p6ABAJZJx0RQZGDaI5f4 +6Pjph2U7pvLm18mXNd5cYPQtcFoFuDMEYrcXcBYJKwYBBAHaRw8BAQdAwdROT7La +zWiJsEWF/bXjcAybl7TE3avv7GTVUT00MK2I1QQYFgoAfQUCYrcXcAKeAQKbAgUW +AgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3F3AACgkQKvTwayMtR7nA+wEAzKlK +eGvOSUtp5R07BTmOchkP0T3sZ0L4MvBBtpAuU5YA/jNm1162I/ceEEtKgyKp0wC5 +pqYR0b+AWgB0tPaMfaoJAAoJEKFJBrdXMI7w608A/0nV1NXH/U0pRzmNNeRJWAMl +FXUdxhhYSlqrqYf2GQRlAP9NR9iMwpA0gFP+Uey3bCNC8MxtZLKhPkz2Rz4pnnfa +DA== +=5bcR +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCaKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCaKey.asc new file mode 100644 index 00000000..bb403ae0 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCaKey.asc @@ -0,0 +1,28 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: 3145 68FD 089E 812B CB45 1E2B A149 06B7 5730 8EF0 +Comment: Foo Bank CA +Comment: Freshly generated key + +lIYEYrcXbxYJKwYBBAHaRw8BAQdAPIIGHwbBzEIExd70jtw7uDvOymt0nU83uLqR +4Og+cxD+CQMCgCIAcSyeuXJgGMgKUCcU6tDwfGXgIVy0wCoDsSX2qWTKkyOYf7fu +Kw0BmQ4bFhQtC9hpPDhCKuR0cLUV8f0TEU0/Vq4n5hNy2erDW60KFLQcRm9vIEJh +bmsgQ0EgPGNhQGZvb2JhbmsuY29tPoiPBBMWCgBBBQJitxdvCRChSQa3VzCO8BYh +BDFFaP0InoEry0UeK6FJBrdXMI7wAp4BApsBBRYCAwEABAsJCAcFFQoJCAsCmQEA +AP4fAQDMSUOMv0NFSdZ3jIqM2gH7JPpEBD2QPoGBGz+8rJC2pwEA18jKwoWd4TQH +iUTGGHqEHZwagxH9gyEkdJ33OivEfgqciwRitxdvEgorBgEEAZdVAQUBAQdAyaEH +Hn16XAhu++/dQ4ItmfZUkMSCQ4arUM6lhE1d7wUDAQgH/gkDAoAiAHEsnrlyYPCE +d+xi8TsvxtcWq7lO+wwMxg/et4nFijmCDwK5/1duRutt/UYj1PU1cicfJ9choM6l +5qui74PBr5yTkUvNhAOjWfH60heIdQQYFgoAHQUCYrcXbwKeAQKbDAUWAgMBAAQL +CQgHBRUKCQgLAAoJEKFJBrdXMI7w3gYBAPa7AGgbhOUFqGUh+hcRxqauV2NaxaZr +xSp+4IWd96egAQCWScdEUGRg2iOX+Oj46YdlO6by5tfJlzXeXGD0LXBaBZyGBGK3 +F3AWCSsGAQQB2kcPAQEHQMHUTk+y2s1oibBFhf2143AMm5e0xN2r7+xk1VE9NDCt +/gkDAoAiAHEsnrlyYFpx33LyuL4N/uccem+lZPCwjSum+Turs6vZQNY3toahx0fm +i68BGm1Eu716NN/5AV3nXXa9jmf6PsesiEvfWWITo8A7/fuI1QQYFgoAfQUCYrcX +cAKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3F3AACgkQKvTwayMt +R7nA+wEAzKlKeGvOSUtp5R07BTmOchkP0T3sZ0L4MvBBtpAuU5YA/jNm1162I/ce +EEtKgyKp0wC5pqYR0b+AWgB0tPaMfaoJAAoJEKFJBrdXMI7w608A/0nV1NXH/U0p +RzmNNeRJWAMlFXUdxhhYSlqrqYf2GQRlAP9NR9iMwpA0gFP+Uey3bCNC8MxtZLKh +Pkz2Rz4pnnfaDA== +=roYK +-----END PGP PRIVATE KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCustomerCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCustomerCert.asc new file mode 100644 index 00000000..651dd214 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCustomerCert.asc @@ -0,0 +1,22 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 2C4C CA4C 8917 7FD1 91EE A3E0 F8BB 6510 168F D2BF +Comment: Customer + +mDMEYrcaYxYJKwYBBAHaRw8BAQdAIt6xhlPPq2wTnLO2CqMvoP2yk68NBSPJWkse +85lCWee0H0N1c3RvbWVyIDxjdXN0b21lckBleGFtcGxlLmNvbT6IjwQTFgoAQQUC +YrcaYwkQ+LtlEBaP0r8WIQQsTMpMiRd/0ZHuo+D4u2UQFo/SvwKeAQKbAQUWAgMB +AAQLCQgHBRUKCQgLApkBAAB3agEAmnfM6RToSpLfBFXOERCAz0v9FYfskTz7bsGM +CPSEgYcBAK85o67OTq5y8JhHHFfHvHeIIaE/IAzJLQHRNT3pvJ8KuDgEYrcaYxIK +KwYBBAGXVQEFAQEHQGZVHqBfmrVSMbIFQUSE9bnj9JU/W/JUFuPHbd5csPpdAwEI +B4h1BBgWCgAdBQJitxpjAp4BApsMBRYCAwEABAsJCAcFFQoJCAsACgkQ+LtlEBaP +0r/XhAD+LHlbWcUil8HmnWpBSwcv3wBP1vnt4zPOlm1pkfmgq/MA/3hb+I0kQNMR +7ux3bYORuLiHulapQtYQG5GGRfbvJqMPuDMEYrcaYxYJKwYBBAHaRw8BAQdAy3Jc +mVMbgm6VT88y2xNCFrePTBXaroz90pI9mWBjvMGI1QQYFgoAfQUCYrcaYwKeAQKb +AgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3GmMACgkQZTy2QngzKnRNbwEA +pyuSMaZgI+kOaiFiIxCGXoR/zhYKKMyoq5JlF1W+cwQBALwz2ixIlP3jzT7wJnDf +hcK7n/SMlXD4MIqR2CQkxRYHAAoJEPi7ZRAWj9K/Cb0A/24XLgqc5mj+MT0gyXRU +GBOpoTlpZ86bpb4LcLycRU+0AQDuAq/i1n6e/noMRsbOh0WYZbqAbOgiv9DVJcRQ +4kfpAg== +=r4Bk +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCustomerKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCustomerKey.asc new file mode 100644 index 00000000..68c5ed09 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankCustomerKey.asc @@ -0,0 +1,24 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: 2C4C CA4C 8917 7FD1 91EE A3E0 F8BB 6510 168F D2BF +Comment: Customer + +lFgEYrcaYxYJKwYBBAHaRw8BAQdAIt6xhlPPq2wTnLO2CqMvoP2yk68NBSPJWkse +85lCWecAAP9xVDxOuRZ5pDo5cSKIJf50dMNp/I/xHkNDHPNcI+ManQ9HtB9DdXN0 +b21lciA8Y3VzdG9tZXJAZXhhbXBsZS5jb20+iI8EExYKAEEFAmK3GmMJEPi7ZRAW +j9K/FiEELEzKTIkXf9GR7qPg+LtlEBaP0r8CngECmwEFFgIDAQAECwkIBwUVCgkI +CwKZAQAAd2oBAJp3zOkU6EqS3wRVzhEQgM9L/RWH7JE8+27BjAj0hIGHAQCvOaOu +zk6ucvCYRxxXx7x3iCGhPyAMyS0B0TU96byfCpxdBGK3GmMSCisGAQQBl1UBBQEB +B0BmVR6gX5q1UjGyBUFEhPW54/SVP1vyVBbjx23eXLD6XQMBCAcAAP9iOym80xxC +El9TTF/k7mfRBjNocGBMMUP5nnkPwdag2A+KiHUEGBYKAB0FAmK3GmMCngECmwwF +FgIDAQAECwkIBwUVCgkICwAKCRD4u2UQFo/Sv9eEAP4seVtZxSKXweadakFLBy/f +AE/W+e3jM86WbWmR+aCr8wD/eFv4jSRA0xHu7Hdtg5G4uIe6VqlC1hAbkYZF9u8m +ow+cWARitxpjFgkrBgEEAdpHDwEBB0DLclyZUxuCbpVPzzLbE0IWt49MFdqujP3S +kj2ZYGO8wQABAPY7EMCZEq/sSDkldwv/43GUe4KuDay7Q6jHugO+YkkqD3iI1QQY +FgoAfQUCYrcaYwKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3GmMA +CgkQZTy2QngzKnRNbwEApyuSMaZgI+kOaiFiIxCGXoR/zhYKKMyoq5JlF1W+cwQB +ALwz2ixIlP3jzT7wJnDfhcK7n/SMlXD4MIqR2CQkxRYHAAoJEPi7ZRAWj9K/Cb0A +/24XLgqc5mj+MT0gyXRUGBOpoTlpZ86bpb4LcLycRU+0AQDuAq/i1n6e/noMRsbO +h0WYZbqAbOgiv9DVJcRQ4kfpAg== +=th8Q +-----END PGP PRIVATE KEY BLOCK----- \ No newline at end of file diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankEmployeeCert.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankEmployeeCert.asc new file mode 100644 index 00000000..5edc820d --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankEmployeeCert.asc @@ -0,0 +1,22 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPainless +Comment: 3B24 FD39 4732 D6A9 CF6E 071E 21AD CF3B 9F33 49FE +Comment: Foo Bank Employee + +mDMEYrcZeRYJKwYBBAHaRw8BAQdAl9j10kv/7NRAZe+yATf7kkXOoHwkxaKkHzM3 +wMihWlu0KEZvbyBCYW5rIEVtcGxveWVlIDxlbXBsb3llZUBmb29iYW5rLmNvbT6I +jwQTFgoAQQUCYrcZeQkQIa3PO58zSf4WIQQ7JP05RzLWqc9uBx4hrc87nzNJ/gKe +AQKbAQUWAgMBAAQLCQgHBRUKCQgLApkBAAA1aAEAthiiVUcYiKVyzfzbrZLkQlTW +NR6fu85fR5rPns2NUdwA/2vkrneDmkE04osRwUGLMh30iQzduQ3aFW0hEe2OmDUO +uDgEYrcZeRIKKwYBBAGXVQEFAQEHQCswfL5xK4bFJ1lJwadyjHMH1kuKjFNGVHky +p38zas0YAwEIB4h1BBgWCgAdBQJitxl5Ap4BApsMBRYCAwEABAsJCAcFFQoJCAsA +CgkQIa3PO58zSf68OgD8DencsxhJRy8Qtj0B/ecLr/jvWvkHcwOdRFKF1061xHIA +/3onWLkTEqcL4u3Dfr9C3LF/Ien0+v0XDoFf/OrgQWgKuDMEYrcZeRYJKwYBBAHa +Rw8BAQdA+VUn22iyOQNjzXMgqWXnYaHTSuGFdjWMUTHHbjySSuOI1QQYFgoAfQUC +YrcZeQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3GXkACgkQnGOe +WTe0K9zF6wEAh/nFBiBEV8N5CWvre6CU0Ky85cxrwE0vOA5tPaefwusBAL6yqhbJ +wtEV0WqDb0Tg6OFl3eJG8VYOgh+zrt33LAEOAAoJECGtzzufM0n+NYcA/jOzaTUy +1XZ45yNTN23xx8yyIdwPb24my/o7rbyCpV2qAP929vks8rEU+d+FIY6KnSrZRKts +FkuC6kGOw25VW7YiAw== +=/hVO +-----END PGP PUBLIC KEY BLOCK----- diff --git a/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankEmployeeKey.asc b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankEmployeeKey.asc new file mode 100644 index 00000000..48a3e4e5 --- /dev/null +++ b/wot-dijkstra/src/test/resources/test_vectors/freshly_generated/foobankEmployeeKey.asc @@ -0,0 +1,27 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: PGPainless +Comment: 3B24 FD39 4732 D6A9 CF6E 071E 21AD CF3B 9F33 49FE +Comment: Foo Bank Employee + +lIYEYrcZeRYJKwYBBAHaRw8BAQdAl9j10kv/7NRAZe+yATf7kkXOoHwkxaKkHzM3 +wMihWlv+CQMCMzeQucBpShVg5GroEDGhC62uvl+Rjki+P6aR5rCKbaoff1Y3DEGQ +LEz0InfGo4I2lLUhox1E+th6BHT+fwg7E/Qk+9j040TvEXAqHIJhXbQoRm9vIEJh +bmsgRW1wbG95ZWUgPGVtcGxveWVlQGZvb2JhbmsuY29tPoiPBBMWCgBBBQJitxl5 +CRAhrc87nzNJ/hYhBDsk/TlHMtapz24HHiGtzzufM0n+Ap4BApsBBRYCAwEABAsJ +CAcFFQoJCAsCmQEAADVoAQC2GKJVRxiIpXLN/NutkuRCVNY1Hp+7zl9Hms+ezY1R +3AD/a+Sud4OaQTTiixHBQYsyHfSJDN25DdoVbSER7Y6YNQ6ciwRitxl5EgorBgEE +AZdVAQUBAQdAKzB8vnErhsUnWUnBp3KMcwfWS4qMU0ZUeTKnfzNqzRgDAQgH/gkD +AjM3kLnAaUoVYI0D8gPzG1t3dPpkNgc411bts2T9BgrZPkV7C3u338TXsFSHxTdo +vK7/l/PhikN0qKjKVG5PXnxHhu56RUYiF+XAhkjcI9qIdQQYFgoAHQUCYrcZeQKe +AQKbDAUWAgMBAAQLCQgHBRUKCQgLAAoJECGtzzufM0n+vDoA/A3p3LMYSUcvELY9 +Af3nC6/471r5B3MDnURShddOtcRyAP96J1i5ExKnC+Ltw36/QtyxfyHp9Pr9Fw6B +X/zq4EFoCpyGBGK3GXkWCSsGAQQB2kcPAQEHQPlVJ9tosjkDY81zIKll52Gh00rh +hXY1jFExx248kkrj/gkDAjM3kLnAaUoVYFXrAVkSWsFeXVYLYtq0a49sc5q7Kz1K +KJmDBZKnvwgipPqf1eAkcZDSNanBZ2BO2K77Ix5FDFp67qc3XIZ6HUZqrP1siQmI +1QQYFgoAfQUCYrcZeQKeAQKbAgUWAgMBAAQLCQgHBRUKCQgLXyAEGRYKAAYFAmK3 +GXkACgkQnGOeWTe0K9zF6wEAh/nFBiBEV8N5CWvre6CU0Ky85cxrwE0vOA5tPaef +wusBAL6yqhbJwtEV0WqDb0Tg6OFl3eJG8VYOgh+zrt33LAEOAAoJECGtzzufM0n+ +NYcA/jOzaTUy1XZ45yNTN23xx8yyIdwPb24my/o7rbyCpV2qAP929vks8rEU+d+F +IY6KnSrZRKtsFkuC6kGOw25VW7YiAw== +=kvmL +-----END PGP PRIVATE KEY BLOCK----- \ No newline at end of file