diff --git a/sequoia-wot-vectors/src/test/kotlin/org/pgpainless/wot/query/AuthenticateTests.kt b/sequoia-wot-vectors/src/test/kotlin/org/pgpainless/wot/query/AuthenticateTests.kt new file mode 100644 index 00000000..763bbfa2 --- /dev/null +++ b/sequoia-wot-vectors/src/test/kotlin/org/pgpainless/wot/query/AuthenticateTests.kt @@ -0,0 +1,773 @@ +// SPDX-FileCopyrightText: 2023 Neal H. Walfield , Heiko Schaefer +// +// SPDX-License-Identifier: LGPL-2.0-or-later + +package org.pgpainless.wot.query + +import org.pgpainless.wot.network.* +import org.sequoia_pgp.wot.vectors.* +import java.time.Instant +import java.util.Date +import kotlin.RuntimeException +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * Tests for the authenticate function of the Web of Trust algorithm, as outlined in + * https://gitlab.com/sequoia-pgp/sequoia-wot/-/blob/main/spec/sequoia-wot.md + * + * These tests are ported from https://gitlab.com/sequoia-pgp/sequoia-wot/-/blob/main/src/lib.rs + * by Neal H. Walfield , licensed under LGPL-2.0-or-later. + */ +class AuthenticateTest { + + // Authenticates the target. + private fun sp(q: Query, + targetFpr: Fingerprint, + targetUserid: String, + expected: List>>, + minTrustAmount: Int?) { + + println("Authenticating: $targetFpr, $targetUserid"); + + val got = q.authenticate(targetFpr, targetUserid, (minTrustAmount ?: 120)) + + when (Pair(got.paths.isNotEmpty(), expected.isNotEmpty())) { + Pair(false, false) -> { + println("Can't authenticate == can't authenticate (good)"); + } + + Pair(false, true) -> { + throw RuntimeException("Couldn't authenticate. Expected paths: $expected") + } + + Pair(true, false) -> { + throw RuntimeException("Unexpectedly authenticated binding. Got: $got") + } + + Pair(true, true) -> { + println("Got paths: ${got.items}") + println("Expected: $expected") + + assertEquals(expected.size, got.paths.size, "Expected $expected paths, got ${got.paths} [${got.amount}]") + got.items.map { (path, amount) -> + Pair(amount, path.certificates.map { it.fingerprint }.toList()) + }.zip(expected).withIndex() + .forEach { (i, b) -> + val g = b.first + var e = b.second + + // Adjust test expectations: sequoia-wot returns 1-step paths for self-signed roots. + // We return a 2-step path. + if (e.second.size == 1) { + val list = e.second.toMutableList() + list.add(list[0]) + e = Pair(e.first, list.toList()) + } + + assertEquals(e, g, "got vs. expected path (#$i)") + assertEquals(e.first, g.first, "got vs. expected trust amount (#$i)") + } + + assertEquals(expected.sumOf { it.first }, got.amount) + } + } + + // NOTE: we're not checking the validity of the path on the OpenPGP layer + } + + private fun printNetwork(n: Network) { + println("Network contains " + n.nodes.size + " nodes with " + n.numberOfEdges + " edges built from " + + n.numberOfSignatures + " signatures.") + println(n) + } + + @Test + fun simple() { + val t = SimpleVectors() + val n = t.getNetworkAt() + + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(100, listOf(t.aliceFpr, t.bobFpr))), null) + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + sp(q1, t.daveFpr, t.daveUid, listOf(Pair(100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr))), null) + sp(q1, t.ellenFpr, t.ellenUid, listOf(), null) + sp(q1, t.frankFpr, t.frankUid, listOf(), null) + sp(q1, t.carolFpr, t.bobUid, listOf(), null) // No one authenticated Bob's User ID on Carol's key. + + val q2 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + + sp(q2, t.aliceFpr, t.aliceUid, listOf(), null) + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.bobFpr))), null) + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(100, listOf(t.bobFpr, t.carolFpr))), null) + sp(q2, t.daveFpr, t.daveUid, listOf(Pair(100, listOf(t.bobFpr, t.carolFpr, t.daveFpr))), null) + sp(q2, t.ellenFpr, t.ellenUid, listOf(), null) + sp(q2, t.frankFpr, t.frankUid, listOf(), null) + sp(q2, t.carolFpr, t.bobUid, listOf(), null) // No one authenticated Bob's User ID on Carol's key. + } + + @Test + fun cycle() { + val t = CycleVectors() + val n = t.getNetworkAt() + + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.aliceFpr, t.bobFpr))), null) + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + sp(q1, t.daveFpr, t.daveUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr))), null) + sp(q1, t.edFpr, t.edUid, listOf(Pair(30, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr))), null) + sp(q1, t.frankFpr, t.frankUid, listOf(), null) + + val q2 = Query(n, Roots(listOf(Root(t.aliceFpr), Root(t.daveFpr))), false) + + sp(q2, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + + // The following paths are identical and the sorting depends on the fingerprint. + // Thus, regenerating the keys could create a failure. + sp(q2, t.bobFpr, t.bobUid, + listOf(Pair(120, listOf(t.aliceFpr, t.bobFpr)), + Pair(120, listOf(t.daveFpr, t.bobFpr))), + 300) + + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + sp(q2, t.edFpr, t.edUid, listOf(Pair(30, listOf(t.daveFpr, t.edFpr))), null) + sp(q2, t.frankFpr, t.frankUid, listOf(Pair(30, listOf(t.daveFpr, t.edFpr, t.frankFpr))), null) + } + + @Test + fun cliques() { + val t1 = CliquesVectors() + val n1 = t1.getNetworkAt() + printNetwork(n1) + + val q1 = Query(n1, Roots(listOf(Root(t1.rootFpr))), false) + + // root -> a-0 -> a-1 -> b-0 -> ... -> f-0 -> target + sp(q1, t1.targetFpr, t1.targetUid, + listOf(Pair(120, listOf(t1.rootFpr, t1.a0Fpr, t1.a1Fpr, t1.b0Fpr, t1.b1Fpr, t1.c0Fpr, t1.c1Fpr, t1.d0Fpr, t1.d1Fpr, t1.e0Fpr, t1.f0Fpr, t1.targetFpr))), + null) + + val q2 = Query(n1, Roots(listOf(Root(t1.a1Fpr))), false) + + sp(q2, t1.targetFpr, t1.targetUid, + listOf(Pair(120, listOf(t1.a1Fpr, t1.b0Fpr, t1.b1Fpr, t1.c0Fpr, t1.c1Fpr, t1.d0Fpr, t1.d1Fpr, t1.e0Fpr, t1.f0Fpr, t1.targetFpr))), + null) + + val t2 = CliquesLocalOptimaVectors() + val n2 = t2.getNetworkAt() + printNetwork(n2) + + val q3 = Query(n2, Roots(listOf(Root(t2.rootFpr))), false) + + // root -> b-0 -> ... -> f-0 -> target + sp(q3, t2.targetFpr, t2.targetUid, + listOf(Pair(30, listOf(t2.rootFpr, t2.b0Fpr, t2.b1Fpr, t2.c0Fpr, t2.c1Fpr, t2.d0Fpr, t2.d1Fpr, t2.e0Fpr, t2.f0Fpr, t2.targetFpr)), + Pair(30, listOf(t2.rootFpr, t2.a1Fpr, t2.b0Fpr, t2.b1Fpr, t2.c0Fpr, t2.c1Fpr, t2.d0Fpr, t2.d1Fpr, t2.e0Fpr, t2.f0Fpr, t2.targetFpr)), + Pair(60, listOf(t2.rootFpr, t2.a0Fpr, t2.a1Fpr, t2.b0Fpr, t2.b1Fpr, t2.c0Fpr, t2.c1Fpr, t2.d0Fpr, t2.d1Fpr, t2.e0Fpr, t2.f0Fpr, t2.targetFpr))), + null) + + val q4 = Query(n2, Roots(listOf(Root(t2.a1Fpr))), false) + + sp(q4, t2.targetFpr, t2.targetUid, + listOf(Pair(120, listOf(t2.a1Fpr, t2.b0Fpr, t2.b1Fpr, t2.c0Fpr, t2.c1Fpr, t2.d0Fpr, t2.d1Fpr, t2.e0Fpr, t2.f0Fpr, t2.targetFpr))), + null) + + + val t3 = CliquesLocalOptima2Vectors() + val n3 = t3.getNetworkAt() + printNetwork(n3) + + val q5 = Query(n3, Roots(listOf(Root(t3.rootFpr))), false) + + // root -> b-0 -> ... -> f-0 -> target + sp(q5, t3.targetFpr, t3.targetUid, + listOf(Pair(30, listOf(t3.rootFpr, t3.b0Fpr, t3.b1Fpr, t3.c1Fpr, t3.d0Fpr, t3.d1Fpr, t3.e0Fpr, t3.f0Fpr, t3.targetFpr)), + Pair(30, listOf(t3.rootFpr, t3.a1Fpr, t3.b0Fpr, t3.b1Fpr, t3.c0Fpr, t3.c1Fpr, t3.d0Fpr, t3.d1Fpr, t3.e0Fpr, t3.f0Fpr, t3.targetFpr)), + Pair(60, listOf(t3.rootFpr, t3.a0Fpr, t3.a1Fpr, t3.b0Fpr, t3.b1Fpr, t3.c0Fpr, t3.c1Fpr, t3.d0Fpr, t3.d1Fpr, t3.e0Fpr, t3.f0Fpr, t3.targetFpr))), + null) + + val q6 = Query(n3, Roots(listOf(Root(t3.a1Fpr))), false) + + sp(q6, t3.targetFpr, t3.targetUid, + listOf(Pair(30, listOf(t3.a1Fpr, t3.b0Fpr, t3.b1Fpr, t3.c1Fpr, t3.d0Fpr, t3.d1Fpr, t3.e0Fpr, t3.f0Fpr, t3.targetFpr)), + Pair(90, listOf(t3.a1Fpr, t3.b0Fpr, t3.b1Fpr, t3.c0Fpr, t3.c1Fpr, t3.d0Fpr, t3.d1Fpr, t3.e0Fpr, t3.f0Fpr, t3.targetFpr))), + null) + } + + @Test + fun roundabout() { + val t = RoundaboutVectors() + val n = t.getNetworkAt() + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + + sp(q1, t.bobFpr, t.bobUid, + listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr)), + Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr, t.frankFpr, t.bobFpr)) + ), + null) + + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr))), null) + + sp(q1, t.daveFpr, t.daveUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr))), null) + + sp(q1, t.elmarFpr, t.elmarUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr))), null) + + sp(q1, t.frankFpr, t.frankUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr, t.frankFpr))), null) + + sp(q1, t.georgeFpr, t.georgeUid, + listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr)), + Pair(60, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr, + t.frankFpr, t.bobFpr, t.georgeFpr))), + null) + + sp(q1, t.henryFpr, t.henryUid, + listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr, t.henryFpr)), + Pair(60, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr, + t.frankFpr, t.bobFpr, t.georgeFpr, t.henryFpr))), + null) + + sp(q1, t.isaacFpr, t.isaacUid, + listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr, t.henryFpr, t.isaacFpr))), + null) + + sp(q1, t.jennyFpr, t.jennyUid, listOf(), null) + + + val q2 = Query(n, Roots(listOf(Root(t.jennyFpr))), false) + + sp(q2, t.aliceFpr, t.aliceUid, listOf(), null) + + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(100, listOf(t.jennyFpr, t.elmarFpr, t.frankFpr, t.bobFpr))), null) + + sp(q2, t.carolFpr, t.carolUid, listOf(), null) + + sp(q2, t.daveFpr, t.daveUid, listOf(), null) + + sp(q2, t.elmarFpr, t.elmarUid, listOf(Pair(100, listOf(t.jennyFpr, t.elmarFpr))), null) + + sp(q2, t.frankFpr, t.frankUid, listOf(Pair(100, listOf(t.jennyFpr, t.elmarFpr, t.frankFpr))), null) + + sp(q2, t.georgeFpr, t.georgeUid, + listOf(Pair(100, listOf(t.jennyFpr, t.georgeFpr)), + Pair(100, listOf(t.jennyFpr, t.elmarFpr, t.frankFpr, t.bobFpr, t.georgeFpr)) + ), null) + + sp(q2, t.henryFpr, t.henryUid, + listOf(Pair(100, listOf(t.jennyFpr, t.georgeFpr, t.henryFpr)), + Pair(20, listOf(t.jennyFpr, t.elmarFpr, t.frankFpr, t.bobFpr, t.georgeFpr, t.henryFpr)) + ), null) + + sp(q2, t.isaacFpr, t.isaacUid, listOf(), null) + + sp(q2, t.jennyFpr, t.jennyUid, listOf(Pair(120, listOf(t.jennyFpr))), null) + + + val q3 = Query(n, Roots(listOf(Root(t.aliceFpr), Root(t.jennyFpr))), false) + + sp(q3, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + + // In the first iteration of backwards_propagate, we find two paths: + // + // A -> B (60) + // J -> E -> F -> B (100) + // + // It doesn't find: + // + // A -> C -> D -> E -> F -> B (120) + // + // Query::authenticate chooses the path rooted at J, + // because it has more trust. Then we call + // backwards_propagate again and find: + // + // A -> B (60) + // + // Finally, we call backwards a third time and find: + // + // A -> C -> D -> E -> F -> B (120 -> 20) + sp(q3, t.bobFpr, t.bobUid, + listOf(Pair(100, listOf(t.jennyFpr, t.elmarFpr, t.frankFpr, t.bobFpr)), + Pair(60, listOf(t.aliceFpr, t.bobFpr)), + Pair(20, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr, t.frankFpr, t.bobFpr)) + ), 240) + + sp(q3, t.carolFpr, t.carolUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr))), null) + + sp(q3, t.daveFpr, t.daveUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr))), null) + + sp(q3, t.elmarFpr, t.elmarUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr))), null) + + sp(q3, t.frankFpr, t.frankUid, listOf(Pair(120, listOf(t.aliceFpr, t.carolFpr, t.daveFpr, t.elmarFpr, t.frankFpr))), 240); + + sp(q3, t.georgeFpr, t.georgeUid, + listOf( + Pair(100, listOf(t.jennyFpr, t.georgeFpr)), + Pair(100, listOf(t.jennyFpr, t.elmarFpr, t.frankFpr, t.bobFpr, t.georgeFpr)), + Pair(20, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr)), + ), 240) + + + // NOTE: original expectation from sequoia-wot: + // sp(q3, t.henryFpr, t.henryUid, + // listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr, t.henryFpr)), + // Pair(60, listOf(t.jennyFpr, t.georgeFpr, t.henryFpr)) + // ), null) + + // NOTE: Adjusted expectation for pgpainless. + // sequoia-wot searches for paths in a very specific way: + // backward_propagate() gets called twice in succession, from `authenticate()`, with two different search + // modes. The results get merged in a very specific way. In this test, that approach leads to a different + // distribution of trust amounts found for the two paths, which also happens to switch the ordering of the + // two paths. + // Note that the authentication result (the trust amount) remains unchanged, the total flow of 120 remains, + // it's just distributed differently between the two available paths. Both results are correct. + sp(q3, t.henryFpr, t.henryUid, + listOf(Pair(100, listOf(t.jennyFpr, t.georgeFpr, t.henryFpr)), + Pair(20, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr, t.henryFpr)) + ), null) + + + sp(q3, t.isaacFpr, t.isaacUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr, t.henryFpr, t.isaacFpr))), null) + + sp(q3, t.jennyFpr, t.jennyUid, listOf(Pair(120, listOf(t.jennyFpr))), null) + } + + @Test + fun localOptima() { + val t = LocalOptimaVectors() + val n = t.getNetworkAt() + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.aliceFpr, t.bobFpr))), null) + + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + + sp(q1, t.daveFpr, t.daveUid, listOf(Pair(50, listOf(t.aliceFpr, t.bobFpr, t.daveFpr))), null) + + sp(q1, t.ellenFpr, t.ellenUid, + listOf( + Pair(100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.ellenFpr)), + Pair(20, listOf(t.aliceFpr, t.bobFpr, t.daveFpr, t.ellenFpr)), + ), null) + + sp(q1, t.francisFpr, t.francisUid, + listOf( + Pair(75, listOf(t.aliceFpr, t.bobFpr, t.francisFpr)), + Pair(45, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.ellenFpr, t.francisFpr)), + ), null) + + sp(q1, t.georginaFpr, t.georginaUid, listOf(Pair(30, listOf(t.aliceFpr, t.bobFpr, t.daveFpr, t.ellenFpr, t.georginaFpr))), null) + + sp(q1, t.henryFpr, t.henryUid, + listOf( + Pair(100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.ellenFpr, t.henryFpr)), + Pair(20, listOf(t.aliceFpr, t.bobFpr, t.daveFpr, t.ellenFpr, t.henryFpr)), + ), null) + + + val q2 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + + sp(q2, t.aliceFpr, t.aliceUid, listOf(), null) + + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.bobFpr))), null) + + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(100, listOf(t.bobFpr, t.carolFpr))), null) + + sp(q2, t.daveFpr, t.daveUid, listOf(Pair(50, listOf(t.bobFpr, t.daveFpr))), null) + + sp(q2, t.ellenFpr, t.ellenUid, + listOf( + Pair(100, listOf(t.bobFpr, t.carolFpr, t.ellenFpr)), + Pair(50, listOf(t.bobFpr, t.daveFpr, t.ellenFpr)), + ), null) + + sp(q2, t.francisFpr, t.francisUid, + listOf( + Pair(75, listOf(t.bobFpr, t.francisFpr)), + Pair(100, listOf(t.bobFpr, t.carolFpr, t.ellenFpr, t.francisFpr)), + Pair(20, listOf(t.bobFpr, t.daveFpr, t.ellenFpr, t.francisFpr)), + ), 240) + } + + @Test + fun multipleUserids3() { + val t = MultipleUserIds3Vectors() + val n = t.getNetworkAt() + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + sp(q1, t.frankFpr, t.frankUid, + listOf( + Pair(20, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.frankFpr)), + Pair(10, listOf(t.aliceFpr, t.bobFpr, t.daveFpr, t.edFpr, t.frankFpr)), + ), null) + } + + @Test + fun certificationLiveness() { + val t = CertificationLivenessVectors() + + for ((i, time) in listOf(1580598000, 1583103600, 1585778400).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + val q = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + val amount = when (i + 1) { + 1 -> 60 + 2 -> 120 + 3 -> 60 + else -> throw RuntimeException("") + } + + sp(q, t.carolFpr, t.carolUid, listOf(Pair(amount, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + } + } + + @Test + fun certRevokedSoft() { + val t = CertRevokedSoftVectors() + + for ((i, time) in listOf(1580598000, 1583103600, 1585778400).withIndex()) { + // At t1, soft revocations are in the future, so certifications are still valid. + // + // At t2, B is soft-revoked, so existing certifications are still valid, but we can no longer + // authenticate B. + // + // At t3, A re-certifies B and B re-certifies D. These certifications should be ignored as they are made + // after B was revoked. + + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + // Consider just the code path where B is the issuer. + // + // Covers scenarios #1 at t1, #3 at t2 and t3 + val q1 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + sp(q1, t.daveFpr, t.daveUid, listOf(Pair(60, listOf(t.bobFpr, t.daveFpr))), null) + + + val q2 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + // Consider just the code path where B is the target. + // + // Covers scenarios #2 at t1, #4 at t2 and t3. + if (i + 1 == 1) { + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr))), null) + } else { + sp(q2, t.bobFpr, t.bobUid, listOf(), null) + } + + // Consider the code path where B is both an issuer and a target. + // + // Covers scenarios #1 & #2 at t1, #3 & #4 at t2 and t3. + sp(q2, t.daveFpr, t.daveUid, + listOf( + Pair(60, listOf(t.aliceFpr, t.bobFpr, t.daveFpr)), + Pair(30, listOf(t.aliceFpr, t.carolFpr, t.daveFpr)), + ), null) + } + + } + + @Test + fun certRevokedHard() { + val t = CertRevokedHardVectors() + + // At t1, B is hard revoked in the future so all certifications are invalid. + // + // At t2, B is hard revoked so all certifications are invalid. + // + // At t3, A re-certifies B and B re-certifies D. These certifications should also be ignored. + for ((i, time) in listOf(1580598000, 1583103600, 1585778400).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + // Consider just the code path where B is the issuer. + // + // Covers scenarios #5 at t1, #7 at t2 and t3 + val q1 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + sp(q1, t.daveFpr, t.daveUid, listOf(), null) + + val q2 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + // Consider just the code path where B is the target. + // + // Covers scenarios #6 at t1, #8 at t2 and t3. + sp(q2, t.bobFpr, t.bobUid, listOf(), null) + + // Consider the code path where B is both an issuer and a target. + // + // Covers scenarios #5 & #6 at t1, #7 & #8 at t2 and t3. + sp(q2, t.daveFpr, t.daveUid, listOf(Pair(30, listOf(t.aliceFpr, t.carolFpr, t.daveFpr))), null) + } + } + + @Test + fun certExpired() { + val t = CertExpiredVectors() + + for ((i, time) in listOf(1580598000, 1583103600, 1585778400).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + // Bob as target. + // (Once Bob has expired, it can be used as a trusted introducer for prior certifications, but + // bindings cannot be authenticated.) + if (i + 1 == 1) { + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr))), null) + } else { + sp(q1, t.bobFpr, t.bobUid, listOf(), null) + } + + // Bob in the middle. + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + + // Bob as root. + val q2 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(60, listOf(t.bobFpr, t.carolFpr))), null) + + // Bob's self signature. + if (i + 1 == 1) { + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.bobFpr))), null) + } else { + sp(q2, t.bobFpr, t.bobUid, listOf(), null) + } + } + } + + @Test + fun userIdRevoked() { + val t = UserIdRevokedVectors() + + // At t2, B is soft-revoked so all future certifications are invalid. + for ((i, time) in listOf(1580598000, 1583103600, 1585778400).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + // Revoked User ID on the root. + val q1 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + + if (i + 1 == 1) { + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.bobFpr))), null) + } else { + sp(q1, t.bobFpr, t.bobUid, listOf(), null) + } + + val q2 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + if (i + 1 == 1) { + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr))), null) + } else { + // Can't authenticate binding with a revoked User ID. + sp(q2, t.bobFpr, t.bobUid, listOf(), null) + } + + // Can use a delegation even if the certification that it is a part of has had its User ID revoked. + if (i + 1 < 3) { + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + } else { + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + } + } + } + + @Test + fun certificationsRevoked() { + val t = CertificationRevokedVectors() + + for ((i, time) in listOf(1580598000, 1583103600, 1585778400).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + // Revoked User ID on the root. + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + + when (i + 1) { + 1 -> { + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr))), null) + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + } + + 2 -> { + sp(q1, t.bobFpr, t.bobUid, listOf(), null) + sp(q1, t.carolFpr, t.carolUid, listOf(), null) + } + + 3 -> { + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.aliceFpr, t.bobFpr))), null) + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(120, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + } + + else -> throw RuntimeException() // unreachable + } + + // Alice, not Bob, revokes Bob's user id. So when Bob is the root, the self-signature should still be good. + val q2 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.bobFpr))), null) + } + } + + @Test + fun infinityAndBeyond() { + val t = InfinityAndBeyondVectors() + val n = t.getNetworkAt() + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.u1Fpr))), false) + + // This should always work. + sp(q1, t.u254Fpr, t.u254Uid, listOf(Pair(120, t.fprs.subList(0, 254))), null) + + // This tests that depth=255 really means infinity. + sp(q1, t.u260Fpr, t.u260Uid, listOf(Pair(120, t.fprs)), null) + } + + @Test + fun zeroTrust() { + val t = ZeroTrustVectors() + + // At t2, B is certified with a trust amount of 0. This should eliminate the path. + for ((i, time) in listOf(1580598000, 1583103600).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + if (i + 1 == 1) { + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(60, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + } else { + sp(q1, t.carolFpr, t.carolUid, listOf(), null) + } + + // Start with bob and make sure that a certification by a root with a 0 trust amount is also respected. + val q2 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + + if (i + 1 == 1) { + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(60, listOf(t.bobFpr, t.carolFpr))), null) + } else { + sp(q2, t.carolFpr, t.carolUid, listOf(), null) + } + } + } + + @Test + fun partiallyTrustedRoots() { + val t = SimpleVectors() + val n = t.getNetworkAt() + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr, 90))), false) + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(90, listOf(t.aliceFpr))), null) + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr))), null) + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + sp(q1, t.daveFpr, t.daveUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr))), null) + sp(q1, t.ellenFpr, t.ellenUid, listOf(), null) + sp(q1, t.frankFpr, t.frankUid, listOf(), null) + + // No one authenticated Bob's User ID on Carol's key. + sp(q1, t.carolFpr, t.bobUid, listOf(), null) + + // Multiple partially trusted roots. Check that together they can fully certify a self-signature. + val q2 = Query(n, Roots(listOf(Root(t.aliceFpr, 90), Root(t.bobFpr, 90))), false) + + sp(q2, t.aliceFpr, t.aliceUid, listOf(Pair(90, listOf(t.aliceFpr))), null) + + // NOTE: original expectation from sequoia-wot: + // sp(q2, t.bobFpr, t.bobUid, + // listOf(Pair(90, listOf(t.bobFpr)), + // Pair(90, listOf(t.aliceFpr, t.bobFpr))), null) + + // Our changed expectation: the order has changed because we return self-signed roots including the + // self-certification edge. + // This also happens to result in different ordering of the two paths, in this case. + sp(q2, t.bobFpr, t.bobUid, + listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr)), + Pair(90, listOf(t.bobFpr)) + ), null) + } + + @Test + fun selfSigned() { + val t = SelfSignedVectors() + val n = t.getNetworkAt() + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + sp(q1, t.bobFpr, t.bobUid, listOf(Pair(100, listOf(t.aliceFpr, t.bobFpr))), null) + sp(q1, t.carolFpr, t.carolUid, listOf(Pair(90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr))), null) + sp(q1, t.carolFpr, t.carolOtherOrgUid, listOf(), null) + sp(q1, t.daveFpr, t.daveUid, listOf(), null) + + val q2 = Query(n, Roots(listOf(Root(t.bobFpr))), false) + sp(q2, t.bobFpr, t.bobUid, listOf(Pair(120, listOf(t.bobFpr))), null) + sp(q2, t.carolFpr, t.carolUid, listOf(Pair(90, listOf(t.bobFpr, t.carolFpr))), null) + sp(q2, t.carolFpr, t.carolOtherOrgUid, listOf(Pair(90, listOf(t.bobFpr, t.carolFpr, t.carolFpr))), null) + sp(q2, t.daveFpr, t.daveUid, listOf(Pair(90, listOf(t.bobFpr, t.carolFpr, t.daveFpr))), null) + } + + @Test + fun isolatedRoot() { + val t = IsolatedRootVectors() + + for ((i, time) in listOf(1577919600, 1580598000).withIndex()) { + val date = Date(Instant.ofEpochSecond(time).toEpochMilli()) + println("Trying at #$i $date"); + + val n = t.getNetworkAt(ReferenceTime.timestamp(date)) + printNetwork(n) + + val q1 = Query(n, Roots(listOf(Root(t.aliceFpr))), false) + + if (i == 0) { + sp(q1, t.aliceFpr, t.aliceUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + } else { + sp(q1, t.aliceFpr, t.aliceUid, listOf(), null) + } + + sp(q1, t.aliceFpr, t.aliceOtherOrgUid, listOf(Pair(120, listOf(t.aliceFpr))), null) + } + } + +} \ No newline at end of file diff --git a/sequoia-wot-vectors/src/test/kotlin/org/pgpainless/wot/query/BackPropagateTest.kt b/sequoia-wot-vectors/src/test/kotlin/org/pgpainless/wot/query/BackPropagateTest.kt new file mode 100644 index 00000000..e00987e4 --- /dev/null +++ b/sequoia-wot-vectors/src/test/kotlin/org/pgpainless/wot/query/BackPropagateTest.kt @@ -0,0 +1,544 @@ +// SPDX-FileCopyrightText: 2023 Neal H. Walfield , Heiko Schaefer +// +// SPDX-License-Identifier: LGPL-2.0-or-later + +package org.pgpainless.wot.query + +import org.pgpainless.wot.network.Fingerprint +import org.pgpainless.wot.network.Root +import org.pgpainless.wot.network.Roots +import org.pgpainless.wot.query.Path +import org.sequoia_pgp.wot.vectors.* +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +internal const val DEPTH_UNCONSTRAINED = 255 + +/** + * Tests for the backward propagation function of the Web of Trust algorithm, as outlined in + * https://gitlab.com/sequoia-pgp/sequoia-wot/-/blob/main/spec/sequoia-wot.md + * + * These tests are ported from https://gitlab.com/sequoia-pgp/sequoia-wot/-/blob/main/src/backward_propagation.rs + * by Neal H. Walfield , licensed under LGPL-2.0-or-later. + */ +class BackPropagateTest { + + // Compares a computed path and a trust amount with the expected result. + private fun checkResult(result: Pair, residualDepth: Int, amount: Int, expectedPath: List) { + val (gotPath, gotAmount) = result; + val gotCerts: List = gotPath.certificates.map { it.fingerprint } + + assertEquals(expectedPath.size, gotCerts.size) + assert(gotCerts.zip(expectedPath).none { it.first != it.second }) // FIXME: debug output? + + println("got $gotPath") + println("expected $expectedPath") + + assertEquals(amount, gotAmount, "Trust amount mismatch") + assertEquals(residualDepth, gotPath.residualDepth.value(), "Residual depth mismatch") + + // NOTE: The Rust tests also check for validity of the path, but we're separating those concerns here. + // This package only deals with WoT calculations. + } + + @Test + fun simple() { + val t = SimpleVectors() + val n = t.getNetworkAt() + + println("Network contains " + n.nodes.size + " nodes with " + n.numberOfEdges + " edges built from " + n.numberOfSignatures + " signatures.") + println(n) + + val q = Query(n, Roots(), false) + + val a1 = q.backwardPropagate(t.ellenFpr, t.ellenUid) + checkResult(a1[t.daveFpr]!!, 1, 100, listOf(t.daveFpr, t.ellenFpr)); + checkResult(a1[t.carolFpr]!!, 0, 100, listOf(t.carolFpr, t.daveFpr, t.ellenFpr)); + + val a2 = q.backwardPropagate(t.daveFpr, t.daveUid); + assertNull(a2[t.ellenFpr]); + checkResult(a2[t.carolFpr]!!, 1, 100, listOf(t.carolFpr, t.daveFpr)); + checkResult(a2[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.carolFpr, t.daveFpr)); + checkResult(a2[t.aliceFpr]!!, 0, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr)); + + val a3 = q.backwardPropagate(t.daveFpr, t.daveUid); + assertNull(a3[t.ellenFpr]); + checkResult(a3[t.carolFpr]!!, 1, 100, listOf(t.carolFpr, t.daveFpr)); + checkResult(a3[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.carolFpr, t.daveFpr)); + + // This should work even though Bob is the root and the path is via Bob. + checkResult(a3[t.aliceFpr]!!, 0, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr)); + + val a4 = q.backwardPropagate(t.daveFpr, t.daveUid); + assertNull(a4[t.ellenFpr]) + checkResult(a4[t.carolFpr]!!, 1, 100, listOf(t.carolFpr, t.daveFpr)); + + // This should work even though Carol is the root is the path is via Carol. + checkResult(a4[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.carolFpr, t.daveFpr)); + checkResult(a4[t.aliceFpr]!!, 0, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr)); + + // Try to authenticate dave's key for a User ID that no one has certified. + val a5 = q.backwardPropagate(t.daveFpr, t.ellenUid); + assertNull(a5[t.ellenFpr]); + assertNull(a5[t.daveFpr]); + assertNull(a5[t.carolFpr]); + assertNull(a5[t.bobFpr]); + assertNull(a5[t.aliceFpr]); + + // A target that is not in the network. + val fpr = Fingerprint("0123456789ABCDEF0123456789ABCDEF01234567") + val a6 = q.backwardPropagate(fpr, t.ellenUid); + assertNull(a6[t.ellenFpr]); + assertNull(a6[t.daveFpr]); + assertNull(a6[t.carolFpr]); + assertNull(a6[t.bobFpr]); + assertNull(a6[t.aliceFpr]); + } + + @Test + fun cycle() { + val t = CycleVectors() + val n = t.getNetworkAt() + + println("Network contains " + n.nodes.size + " nodes with " + n.numberOfEdges + " edges built from " + n.numberOfSignatures + " signatures.") + println(n) + + val q = Query(n, Roots(), false) + + val a1 = q.backwardPropagate(t.frankFpr, t.frankUid); + checkResult(a1[t.edFpr]!!, 0, 120, listOf(t.edFpr, t.frankFpr)); + checkResult(a1[t.daveFpr]!!, 0, 30, listOf(t.daveFpr, t.edFpr, t.frankFpr)); + checkResult(a1[t.carolFpr]!!, 0, 30, listOf(t.carolFpr, t.daveFpr, t.edFpr, t.frankFpr)); + checkResult(a1[t.bobFpr]!!, 0, 30, listOf(t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr, t.frankFpr)); + assertNull(a1[t.aliceFpr]) + + val a2 = q.backwardPropagate(t.frankFpr, t.frankUid); + checkResult(a2[t.edFpr]!!, 0, 120, listOf(t.edFpr, t.frankFpr)); + checkResult(a2[t.daveFpr]!!, 0, 30, listOf(t.daveFpr, t.edFpr, t.frankFpr)); + checkResult(a2[t.carolFpr]!!, 0, 30, listOf(t.carolFpr, t.daveFpr, t.edFpr, t.frankFpr)); + checkResult(a2[t.bobFpr]!!, 0, 30, listOf(t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr, t.frankFpr)); + assertNull(a2[t.aliceFpr]) + + val a3 = q.backwardPropagate(t.edFpr, t.edUid); + assertNull(a3[t.frankFpr]) + checkResult(a3[t.daveFpr]!!, 1, 30, listOf(t.daveFpr, t.edFpr)); + checkResult(a3[t.carolFpr]!!, 1, 30, listOf(t.carolFpr, t.daveFpr, t.edFpr)); + checkResult(a3[t.bobFpr]!!, 1, 30, listOf(t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr)); + checkResult(a3[t.aliceFpr]!!, 0, 30, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr)); + + val a4 = q.backwardPropagate(t.carolFpr, t.carolUid); + assertNull(a4[t.frankFpr]); + assertNull(a4[t.edFpr]); + checkResult(a4[t.daveFpr]!!, DEPTH_UNCONSTRAINED, 90, listOf(t.daveFpr, t.bobFpr, t.carolFpr)); + checkResult(a4[t.bobFpr]!!, DEPTH_UNCONSTRAINED, 90, listOf(t.bobFpr, t.carolFpr)); + + // The backward propagation algorithm doesn't know that alice + // is not reachable from the root (dave). + checkResult(a4[t.aliceFpr]!!, 2, 90, listOf(t.aliceFpr, t.bobFpr, t.carolFpr)); + } + + @Test + fun cliques() { + val t1 = CliquesVectors() + val n1 = t1.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + val a1 = q1.backwardPropagate(t1.targetFpr, t1.targetUid); + + // root -> a-0 -> b-0 -> ... -> f-0 -> target + checkResult(a1[t1.rootFpr]!!, 90, 120, + listOf(t1.rootFpr, + t1.a0Fpr, + t1.a1Fpr, + t1.b0Fpr, + t1.b1Fpr, + t1.c0Fpr, + t1.c1Fpr, + t1.d0Fpr, + t1.d1Fpr, + t1.e0Fpr, + t1.f0Fpr, + t1.targetFpr)); + + val t2 = CliquesLocalOptimaVectors() + val n2 = t2.getNetworkAt() + + println("Network contains " + n2.nodes.size + " nodes with " + n2.numberOfEdges + " edges built from " + n2.numberOfSignatures + " signatures.") + println(n2) + + val q2 = Query(n2, Roots(), false) + val a2 = q2.backwardPropagate(t2.targetFpr, t2.targetUid); + + // root -> a-0 -> b-0 -> ... -> f-0 -> target + checkResult(a2[t2.rootFpr]!!, + 93, 30, + listOf(t2.rootFpr, + t2.b0Fpr, + t2.b1Fpr, + t2.c0Fpr, + t2.c1Fpr, + t2.d0Fpr, + t2.d1Fpr, + t2.e0Fpr, + t2.f0Fpr, + t2.targetFpr)); + + val t3 = CliquesLocalOptima2Vectors() + val n3 = t3.getNetworkAt() + + println("Network contains " + n3.nodes.size + " nodes with " + n3.numberOfEdges + " edges built from " + n3.numberOfSignatures + " signatures.") + println(n3) + + val q3 = Query(n3, Roots(), false) + val a3 = q3.backwardPropagate(t3.targetFpr, t3.targetUid); + + // root -> a-0 -> b-0 -> ... -> f-0 -> target + checkResult(a3[t3.rootFpr]!!, 94, 30, + listOf(t3.rootFpr, + t3.b0Fpr, + t3.b1Fpr, + t3.c1Fpr, + t3.d0Fpr, + t3.d1Fpr, + t3.e0Fpr, + t3.f0Fpr, + t3.targetFpr)); + } + + @Test + fun roundabout() { + val t = RoundaboutVectors() + val n = t.getNetworkAt() + + println("Network contains " + n.nodes.size + " nodes with " + n.numberOfEdges + " edges built from " + n.numberOfSignatures + " signatures.") + println(n) + + val q1 = Query(n, Roots(), false) + val a1 = q1.backwardPropagate(t.isaacFpr, t.isaacUid); + + checkResult(a1[t.aliceFpr]!!, 0, 60, listOf(t.aliceFpr, t.bobFpr, t.georgeFpr, t.henryFpr, t.isaacFpr)); + assertNull(a1[t.carolFpr]) + assertNull(a1[t.jennyFpr]) + + val a2 = q1.backwardPropagate(t.henryFpr, t.henryUid); + + // The backward propagation algorithm doesn't know that jenny + // is not reachable from the root (alice). + checkResult(a2[t.jennyFpr]!!, 0, 100, listOf(t.jennyFpr, t.georgeFpr, t.henryFpr)); + } + + @Test + fun localOptima() { + val t = LocalOptimaVectors() + val n = t.getNetworkAt() + + println("Network contains " + n.nodes.size + " nodes with " + n.numberOfEdges + " edges built from " + n.numberOfSignatures + " signatures.") + println(n) + + val q = Query(n, Roots(), false) + + val a1 = q.backwardPropagate(t.henryFpr, t.henryUid); + checkResult(a1[t.aliceFpr]!!, 0, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.ellenFpr, t.henryFpr)); + checkResult(a1[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.carolFpr, t.ellenFpr, t.henryFpr)); + checkResult(a1[t.carolFpr]!!, 0, 100, listOf(t.carolFpr, t.ellenFpr, t.henryFpr)); + checkResult(a1[t.daveFpr]!!, 0, 50, listOf(t.daveFpr, t.ellenFpr, t.henryFpr)); + checkResult(a1[t.ellenFpr]!!, 0, 120, listOf(t.ellenFpr, t.henryFpr)); + assertNull(a1[t.francisFpr]) + assertNull(a1[t.georginaFpr]) + + val a2 = q.backwardPropagate(t.francisFpr, t.francisUid); + + // Recall: given a choice, we prefer the forward pointer that has the least depth. + checkResult(a2[t.aliceFpr]!!, 149, 75, listOf(t.aliceFpr, t.bobFpr, t.francisFpr)); + checkResult(a2[t.bobFpr]!!, 200, 75, listOf(t.bobFpr, t.francisFpr)); + checkResult(a2[t.carolFpr]!!, 49, 100, listOf(t.carolFpr, t.ellenFpr, t.francisFpr)); + checkResult(a2[t.daveFpr]!!, 99, 50, listOf(t.daveFpr, t.ellenFpr, t.francisFpr)); + checkResult(a2[t.ellenFpr]!!, 100, 120, listOf(t.ellenFpr, t.francisFpr)); + assertNull(a2[t.georginaFpr]) + assertNull(a2[t.henryFpr]) + } + + @Test + fun bestViaRoot() { + val t = BestViaRootVectors() + val n = t.getNetworkAt() + + println("Network contains " + n.nodes.size + " nodes with " + n.numberOfEdges + " edges built from " + n.numberOfSignatures + " signatures.") + println(n) + + val q1 = Query(n, Roots(), false) + + val a1 = q1.backwardPropagate(t.targetFpr, t.targetUid); + + checkResult(a1[t.bobFpr]!!, 9, 120, listOf(t.bobFpr, t.carolFpr, t.targetFpr)); + checkResult(a1[t.carolFpr]!!, 10, 120, listOf(t.carolFpr, t.targetFpr)); + checkResult(a1[t.aliceFpr]!!, 8, 120, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.targetFpr)); + + val a2 = q1.backwardPropagate(t.targetFpr, t.targetUid); + + checkResult(a2[t.aliceFpr]!!, 8, 120, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.targetFpr)); + checkResult(a2[t.bobFpr]!!, 9, 120, listOf(t.bobFpr, t.carolFpr, t.targetFpr)); + checkResult(a2[t.carolFpr]!!, 10, 120, listOf(t.carolFpr, t.targetFpr)); + + + // Again, but this time we specify the roots. + val q2 = Query(n, Roots(listOf(Root(t.aliceFpr, 120))), false) + val a3 = q2.backwardPropagate(t.targetFpr, t.targetUid); + + checkResult(a3[t.aliceFpr]!!, 8, 120, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.targetFpr)); + + // As seen above, the best path from alice to the target is via bob. But when both alice and bob are both fully + // trusted roots, the returned path is not via bob, but one that is less optimal. + val q3 = Query(n, Roots(listOf(Root(t.aliceFpr), Root(t.bobFpr))), false) + val a4 = q3.backwardPropagate(t.targetFpr, t.targetUid); + + checkResult(a4[t.bobFpr]!!, 9, 120, listOf(t.bobFpr, t.carolFpr, t.targetFpr)); + checkResult(a4[t.aliceFpr]!!, 8, 50, listOf(t.aliceFpr, t.yellowFpr, t.zebraFpr, t.targetFpr)); + } + + @Test + fun regex1() { + val t = Regex1Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " t.edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + // alice as root. + val a1 = q1.backwardPropagate(t.bobFpr, t.bobUid); + checkResult(a1[t.aliceFpr]!!, 3, 100, listOf(t.aliceFpr, t.bobFpr)); + + val a2 = q1.backwardPropagate(t.carolFpr, t.carolUid); + checkResult(a2[t.aliceFpr]!!, 1, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr)); + + val a3 = q1.backwardPropagate(t.daveFpr, t.daveUid); + + // There is no path, because t.dave@example.org does not match the constraint on t.bob (domain: example.org). + assertNull(a3[t.aliceFpr]) + + val a4 = q1.backwardPropagate(t.edFpr, t.edUid) + + // There is no path, because t.ed@example.org does not match the constraint on t.dave (domain: other.org). + assertNull(a4[t.aliceFpr]) + + val a5 = q1.backwardPropagate(t.frankFpr, t.frankUid) + + // There is no path, because t.frank@other.org does not match the constraint on t.bob (domain: example.org). + assertNull(a5[t.aliceFpr]) + + + // bob as root. + val a6 = q1.backwardPropagate(t.carolFpr, t.carolUid) + checkResult(a6[t.bobFpr]!!, 1, 100, listOf(t.bobFpr, t.carolFpr)) + + val a7 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a7[t.bobFpr]!!, 1, 100, listOf(t.bobFpr, t.daveFpr)) + + val a8 = q1.backwardPropagate(t.edFpr, t.edUid) + // There is no path, because t.ed@example.org does not match the constraint on t.dave (domain: other.org). + assertNull(a8[t.bobFpr]) + + val a9 = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(a9[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.daveFpr, t.frankFpr)) + + // dave as root. + val a10 = q1.backwardPropagate(t.edFpr, t.edUid) + checkResult(a10[t.daveFpr]!!, 1, 100, listOf(t.daveFpr, t.edFpr)); + + val a11 = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(a11[t.daveFpr]!!, 1, 100, listOf(t.daveFpr, t.frankFpr)) + } + + @Test + fun regex2() { + val t = Regex2Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " t.edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + val a1 = q1.backwardPropagate(t.bobFpr, t.bobUid) + checkResult(a1[t.aliceFpr]!!, 7, 100, listOf(t.aliceFpr, t.bobFpr)) + + val a2 = q1.backwardPropagate(t.carolFpr, t.carolUid) + // There is no path, because carol@other.org does not match the constraint on carol (domain: example.org). + assertNull(a2[t.aliceFpr]) + + val a3 = q1.backwardPropagate(t.daveFpr, t.daveUid) + // There is no path, because dave@their.org does not match the constraint on carol (domain: example.org). + assertNull(a3[t.aliceFpr]) + + val a4 = q1.backwardPropagate(t.edFpr, t.edUid) + checkResult(a4[t.aliceFpr]!!, 4, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr)) + + val a5 = q1.backwardPropagate(t.carolFpr, t.carolUid); + // There is no path, because carol@other.org does not match + // the constraint on carol (domain: example.org). + assertNull(a5[t.bobFpr]) + + val a6 = q1.backwardPropagate(t.daveFpr, t.daveUid) + // There is no path, because dave@their.org does not match the constraint on carol (domain: example.org). + assertNull(a6[t.bobFpr]) + + val a7 = q1.backwardPropagate(t.edFpr, t.edUid) + checkResult(a7[t.bobFpr]!!, 5, 100, listOf(t.bobFpr, t.carolFpr, t.daveFpr, t.edFpr)) + + val a8 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a8[t.carolFpr]!!, 7, 100, listOf(t.carolFpr, t.daveFpr)); + + val a9 = q1.backwardPropagate(t.edFpr, t.edUid) + checkResult(a9[t.carolFpr]!!, 6, 100, listOf(t.carolFpr, t.daveFpr, t.edFpr)) + } + + @Test + fun regex3() { + val t = Regex3Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " t.edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + // alice as root. + val a1 = q1.backwardPropagate(t.bobFpr, t.bobUid) + checkResult(a1[t.aliceFpr]!!, 3, 100, listOf(t.aliceFpr, t.bobFpr)) + + val a2 = q1.backwardPropagate(t.carolFpr, t.carolUid) + checkResult(a2[t.aliceFpr]!!, 1, 100, listOf(t.aliceFpr, t.bobFpr, t.carolFpr)) + + val a3 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a3[t.aliceFpr]!!, 1, 100, listOf(t.aliceFpr, t.bobFpr, t.daveFpr)) + + val a4 = q1.backwardPropagate(t.edFpr, t.edUid) + // There is no path, because ed@example.org does not match the constraint on dave (domain: other.org). + assertNull(a4[t.aliceFpr]) + + val a5 = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(a5[t.aliceFpr]!!, 0, 100, listOf(t.aliceFpr, t.bobFpr, t.daveFpr, t.frankFpr)) + + val a6 = q1.backwardPropagate(t.georgeFpr, t.georgeUid) + assertNull(a6[t.aliceFpr]) + + val a7 = q1.backwardPropagate(t.henryFpr, t.henryUid) + assertNull(a7[t.aliceFpr]) + + + // bob as root. + val a8 = q1.backwardPropagate(t.carolFpr, t.carolUid) + checkResult(a8[t.bobFpr]!!, 1, 100, listOf(t.bobFpr, t.carolFpr)) + + val a9 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a9[t.bobFpr]!!, 1, 100, listOf(t.bobFpr, t.daveFpr)) + + val a10 = q1.backwardPropagate(t.edFpr, t.edUid) + // There is no path, because ed@example.org does not match the constraint on dave (domain: other.org). + assertNull(a10[t.bobFpr]) + + val a11 = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(a11[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.daveFpr, t.frankFpr)) + + val a12 = q1.backwardPropagate(t.georgeFpr, t.georgeUid) + checkResult(a12[t.bobFpr]!!, 0, 100, listOf(t.bobFpr, t.daveFpr, t.georgeFpr)) + + val a13 = q1.backwardPropagate(t.henryFpr, t.henryUid) + checkResult(a13[t.bobFpr]!!, 1, 100, listOf(t.bobFpr, t.henryFpr)) + + + // dave as root. + val a14 = q1.backwardPropagate(t.edFpr, t.edUid) + checkResult(a14[t.daveFpr]!!, 1, 100, listOf(t.daveFpr, t.edFpr)) + + val a15 = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(a15[t.daveFpr]!!, 1, 100, listOf(t.daveFpr, t.frankFpr)) + + val a16 = q1.backwardPropagate(t.georgeFpr, t.georgeUid) + checkResult(a16[t.daveFpr]!!, 1, 100, listOf(t.daveFpr, t.georgeFpr)) + } + + @Test + fun multipleUserids1() { + val t = MultipleUserIds1Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " t.edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + val a1 = q1.backwardPropagate(t.carolFpr, t.carolUid) + checkResult(a1[t.aliceFpr]!!, 0, 70, listOf(t.aliceFpr, t.bobFpr, t.carolFpr)) + + val a2 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a2[t.aliceFpr]!!, 0, 50, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr)) + } + + @Test + fun multipleUserids2() { + val t = MultipleUserIds2Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " t.edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + + val a1 = q1.backwardPropagate(t.bobFpr, t.bobUid) + checkResult(a1[t.aliceFpr]!!, DEPTH_UNCONSTRAINED, 70, listOf(t.aliceFpr, t.bobFpr)) + + val a2 = q1.backwardPropagate(t.bobFpr, t.bobSomeOrgUid) + checkResult(a2[t.aliceFpr]!!, 1, 50, listOf(t.aliceFpr, t.bobFpr)) + + val a3 = q1.backwardPropagate(t.carolFpr, t.carolUid) + checkResult(a3[t.aliceFpr]!!, 0, 50, listOf(t.aliceFpr, t.bobFpr, t.carolFpr)) + + val a4 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a4[t.aliceFpr]!!, 0, 70, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr)) + + val a5 = q1.backwardPropagate(t.edFpr, t.edUid) + assertNull(a5[t.aliceFpr]) + + val a6 = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(a6[t.aliceFpr]!!, 0, 70, listOf(t.aliceFpr, t.bobFpr, t.frankFpr)) + } + + @Test + fun multipleUserids3() { + val t = MultipleUserIds3Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + val auth = q1.backwardPropagate(t.frankFpr, t.frankUid) + checkResult(auth[t.aliceFpr]!!, 0, 20, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.frankFpr)) + } + + @Test + fun multipleCertifications1() { + val t = MultipleCertifications1Vectors() + val n1 = t.getNetworkAt() + + println("Network contains " + n1.nodes.size + " nodes with " + n1.numberOfEdges + " edges built from " + n1.numberOfSignatures + " signatures.") + println(n1) + + val q1 = Query(n1, Roots(), false) + + val a1 = q1.backwardPropagate(t.carolFpr, t.carolUid) + checkResult(a1[t.aliceFpr]!!, 0, 70, listOf(t.aliceFpr, t.bobFpr, t.carolFpr)) + + val a2 = q1.backwardPropagate(t.daveFpr, t.daveUid) + checkResult(a2[t.aliceFpr]!!, 0, 50, listOf(t.aliceFpr, t.bobFpr, t.carolFpr, t.daveFpr)) + } +} \ No newline at end of file diff --git a/sequoia-wot-vectors/src/test/kotlin/org/sequoia_pgp/wot/suite/BestViaRoot.kt b/sequoia-wot-vectors/src/test/kotlin/org/sequoia_pgp/wot/suite/BestViaRoot.kt index 1b008585..91ad984d 100644 --- a/sequoia-wot-vectors/src/test/kotlin/org/sequoia_pgp/wot/suite/BestViaRoot.kt +++ b/sequoia-wot-vectors/src/test/kotlin/org/sequoia_pgp/wot/suite/BestViaRoot.kt @@ -33,7 +33,7 @@ class BestViaRoot : TestCase(BestViaRootVectors()) { val keyRing = tempKeyRingFile.absolutePath val v = vectors as BestViaRootVectors val p = Runtime.getRuntime().exec( - "$executable --keyring=$keyRing -r ${v.alice_fpr} --full authenticate ${v.target_fpr} ${v.target_uid}", + "$executable --keyring=$keyRing -r ${v.aliceFpr} --full authenticate ${v.targetFpr} ${v.targetUid}", env) val output = p.inputStream.let { val bOut = ByteArrayOutputStream() diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/ArtifactVectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/ArtifactVectors.kt index b06792d9..93a5d749 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/ArtifactVectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/ArtifactVectors.kt @@ -38,7 +38,7 @@ interface ArtifactVectors { fun getResourceName(): String - fun getNetworkAt(referenceTime: ReferenceTime, policy: Policy = PGPainless.getPolicy()): Network { + fun getNetworkAt(referenceTime: ReferenceTime = ReferenceTime.now(), policy: Policy = PGPainless.getPolicy()): Network { val inputStream = keyRingInputStream() val keyRing = PGPainless.readKeyRing().publicKeyRingCollection(inputStream) val store = KeyRingCertificateStore(keyRing) diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/BestViaRootVectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/BestViaRootVectors.kt index 11f80e48..0ed9db8d 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/BestViaRootVectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/BestViaRootVectors.kt @@ -26,28 +26,28 @@ import org.pgpainless.wot.network.Fingerprint */ class BestViaRootVectors: ArtifactVectors { - val alice_fpr = Fingerprint("B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB") - val alice_uid = "" + val aliceFpr = Fingerprint("B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB") + val aliceUid = "" - val bob_fpr = Fingerprint("6A8B9EC7D0A1B297B5D4A7A1C048DFF96601D9BD") - val bob_uid = "" + val bobFpr = Fingerprint("6A8B9EC7D0A1B297B5D4A7A1C048DFF96601D9BD") + val bobUid = "" // Certified by: B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB - val carol_fpr = Fingerprint("77A6F7D4BEE0369F70B249579D2987669F792B35") - val carol_uid = "" + val carolFpr = Fingerprint("77A6F7D4BEE0369F70B249579D2987669F792B35") + val carolUid = "" // Certified by: 6A8B9EC7D0A1B297B5D4A7A1C048DFF96601D9BD - val target_fpr = Fingerprint("2AB08C06FC795AC26673B23CAD561ABDCBEBFDF0") - val target_uid = "" + val targetFpr = Fingerprint("2AB08C06FC795AC26673B23CAD561ABDCBEBFDF0") + val targetUid = "" // Certified by: 77A6F7D4BEE0369F70B249579D2987669F792B35 // Certified by: 56D44411F982758169E4681B402E8D5D9D7D6567 - val yellow_fpr = Fingerprint("86CB4639D1FE096BA941D05822B8AF50198C49DD") - val yellow_uid = "" + val yellowFpr = Fingerprint("86CB4639D1FE096BA941D05822B8AF50198C49DD") + val yellowUid = "" // Certified by: B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB - val zebra_fpr = Fingerprint("56D44411F982758169E4681B402E8D5D9D7D6567") - val zebra_uid = "" + val zebraFpr = Fingerprint("56D44411F982758169E4681B402E8D5D9D7D6567") + val zebraUid = "" // Certified by: 86CB4639D1FE096BA941D05822B8AF50198C49DD /** diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/IsolatedRootVectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/IsolatedRootVectors.kt index 7b5677da..5c4bf3e5 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/IsolatedRootVectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/IsolatedRootVectors.kt @@ -16,7 +16,7 @@ class IsolatedRootVectors: ArtifactVectors { val aliceFpr = Fingerprint("DCF3020AAB76ECC7F0E5AC0D375DCE1BEE264B87") val aliceUid = "" - val aliceOtherOrguid = "" + val aliceOtherOrgUid = "" /** * A is created. diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleCertifications1Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleCertifications1Vectors.kt index 723a80f5..0540c499 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleCertifications1Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleCertifications1Vectors.kt @@ -26,21 +26,21 @@ import org.pgpainless.wot.network.Fingerprint */ class MultipleCertifications1Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("9219941467AA737C6EC1207959A2CEFC112C359A") - val alice_uid = "" + val aliceFpr = Fingerprint("9219941467AA737C6EC1207959A2CEFC112C359A") + val aliceUid = "" - val bob_fpr = Fingerprint("72CAA0F0A4A020F5FA20CD8CB5CC04473AA88123") - val bob_uid = "" + val bobFpr = Fingerprint("72CAA0F0A4A020F5FA20CD8CB5CC04473AA88123") + val bobUid = "" // Certified by: 9219941467AA737C6EC1207959A2CEFC112C359A // Certified by: 9219941467AA737C6EC1207959A2CEFC112C359A // Certified by: 9219941467AA737C6EC1207959A2CEFC112C359A - val carol_fpr = Fingerprint("853304031E7B0B116BBD0B398734F11945313904") - val carol_uid = "" + val carolFpr = Fingerprint("853304031E7B0B116BBD0B398734F11945313904") + val carolUid = "" // Certified by: 72CAA0F0A4A020F5FA20CD8CB5CC04473AA88123 - val dave_fpr = Fingerprint("4C77ABDBE4F855E0C3C7A7D549F6B2BFDA83E424") - val dave_uid = "" + val daveFpr = Fingerprint("4C77ABDBE4F855E0C3C7A7D549F6B2BFDA83E424") + val daveUid = "" // Certified by: 853304031E7B0B116BBD0B398734F11945313904 /** diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds1Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds1Vectors.kt index 45757a09..32f6fdfe 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds1Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds1Vectors.kt @@ -38,21 +38,21 @@ import org.pgpainless.wot.network.Fingerprint */ class MultipleUserIds1Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA") - val alice_uid = "" + val aliceFpr = Fingerprint("2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA") + val aliceUid = "" - val bob_fpr = Fingerprint("03182611B91B1E7E20B848E83DFC151ABFAD85D5") - val bob_uid = "" + val bobFpr = Fingerprint("03182611B91B1E7E20B848E83DFC151ABFAD85D5") + val bobUid = "" // Certified by: 2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA - val bob_some_org_uid = "" + val bob_some_orgUid = "" // Certified by: 2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA - val carol_fpr = Fingerprint("9CA36907B46FE7B6B9EE9601E78064C12B6D7902") - val carol_uid = "" + val carolFpr = Fingerprint("9CA36907B46FE7B6B9EE9601E78064C12B6D7902") + val carolUid = "" // Certified by: 03182611B91B1E7E20B848E83DFC151ABFAD85D5 - val dave_fpr = Fingerprint("C1BC6794A6C6281B968A6A41ACE2055D610CEA03") - val dave_uid = "" + val daveFpr = Fingerprint("C1BC6794A6C6281B968A6A41ACE2055D610CEA03") + val daveUid = "" // Certified by: 9CA36907B46FE7B6B9EE9601E78064C12B6D7902 override fun getResourceName(): String { diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds2Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds2Vectors.kt index a1f10489..a3204b45 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds2Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds2Vectors.kt @@ -29,29 +29,29 @@ import org.pgpainless.wot.network.Fingerprint */ class MultipleUserIds2Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("F1C99C4019837703DD17C45440F8A0141DF278EA") - val alice_uid = "" + val aliceFpr = Fingerprint("F1C99C4019837703DD17C45440F8A0141DF278EA") + val aliceUid = "" - val bob_fpr = Fingerprint("5528B9E5DAFC519ED2E37F0377B332E4111456CB") - val bob_uid = "" + val bobFpr = Fingerprint("5528B9E5DAFC519ED2E37F0377B332E4111456CB") + val bobUid = "" // Certified by: F1C99C4019837703DD17C45440F8A0141DF278EA - val bob_some_org_uid = "" + val bobSomeOrgUid = "" // Certified by: F1C99C4019837703DD17C45440F8A0141DF278EA - val carol_fpr = Fingerprint("6F8291428420AB53576BAB4BEFF6477D3E348D71") - val carol_uid = "" + val carolFpr = Fingerprint("6F8291428420AB53576BAB4BEFF6477D3E348D71") + val carolUid = "" // Certified by: 5528B9E5DAFC519ED2E37F0377B332E4111456CB - val dave_fpr = Fingerprint("62C57D90DAD253DEA01D5A86C7382FD6285C18F0") - val dave_uid = "" + val daveFpr = Fingerprint("62C57D90DAD253DEA01D5A86C7382FD6285C18F0") + val daveUid = "" // Certified by: 6F8291428420AB53576BAB4BEFF6477D3E348D71 - val ed_fpr = Fingerprint("0E974D0ACBA0C4D8F51D7CF68F048FF83B173504") - val ed_uid = "" + val edFpr = Fingerprint("0E974D0ACBA0C4D8F51D7CF68F048FF83B173504") + val edUid = "" // Certified by: 6F8291428420AB53576BAB4BEFF6477D3E348D71 - val frank_fpr = Fingerprint("5BEE3D41F85B2FCBC300DE4E18CB2BDA65465F03") - val frank_uid = "" + val frankFpr = Fingerprint("5BEE3D41F85B2FCBC300DE4E18CB2BDA65465F03") + val frankUid = "" // Certified by: 5528B9E5DAFC519ED2E37F0377B332E4111456CB override fun getResourceName(): String { diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds3Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds3Vectors.kt index 51f47ec1..ad6ac4f1 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds3Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/MultipleUserIds3Vectors.kt @@ -28,30 +28,30 @@ import org.pgpainless.wot.network.Fingerprint */ class MultipleUserIds3Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("DA3CFC60BD4B8835702A66782C7A431946C12DF7") - val alice_uid = "" + val aliceFpr = Fingerprint("DA3CFC60BD4B8835702A66782C7A431946C12DF7") + val aliceUid = "" - val bob_fpr = Fingerprint("28C108707090FCDFF630D1E141FB02F0E397D55E") - val bob_uid = "" + val bobFpr = Fingerprint("28C108707090FCDFF630D1E141FB02F0E397D55E") + val bobUid = "" // Certified by: DA3CFC60BD4B8835702A66782C7A431946C12DF7 - val bob_some_org_uid = "" + val bobSomeOrgUid = "" // Certified by: DA3CFC60BD4B8835702A66782C7A431946C12DF7 - val bob_third_org_uid = "" + val bobThirdOrgUid = "" - val carol_fpr = Fingerprint("9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8") - val carol_uid = "" + val carolFpr = Fingerprint("9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8") + val carolUid = "" // Certified by: 28C108707090FCDFF630D1E141FB02F0E397D55E - val dave_fpr = Fingerprint("0C131F8959F45D08B6136FDAAD2E16A26F73D48E") - val dave_uid = "" + val daveFpr = Fingerprint("0C131F8959F45D08B6136FDAAD2E16A26F73D48E") + val daveUid = "" // Certified by: 28C108707090FCDFF630D1E141FB02F0E397D55E - val ed_fpr = Fingerprint("296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB") - val ed_uid = "" + val edFpr = Fingerprint("296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB") + val edUid = "" // Certified by: 0C131F8959F45D08B6136FDAAD2E16A26F73D48E - val frank_fpr = Fingerprint("A72AA1B7D9D8CB04D988F1520A404E37A7766608") - val frank_uid = "" + val frankFpr = Fingerprint("A72AA1B7D9D8CB04D988F1520A404E37A7766608") + val frankUid = "" // Certified by: 9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8 // Certified by: 296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex1Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex1Vectors.kt index d3b0dd82..4d94ecdf 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex1Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex1Vectors.kt @@ -27,27 +27,27 @@ import org.pgpainless.wot.network.Fingerprint */ class Regex1Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("3AD1F297E4B150F75DBFC43476FB81BFE0665C3A") - val alice_uid = "" + val aliceFpr = Fingerprint("3AD1F297E4B150F75DBFC43476FB81BFE0665C3A") + val aliceUid = "" - val bob_fpr = Fingerprint("20C812117FB2A3940EAE9160FEE6B4E47A096FD1") - val bob_uid = "" + val bobFpr = Fingerprint("20C812117FB2A3940EAE9160FEE6B4E47A096FD1") + val bobUid = "" // Certified by: 3AD1F297E4B150F75DBFC43476FB81BFE0665C3A - val carol_fpr = Fingerprint("BC30978345D789CADECDE492F54B42E1625E1A1D") - val carol_uid = "" + val carolFpr = Fingerprint("BC30978345D789CADECDE492F54B42E1625E1A1D") + val carolUid = "" // Certified by: 20C812117FB2A3940EAE9160FEE6B4E47A096FD1 - val dave_fpr = Fingerprint("319810FAD46CBE96DAD7F1F5B014902592999B21") - val dave_uid = "" + val daveFpr = Fingerprint("319810FAD46CBE96DAD7F1F5B014902592999B21") + val daveUid = "" // Certified by: 20C812117FB2A3940EAE9160FEE6B4E47A096FD1 - val ed_fpr = Fingerprint("23D7418EA0C6A42A54C32DBE8D4FE4911ED08467") - val ed_uid = "" + val edFpr = Fingerprint("23D7418EA0C6A42A54C32DBE8D4FE4911ED08467") + val edUid = "" // Certified by: 319810FAD46CBE96DAD7F1F5B014902592999B21 - val frank_fpr = Fingerprint("7FAE20D68EE87F74368AF275A0C40E741FC1C50F") - val frank_uid = "" + val frankFpr = Fingerprint("7FAE20D68EE87F74368AF275A0C40E741FC1C50F") + val frankUid = "" // Certified by: 319810FAD46CBE96DAD7F1F5B014902592999B21 override fun getResourceName(): String { diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex2Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex2Vectors.kt index 9388fded..737534e7 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex2Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex2Vectors.kt @@ -23,23 +23,23 @@ import org.pgpainless.wot.network.Fingerprint */ class Regex2Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("5C396C920399898461F17CB747FDBF3EB3453919") - val alice_uid = "" + val aliceFpr = Fingerprint("5C396C920399898461F17CB747FDBF3EB3453919") + val aliceUid = "" - val bob_fpr = Fingerprint("584D195AD89CE0354D2CCBAEBCDD9EBC09692780") - val bob_uid = "" + val bobFpr = Fingerprint("584D195AD89CE0354D2CCBAEBCDD9EBC09692780") + val bobUid = "" // Certified by: 5C396C920399898461F17CB747FDBF3EB3453919 - val carol_fpr = Fingerprint("FC7A96D4810D0CF477031956AED58C644370C183") - val carol_uid = "" + val carolFpr = Fingerprint("FC7A96D4810D0CF477031956AED58C644370C183") + val carolUid = "" // Certified by: 584D195AD89CE0354D2CCBAEBCDD9EBC09692780 - val dave_fpr = Fingerprint("58077E659732526C1B8BF9837EFC0EDE07B506A8") - val dave_uid = "" + val daveFpr = Fingerprint("58077E659732526C1B8BF9837EFC0EDE07B506A8") + val daveUid = "" // Certified by: FC7A96D4810D0CF477031956AED58C644370C183 - val ed_fpr = Fingerprint("36089C49F18BF6FC6BCA35E3BB85877766C009E4") - val ed_uid = "" + val edFpr = Fingerprint("36089C49F18BF6FC6BCA35E3BB85877766C009E4") + val edUid = "" // Certified by: 58077E659732526C1B8BF9837EFC0EDE07B506A8 override fun getResourceName(): String { diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex3Vectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex3Vectors.kt index 7428d838..a70f82e2 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex3Vectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/Regex3Vectors.kt @@ -22,35 +22,35 @@ import org.pgpainless.wot.network.Fingerprint */ class Regex3Vectors: ArtifactVectors { - val alice_fpr = Fingerprint("D8CFEBBA006E2ED57CF45CC413F0BAE09D94FE4E") - val alice_uid = "" + val aliceFpr = Fingerprint("D8CFEBBA006E2ED57CF45CC413F0BAE09D94FE4E") + val aliceUid = "" - val bob_fpr = Fingerprint("A75DC1A1EDA5282F3A7381B51824E46BBCC801F0") - val bob_uid = "" + val bobFpr = Fingerprint("A75DC1A1EDA5282F3A7381B51824E46BBCC801F0") + val bobUid = "" // Certified by: D8CFEBBA006E2ED57CF45CC413F0BAE09D94FE4E - val carol_fpr = Fingerprint("4BCD4325BDACA452F0301227A30CB4BCC329E769") - val carol_uid = "" + val carolFpr = Fingerprint("4BCD4325BDACA452F0301227A30CB4BCC329E769") + val carolUid = "" // Certified by: A75DC1A1EDA5282F3A7381B51824E46BBCC801F0 - val dave_fpr = Fingerprint("2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380") - val dave_uid = "" + val daveFpr = Fingerprint("2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380") + val daveUid = "" // Certified by: A75DC1A1EDA5282F3A7381B51824E46BBCC801F0 - val ed_fpr = Fingerprint("F645D081F480BE26C7D2C84D941B3E2CE53FAF16") - val ed_uid = "" + val edFpr = Fingerprint("F645D081F480BE26C7D2C84D941B3E2CE53FAF16") + val edUid = "" // Certified by: 2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380 - val frank_fpr = Fingerprint("AFAB11F1A37FD20C85CF8093F4941D1A0EC5749F") - val frank_uid = "" + val frankFpr = Fingerprint("AFAB11F1A37FD20C85CF8093F4941D1A0EC5749F") + val frankUid = "" // Certified by: 2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380 - val george_fpr = Fingerprint("D01C8752D9BA9F3F5F06B21F394E911938D6DB0A") - val george_uid = "" + val georgeFpr = Fingerprint("D01C8752D9BA9F3F5F06B21F394E911938D6DB0A") + val georgeUid = "" // Certified by: 2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380 - val henry_fpr = Fingerprint("B99A8696FD820192CEEE285D3A253E49F1D97109") - val henry_uid = "" + val henryFpr = Fingerprint("B99A8696FD820192CEEE285D3A253E49F1D97109") + val henryUid = "" // Certified by: A75DC1A1EDA5282F3A7381B51824E46BBCC801F0 override fun getResourceName(): String { diff --git a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/SelfSignedVectors.kt b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/SelfSignedVectors.kt index 0f1d1142..e526d5d4 100644 --- a/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/SelfSignedVectors.kt +++ b/sequoia-wot-vectors/src/testFixtures/kotlin/org/sequoia_pgp/wot/vectors/SelfSignedVectors.kt @@ -34,7 +34,7 @@ class SelfSignedVectors: ArtifactVectors { val carolFpr = Fingerprint("830230061426EE99A0455E6ADA869CF879A5630D") val carolUid = "" // Certified by: 7A7B5DE6C8F464CAB78BEFB9CE14BEE51D4DEC01 - val carol_other_orgUid = "" + val carolOtherOrgUid = "" val daveFpr = Fingerprint("51A5E15F87AC6ECAFBEA930FA5F30AF6EB6EF14A") val daveUid = ""