mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 04:17:59 +01:00
It clicked for me; Simplified edge/reverseEdge finding
This commit is contained in:
parent
d284e3407f
commit
d163a2b0a6
6 changed files with 250 additions and 60 deletions
|
@ -152,9 +152,6 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
// Target -> Issuer, Signatures on the target
|
// Target -> Issuer, Signatures on the target
|
||||||
private final Map<OpenPgpFingerprint, List<CertificationSet>> reverseEdges = new HashMap<>();
|
private final Map<OpenPgpFingerprint, List<CertificationSet>> reverseEdges = new HashMap<>();
|
||||||
|
|
||||||
// TODO: Get rid of this
|
|
||||||
Map<OpenPgpFingerprint, Map<OpenPgpFingerprint, List<Certification>>> certifications = new HashMap<>();
|
|
||||||
|
|
||||||
private final Iterable<KeyRingInfo> validatedCertificates;
|
private final Iterable<KeyRingInfo> validatedCertificates;
|
||||||
private final Policy policy;
|
private final Policy policy;
|
||||||
private final ReferenceTime referenceTime;
|
private final ReferenceTime referenceTime;
|
||||||
|
@ -167,8 +164,7 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
this.referenceTime = referenceTime;
|
this.referenceTime = referenceTime;
|
||||||
|
|
||||||
synopsizeCertificates();
|
synopsizeCertificates();
|
||||||
processSignaturesOnCertificates();
|
findEdges();
|
||||||
identifyEdges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void synopsizeCertificates() {
|
private void synopsizeCertificates() {
|
||||||
|
@ -204,15 +200,15 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
new HashSet<>(cert.getValidUserIds())));
|
new HashSet<>(cert.getValidUserIds())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSignaturesOnCertificates() {
|
private void findEdges() {
|
||||||
// Identify certifications and delegations
|
// Identify certifications and delegations
|
||||||
// Target = cert carrying a signature
|
// Target = cert carrying a signature
|
||||||
for (KeyRingInfo validatedTarget : validatedCertificates) {
|
for (KeyRingInfo validatedTarget : validatedCertificates) {
|
||||||
processSigsOnCert(validatedTarget);
|
findEdgesWithTarget(validatedTarget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSigsOnCert(KeyRingInfo validatedTarget) {
|
private void findEdgesWithTarget(KeyRingInfo validatedTarget) {
|
||||||
PGPPublicKeyRing validatedTargetKeyRing = KeyRingUtils.publicKeys(validatedTarget.getKeys());
|
PGPPublicKeyRing validatedTargetKeyRing = KeyRingUtils.publicKeys(validatedTarget.getKeys());
|
||||||
OpenPgpFingerprint targetFingerprint = OpenPgpFingerprint.of(validatedTargetKeyRing);
|
OpenPgpFingerprint targetFingerprint = OpenPgpFingerprint.of(validatedTargetKeyRing);
|
||||||
PGPPublicKey targetPrimaryKey = validatedTargetKeyRing.getPublicKey();
|
PGPPublicKey targetPrimaryKey = validatedTargetKeyRing.getPublicKey();
|
||||||
|
@ -221,7 +217,7 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
// Direct-Key Signatures (delegations) by X on Y
|
// Direct-Key Signatures (delegations) by X on Y
|
||||||
List<PGPSignature> delegations = SignatureUtils.getDelegations(validatedTargetKeyRing);
|
List<PGPSignature> delegations = SignatureUtils.getDelegations(validatedTargetKeyRing);
|
||||||
for (PGPSignature delegation : delegations) {
|
for (PGPSignature delegation : delegations) {
|
||||||
indexAndVerifyDelegation(targetPrimaryKey, target, delegation);
|
processDelegation(targetPrimaryKey, target, delegation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certification Signatures by X on Y over user-ID U
|
// Certification Signatures by X on Y over user-ID U
|
||||||
|
@ -229,38 +225,38 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
while (userIds.hasNext()) {
|
while (userIds.hasNext()) {
|
||||||
String userId = userIds.next();
|
String userId = userIds.next();
|
||||||
List<PGPSignature> userIdSigs = SignatureUtils.get3rdPartyCertificationsFor(userId, validatedTargetKeyRing);
|
List<PGPSignature> userIdSigs = SignatureUtils.get3rdPartyCertificationsFor(userId, validatedTargetKeyRing);
|
||||||
indexAndVerifyCertifications(targetPrimaryKey, target, userId, userIdSigs);
|
processCertification(targetPrimaryKey, target, userId, userIdSigs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void indexAndVerifyDelegation(PGPPublicKey targetPrimaryKey, CertSynopsis target, PGPSignature delegation) {
|
private void processDelegation(PGPPublicKey targetPrimaryKey,
|
||||||
|
CertSynopsis target,
|
||||||
|
PGPSignature delegation) {
|
||||||
List<KeyRingInfo> issuerCandidates = byKeyId.get(delegation.getKeyID());
|
List<KeyRingInfo> issuerCandidates = byKeyId.get(delegation.getKeyID());
|
||||||
if (issuerCandidates == null) {
|
if (issuerCandidates == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (KeyRingInfo candidate : issuerCandidates) {
|
for (KeyRingInfo candidate : issuerCandidates) {
|
||||||
|
|
||||||
PGPPublicKeyRing issuerKeyRing = KeyRingUtils.publicKeys(candidate.getKeys());
|
PGPPublicKeyRing issuerKeyRing = KeyRingUtils.publicKeys(candidate.getKeys());
|
||||||
OpenPgpFingerprint issuerFingerprint = OpenPgpFingerprint.of(issuerKeyRing);
|
OpenPgpFingerprint issuerFingerprint = OpenPgpFingerprint.of(issuerKeyRing);
|
||||||
PGPPublicKey issuerSigningKey = issuerKeyRing.getPublicKey(delegation.getKeyID());
|
PGPPublicKey issuerSigningKey = issuerKeyRing.getPublicKey(delegation.getKeyID());
|
||||||
CertSynopsis issuer = certSynopsisMap.get(issuerFingerprint);
|
CertSynopsis issuer = certSynopsisMap.get(issuerFingerprint);
|
||||||
boolean valid = false;
|
|
||||||
try {
|
try {
|
||||||
valid = SignatureVerifier.verifyDirectKeySignature(delegation, issuerSigningKey, targetPrimaryKey, policy, referenceTime.getTimestamp());
|
boolean valid = SignatureVerifier.verifyDirectKeySignature(delegation, issuerSigningKey,
|
||||||
|
targetPrimaryKey, policy, referenceTime.getTimestamp());
|
||||||
|
if (valid) {
|
||||||
|
indexEdge(new Certification(issuer, Optional.empty(), target, delegation));
|
||||||
|
}
|
||||||
} catch (SignatureValidationException e) {
|
} catch (SignatureValidationException e) {
|
||||||
LOGGER.warn("Cannot verify signature by " + issuerFingerprint + " on cert of " + OpenPgpFingerprint.of(targetPrimaryKey), e);
|
LOGGER.warn("Cannot verify signature by " + issuerFingerprint + " on cert of " + OpenPgpFingerprint.of(targetPrimaryKey), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
Map<OpenPgpFingerprint, List<Certification>> sigsBy = getOrDefault(certifications, issuerFingerprint, HashMap::new);
|
|
||||||
List<Certification> targetSigs = getOrDefault(sigsBy, target.getFingerprint(), ArrayList::new);
|
|
||||||
targetSigs.add(new Certification(issuer, Optional.empty(), target, delegation));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void indexAndVerifyCertifications(PGPPublicKey targetPrimaryKey, CertSynopsis target, String userId, List<PGPSignature> userIdSigs) {
|
private void processCertification(PGPPublicKey targetPrimaryKey,
|
||||||
|
CertSynopsis target,
|
||||||
|
String userId, List<PGPSignature> userIdSigs) {
|
||||||
for (PGPSignature certification : userIdSigs) {
|
for (PGPSignature certification : userIdSigs) {
|
||||||
List<KeyRingInfo> issuerCandidates = byKeyId.get(certification.getKeyID());
|
List<KeyRingInfo> issuerCandidates = byKeyId.get(certification.getKeyID());
|
||||||
if (issuerCandidates == null) {
|
if (issuerCandidates == null) {
|
||||||
|
@ -274,12 +270,10 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
CertSynopsis issuer = certSynopsisMap.get(issuerFingerprint);
|
CertSynopsis issuer = certSynopsisMap.get(issuerFingerprint);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boolean valid = SignatureVerifier.verifySignatureOverUserId(userId, certification, issuerSigningKey, targetPrimaryKey, policy, referenceTime.getTimestamp());
|
boolean valid = SignatureVerifier.verifySignatureOverUserId(userId, certification,
|
||||||
|
issuerSigningKey, targetPrimaryKey, policy, referenceTime.getTimestamp());
|
||||||
if (valid) {
|
if (valid) {
|
||||||
Map<OpenPgpFingerprint, List<Certification>> sigsBy = getOrDefault(certifications, issuerFingerprint, HashMap::new);
|
indexEdge(new Certification(issuer, Optional.just(userId), target, certification));
|
||||||
List<Certification> targetSigs = getOrDefault(sigsBy, target.getFingerprint(), ArrayList::new);
|
|
||||||
targetSigs.add(new Certification(issuer, Optional.just(userId), target, certification));
|
|
||||||
}
|
}
|
||||||
} catch (SignatureValidationException e) {
|
} catch (SignatureValidationException e) {
|
||||||
LOGGER.warn("Cannot verify signature for '" + userId + "' by " + issuerFingerprint + " on cert of " + target.getFingerprint(), e);
|
LOGGER.warn("Cannot verify signature for '" + userId + "' by " + issuerFingerprint + " on cert of " + target.getFingerprint(), e);
|
||||||
|
@ -288,28 +282,37 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void identifyEdges() {
|
private void indexEdge(Certification certification) {
|
||||||
// Re-order data structure
|
OpenPgpFingerprint issuer = certification.getIssuer().getFingerprint();
|
||||||
for (OpenPgpFingerprint issuerFp : certifications.keySet()) {
|
OpenPgpFingerprint target = certification.getTarget().getFingerprint();
|
||||||
Map<OpenPgpFingerprint, List<Certification>> issuedBy = certifications.get(issuerFp);
|
|
||||||
|
|
||||||
// one issuer can issue many edges
|
List<CertificationSet> outEdges = getOrDefault(edges, issuer, ArrayList::new);
|
||||||
List<CertificationSet> outEdges = new ArrayList<>();
|
indexOutEdge(outEdges, certification);
|
||||||
for (OpenPgpFingerprint targetFp : issuedBy.keySet()) {
|
|
||||||
|
|
||||||
List<Certification> onCert = issuedBy.get(targetFp);
|
List<CertificationSet> inEdges = getOrDefault(reverseEdges, target, ArrayList::new);
|
||||||
CertificationSet edgeSigs = CertificationSet.empty(certSynopsisMap.get(issuerFp), certSynopsisMap.get(targetFp));
|
indexInEdge(inEdges, certification);
|
||||||
for (Certification certification : onCert) {
|
}
|
||||||
edgeSigs.add(certification);
|
|
||||||
}
|
|
||||||
outEdges.add(edgeSigs);
|
|
||||||
|
|
||||||
List<CertificationSet> reverseEdge = getOrDefault(reverseEdges, targetFp, ArrayList::new);
|
|
||||||
reverseEdge.add(edgeSigs);
|
|
||||||
|
|
||||||
|
private void indexOutEdge(List<CertificationSet> outEdges, Certification certification) {
|
||||||
|
OpenPgpFingerprint target = certification.getTarget().getFingerprint();
|
||||||
|
for (CertificationSet outEdge : outEdges) {
|
||||||
|
if (target.equals(outEdge.getTarget().getFingerprint())) {
|
||||||
|
outEdge.add(certification);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
edges.put(issuerFp, outEdges);
|
|
||||||
}
|
}
|
||||||
|
outEdges.add(CertificationSet.fromCertification(certification));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void indexInEdge(List<CertificationSet> inEdges, Certification certification) {
|
||||||
|
OpenPgpFingerprint issuer = certification.getIssuer().getFingerprint();
|
||||||
|
for (CertificationSet inEdge : inEdges) {
|
||||||
|
if (issuer.equals(inEdge.getIssuer().getFingerprint())) {
|
||||||
|
inEdge.add(certification);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inEdges.add(CertificationSet.fromCertification(certification));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -322,6 +325,10 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Network getNetwork() {
|
||||||
|
return network;
|
||||||
|
}
|
||||||
|
|
||||||
// Map signature to its revocation state
|
// Map signature to its revocation state
|
||||||
private static RevocationState revocationStateFromSignature(PGPSignature revocation) {
|
private static RevocationState revocationStateFromSignature(PGPSignature revocation) {
|
||||||
if (revocation == null) {
|
if (revocation == null) {
|
||||||
|
|
|
@ -10,6 +10,8 @@ import pgp.certificate_store.exception.BadDataException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import pgp.certificate_store.certificate.Certificate;
|
import pgp.certificate_store.certificate.Certificate;
|
||||||
|
|
||||||
public class WebOfTrustCertificateStore extends PGPCertificateDirectory {
|
public class WebOfTrustCertificateStore extends PGPCertificateDirectory {
|
||||||
|
@ -20,7 +22,15 @@ public class WebOfTrustCertificateStore extends PGPCertificateDirectory {
|
||||||
|
|
||||||
public Iterator<Certificate> getAllItems()
|
public Iterator<Certificate> getAllItems()
|
||||||
throws BadDataException, IOException {
|
throws BadDataException, IOException {
|
||||||
Iterator<Certificate> trustRootAndCerts = new PrefixedIterator<>(getTrustRootCertificate(), items());
|
Certificate trustRoot;
|
||||||
|
try {
|
||||||
|
trustRoot = getTrustRootCertificate();
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
// ignore
|
||||||
|
trustRoot = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Certificate> trustRootAndCerts = new PrefixedIterator<>(trustRoot, items());
|
||||||
return trustRootAndCerts;
|
return trustRootAndCerts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,148 @@
|
||||||
|
|
||||||
package org.pgpainless.wot;
|
package org.pgpainless.wot;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import org.pgpainless.wot.testfixtures.TestCertificateStores;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import pgp.certificate_store.exception.BadDataException;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.CertificationSet;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.Network;
|
||||||
|
import org.pgpainless.wot.testfixtures.TestCertificateStores;
|
||||||
|
import org.pgpainless.wot.testfixtures.WotTestVectors;
|
||||||
|
import pgp.certificate_store.exception.BadDataException;
|
||||||
|
|
||||||
public class WebOfTrustTest {
|
public class WebOfTrustTest {
|
||||||
|
|
||||||
|
OpenPgpFingerprint fooBankCa = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshFooBankCaCert());
|
||||||
|
OpenPgpFingerprint fooBankEmployee = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshFooBankEmployeeCert());
|
||||||
|
OpenPgpFingerprint fooBankAdmin = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshFooBankAdminCert());
|
||||||
|
OpenPgpFingerprint barBankCa = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshBarBankCaCert());
|
||||||
|
OpenPgpFingerprint barBankEmployee = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshBarBankEmployeeCert());
|
||||||
|
|
||||||
|
public WebOfTrustTest() throws IOException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithTwoNodesAndOneDelegation() throws BadDataException, IOException, InterruptedException {
|
||||||
|
WebOfTrustCertificateStore store = TestCertificateStores.oneDelegationGraph();
|
||||||
|
WebOfTrust wot = new WebOfTrust(store);
|
||||||
|
wot.initialize();
|
||||||
|
Network network = wot.getNetwork();
|
||||||
|
|
||||||
|
assertEquals(2, network.getNodes().size());
|
||||||
|
|
||||||
|
assertHasEdge(network, fooBankAdmin, barBankCa);
|
||||||
|
assertHasReverseEdge(network, fooBankAdmin, barBankCa);
|
||||||
|
|
||||||
|
assertHasNoEdge(network, barBankCa, fooBankAdmin);
|
||||||
|
assertHasNoReverseEdge(network, barBankCa, fooBankAdmin);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithCrossSignedCertificates()
|
public void testWithCrossSignedCertificates()
|
||||||
throws BadDataException, IOException, InterruptedException {
|
throws BadDataException, IOException, InterruptedException {
|
||||||
WebOfTrustCertificateStore store = TestCertificateStores.disconnectedGraph();
|
WebOfTrustCertificateStore store = TestCertificateStores.disconnectedGraph();
|
||||||
WebOfTrust wot = new WebOfTrust(store);
|
WebOfTrust wot = new WebOfTrust(store);
|
||||||
wot.initialize();
|
wot.initialize();
|
||||||
|
Network network = wot.getNetwork();
|
||||||
|
|
||||||
|
assertEquals(5, network.getNodes().size());
|
||||||
|
assertTrue(network.getNodes().containsKey(fooBankCa));
|
||||||
|
assertTrue(network.getNodes().containsKey(fooBankEmployee));
|
||||||
|
assertTrue(network.getNodes().containsKey(fooBankAdmin));
|
||||||
|
assertTrue(network.getNodes().containsKey(barBankCa));
|
||||||
|
assertTrue(network.getNodes().containsKey(barBankEmployee));
|
||||||
|
|
||||||
|
// Exemplary edge
|
||||||
|
List<CertificationSet> fooBankCaEdges = network.getEdges().get(fooBankCa);
|
||||||
|
assertEquals(2, fooBankCaEdges.size());
|
||||||
|
|
||||||
|
CertificationSet fbc2fbe = getEdgeFromTo(network, fooBankCa, fooBankEmployee);
|
||||||
|
assertNotNull(fbc2fbe);
|
||||||
|
CertificationSet fbc2fba = getEdgeFromTo(network, fooBankCa, fooBankAdmin);
|
||||||
|
assertNotNull(fbc2fba);
|
||||||
|
|
||||||
|
assertHasIssuerAndTarget(fbc2fba, fooBankCa, fooBankAdmin);
|
||||||
|
assertHasIssuerAndTarget(fbc2fbe, fooBankCa, fooBankEmployee);
|
||||||
|
|
||||||
|
assertHasEdge(network, barBankCa, barBankEmployee);
|
||||||
|
assertHasReverseEdge(network, barBankCa, barBankEmployee);
|
||||||
|
|
||||||
|
assertHasNoEdge(network, fooBankCa, barBankCa);
|
||||||
|
assertHasNoReverseEdge(network, fooBankCa, barBankCa);
|
||||||
|
|
||||||
// CHECKSTYLE:OFF
|
// CHECKSTYLE:OFF
|
||||||
System.out.println(wot);
|
System.out.println(wot);
|
||||||
// CHECKSTYLE:ON
|
// CHECKSTYLE:ON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertHasIssuerAndTarget(CertificationSet certifications, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
assertEquals(issuer, certifications.getIssuer().getFingerprint());
|
||||||
|
assertEquals(target, certifications.getTarget().getFingerprint());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertHasEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
assertNotNull(getEdgeFromTo(network, issuer, target), "Expected edge from " + issuer + " to " + target + " but got none.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertHasReverseEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
assertNotNull(getReverseEdgeFromTo(network, issuer, target), "Expected reverse edge to " + target + " from " + issuer + " but got none.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertHasNoEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
CertificationSet edge = getEdgeFromTo(network, issuer, target);
|
||||||
|
assertNull(edge, "Expected no edge from " + issuer + " to " + target + " but got " + edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertHasNoReverseEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
CertificationSet reverseEdge = getReverseEdgeFromTo(network, issuer, target);
|
||||||
|
assertNull(reverseEdge, "Expected no reverse edge on " + target + " from " + issuer + " but got " + reverseEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CertificationSet getEdgeFromTo(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
List<CertificationSet> edges = network.getEdges().get(issuer);
|
||||||
|
if (edges == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CertificationSet certifications : edges) {
|
||||||
|
if (target.equals(certifications.getTarget().getFingerprint())) {
|
||||||
|
return certifications;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CertificationSet getReverseEdgeFromTo(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
|
||||||
|
List<CertificationSet> revEdges = network.getReverseEdges().get(target);
|
||||||
|
if (revEdges == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CertificationSet certifications : revEdges) {
|
||||||
|
if (issuer.equals(certifications.getIssuer().getFingerprint())) {
|
||||||
|
return certifications;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWotCreationOfEmptyCertificates() throws BadDataException, IOException {
|
||||||
|
WebOfTrustCertificateStore store = TestCertificateStores.emptyGraph();
|
||||||
|
WebOfTrust wot = new WebOfTrust(store);
|
||||||
|
wot.initialize();
|
||||||
|
Network network = wot.getNetwork();
|
||||||
|
|
||||||
|
assertTrue(network.getNodes().isEmpty());
|
||||||
|
assertTrue(network.getEdges().isEmpty());
|
||||||
|
assertTrue(network.getReverseEdges().isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,20 +28,9 @@ public class TestCertificateStores {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static InputStream requireResource(String resourceName) {
|
|
||||||
InputStream inputStream = TestCertificateStores.class.getClassLoader().getResourceAsStream(resourceName);
|
|
||||||
if (inputStream == null) {
|
|
||||||
throw new TestAbortedException("Cannot read resource " + resourceName + ": InputStream is null.");
|
|
||||||
}
|
|
||||||
return inputStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WebOfTrustCertificateStore disconnectedGraph()
|
public static WebOfTrustCertificateStore disconnectedGraph()
|
||||||
throws BadDataException, IOException, InterruptedException {
|
throws BadDataException, IOException, InterruptedException {
|
||||||
SubkeyLookup subkeyLookup = new InMemorySubkeyLookup();
|
WebOfTrustCertificateStore wotStore = createInMemoryStore();
|
||||||
KeyMaterialReaderBackend readerBackend = new KeyMaterialReader();
|
|
||||||
PGPCertificateDirectory.Backend backend = new InMemoryCertificateDirectoryBackend(readerBackend);
|
|
||||||
WebOfTrustCertificateStore wotStore = new WebOfTrustCertificateStore(backend, subkeyLookup);
|
|
||||||
|
|
||||||
wotStore.insertTrustRoot(getTestVector("cross_signed/foobankCaCert.asc"), merger);
|
wotStore.insertTrustRoot(getTestVector("cross_signed/foobankCaCert.asc"), merger);
|
||||||
wotStore.insert(getTestVector("cross_signed/foobankEmployeeCert.asc"), merger);
|
wotStore.insert(getTestVector("cross_signed/foobankEmployeeCert.asc"), merger);
|
||||||
|
@ -52,6 +41,37 @@ public class TestCertificateStores {
|
||||||
return wotStore;
|
return wotStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static WebOfTrustCertificateStore emptyGraph() {
|
||||||
|
WebOfTrustCertificateStore wotStore = createInMemoryStore();
|
||||||
|
|
||||||
|
return wotStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebOfTrustCertificateStore oneDelegationGraph() throws BadDataException, IOException, InterruptedException {
|
||||||
|
WebOfTrustCertificateStore wotStore = createInMemoryStore();
|
||||||
|
wotStore.insert(getTestVector("cross_signed/foobankAdminCert.asc"), merger);
|
||||||
|
wotStore.insert(getTestVector("cross_signed/barbankCaCert.asc"), merger);
|
||||||
|
|
||||||
|
return wotStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WebOfTrustCertificateStore createInMemoryStore() {
|
||||||
|
SubkeyLookup subkeyLookup = new InMemorySubkeyLookup();
|
||||||
|
KeyMaterialReaderBackend readerBackend = new KeyMaterialReader();
|
||||||
|
PGPCertificateDirectory.Backend backend = new InMemoryCertificateDirectoryBackend(readerBackend);
|
||||||
|
WebOfTrustCertificateStore wotStore = new WebOfTrustCertificateStore(backend, subkeyLookup);
|
||||||
|
|
||||||
|
return wotStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream requireResource(String resourceName) {
|
||||||
|
InputStream inputStream = TestCertificateStores.class.getClassLoader().getResourceAsStream(resourceName);
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new TestAbortedException("Cannot read resource " + resourceName + ": InputStream is null.");
|
||||||
|
}
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
private static InputStream getTestVector(String testVectorName) {
|
private static InputStream getTestVector(String testVectorName) {
|
||||||
return requireResource("test_vectors/" + testVectorName);
|
return requireResource("test_vectors/" + testVectorName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,12 @@ public final class CertificationSet {
|
||||||
return new CertificationSet(issuer, target, new HashMap<>());
|
return new CertificationSet(issuer, target, new HashMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CertificationSet fromCertification(Certification certification) {
|
||||||
|
CertificationSet set = CertificationSet.empty(certification.getIssuer(), certification.getTarget());
|
||||||
|
set.add(certification);
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link CertificationSet} from a single certification.
|
* Create a {@link CertificationSet} from a single certification.
|
||||||
*
|
*
|
||||||
|
@ -67,6 +73,23 @@ public final class CertificationSet {
|
||||||
this.certifications = new HashMap<>(certifications);
|
this.certifications = new HashMap<>(certifications);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CertSynopsis getIssuer() {
|
||||||
|
return issuer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CertSynopsis getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Optional<String>, List<Certification>> getCertifications() {
|
||||||
|
// Copy to avoid side effects
|
||||||
|
Map<Optional<String>, List<Certification>> copy = new HashMap<>();
|
||||||
|
for (Optional<String> key : certifications.keySet()) {
|
||||||
|
copy.put(key, new ArrayList<>(certifications.get(key)));
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge this {@link CertificationSet} with another instance.
|
* Merge this {@link CertificationSet} with another instance.
|
||||||
* After the operation, this will contain {@link Certification Certifications} from both sets.
|
* After the operation, this will contain {@link Certification Certifications} from both sets.
|
||||||
|
|
|
@ -102,7 +102,12 @@ public class Network {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder("Network with " + getNodes().size() + " nodes, " + getEdges().size() + " edges:\n");
|
int edgeNum = 0;
|
||||||
|
for (List<CertificationSet> edgesFrom : edges.values()) {
|
||||||
|
edgeNum += edgesFrom.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder("Network with " + getNodes().size() + " nodes, " + edgeNum + " edges:\n");
|
||||||
for (OpenPgpFingerprint issuer : getNodes().keySet()) {
|
for (OpenPgpFingerprint issuer : getNodes().keySet()) {
|
||||||
for (CertificationSet edge : getReverseEdges().get(issuer)) {
|
for (CertificationSet edge : getReverseEdges().get(issuer)) {
|
||||||
sb.append(edge);
|
sb.append(edge);
|
||||||
|
|
Loading…
Reference in a new issue