1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-16 16:44:50 +02:00

Merge remote-tracking branch 'hkos/heiko/tests' into wot

This commit is contained in:
Paul Schaub 2023-07-17 13:30:05 +02:00
commit ae8cf33a9e
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
14 changed files with 1415 additions and 98 deletions

View file

@ -0,0 +1,773 @@
// SPDX-FileCopyrightText: 2023 Neal H. Walfield <neal@pep.foundation>, Heiko Schaefer <heiko@schaefer.name>
//
// 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 <neal@pep.foundation>, licensed under LGPL-2.0-or-later.
*/
class AuthenticateTest {
// Authenticates the target.
private fun sp(q: Query,
targetFpr: Fingerprint,
targetUserid: String,
expected: List<Pair<Int, List<Fingerprint>>>,
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<Long>(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<Long>(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<Long>(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<Long>(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<Long>(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<Long>(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<Long>(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<Long>(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)
}
}
}

View file

@ -0,0 +1,544 @@
// SPDX-FileCopyrightText: 2023 Neal H. Walfield <neal@pep.foundation>, Heiko Schaefer <heiko@schaefer.name>
//
// 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 <neal@pep.foundation>, 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<Path, Int>, residualDepth: Int, amount: Int, expectedPath: List<Fingerprint>) {
val (gotPath, gotAmount) = result;
val gotCerts: List<Fingerprint> = 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))
}
}

View file

@ -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()

View file

@ -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)

View file

@ -26,28 +26,28 @@ import org.pgpainless.wot.network.Fingerprint
*/
class BestViaRootVectors: ArtifactVectors {
val alice_fpr = Fingerprint("B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB")
val alice_uid = "<alice@example.org>"
val aliceFpr = Fingerprint("B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB")
val aliceUid = "<alice@example.org>"
val bob_fpr = Fingerprint("6A8B9EC7D0A1B297B5D4A7A1C048DFF96601D9BD")
val bob_uid = "<bob@example.org>"
val bobFpr = Fingerprint("6A8B9EC7D0A1B297B5D4A7A1C048DFF96601D9BD")
val bobUid = "<bob@example.org>"
// Certified by: B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB
val carol_fpr = Fingerprint("77A6F7D4BEE0369F70B249579D2987669F792B35")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("77A6F7D4BEE0369F70B249579D2987669F792B35")
val carolUid = "<carol@example.org>"
// Certified by: 6A8B9EC7D0A1B297B5D4A7A1C048DFF96601D9BD
val target_fpr = Fingerprint("2AB08C06FC795AC26673B23CAD561ABDCBEBFDF0")
val target_uid = "<target@example.org>"
val targetFpr = Fingerprint("2AB08C06FC795AC26673B23CAD561ABDCBEBFDF0")
val targetUid = "<target@example.org>"
// Certified by: 77A6F7D4BEE0369F70B249579D2987669F792B35
// Certified by: 56D44411F982758169E4681B402E8D5D9D7D6567
val yellow_fpr = Fingerprint("86CB4639D1FE096BA941D05822B8AF50198C49DD")
val yellow_uid = "<yellow@example.org>"
val yellowFpr = Fingerprint("86CB4639D1FE096BA941D05822B8AF50198C49DD")
val yellowUid = "<yellow@example.org>"
// Certified by: B95FF5B1D055D26F758FD4E3BF12C4D1D28FDFFB
val zebra_fpr = Fingerprint("56D44411F982758169E4681B402E8D5D9D7D6567")
val zebra_uid = "<zebra@example.org>"
val zebraFpr = Fingerprint("56D44411F982758169E4681B402E8D5D9D7D6567")
val zebraUid = "<zebra@example.org>"
// Certified by: 86CB4639D1FE096BA941D05822B8AF50198C49DD
/**

View file

@ -16,7 +16,7 @@ class IsolatedRootVectors: ArtifactVectors {
val aliceFpr = Fingerprint("DCF3020AAB76ECC7F0E5AC0D375DCE1BEE264B87")
val aliceUid = "<alice@example.org>"
val aliceOtherOrguid = "<alice@other.org>"
val aliceOtherOrgUid = "<alice@other.org>"
/**
* A is created.

View file

@ -26,21 +26,21 @@ import org.pgpainless.wot.network.Fingerprint
*/
class MultipleCertifications1Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("9219941467AA737C6EC1207959A2CEFC112C359A")
val alice_uid = "<alice@example.org>"
val aliceFpr = Fingerprint("9219941467AA737C6EC1207959A2CEFC112C359A")
val aliceUid = "<alice@example.org>"
val bob_fpr = Fingerprint("72CAA0F0A4A020F5FA20CD8CB5CC04473AA88123")
val bob_uid = "<bob@example.org>"
val bobFpr = Fingerprint("72CAA0F0A4A020F5FA20CD8CB5CC04473AA88123")
val bobUid = "<bob@example.org>"
// Certified by: 9219941467AA737C6EC1207959A2CEFC112C359A
// Certified by: 9219941467AA737C6EC1207959A2CEFC112C359A
// Certified by: 9219941467AA737C6EC1207959A2CEFC112C359A
val carol_fpr = Fingerprint("853304031E7B0B116BBD0B398734F11945313904")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("853304031E7B0B116BBD0B398734F11945313904")
val carolUid = "<carol@example.org>"
// Certified by: 72CAA0F0A4A020F5FA20CD8CB5CC04473AA88123
val dave_fpr = Fingerprint("4C77ABDBE4F855E0C3C7A7D549F6B2BFDA83E424")
val dave_uid = "<dave@example.org>"
val daveFpr = Fingerprint("4C77ABDBE4F855E0C3C7A7D549F6B2BFDA83E424")
val daveUid = "<dave@example.org>"
// Certified by: 853304031E7B0B116BBD0B398734F11945313904
/**

View file

@ -38,21 +38,21 @@ import org.pgpainless.wot.network.Fingerprint
*/
class MultipleUserIds1Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA")
val alice_uid = "<alice@example.org>"
val aliceFpr = Fingerprint("2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA")
val aliceUid = "<alice@example.org>"
val bob_fpr = Fingerprint("03182611B91B1E7E20B848E83DFC151ABFAD85D5")
val bob_uid = "<bob@other.org>"
val bobFpr = Fingerprint("03182611B91B1E7E20B848E83DFC151ABFAD85D5")
val bobUid = "<bob@other.org>"
// Certified by: 2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA
val bob_some_org_uid = "<bob@some.org>"
val bob_some_orgUid = "<bob@some.org>"
// Certified by: 2A2A4A23A7EEC119BC0B46642B3825DC02A05FEA
val carol_fpr = Fingerprint("9CA36907B46FE7B6B9EE9601E78064C12B6D7902")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("9CA36907B46FE7B6B9EE9601E78064C12B6D7902")
val carolUid = "<carol@example.org>"
// Certified by: 03182611B91B1E7E20B848E83DFC151ABFAD85D5
val dave_fpr = Fingerprint("C1BC6794A6C6281B968A6A41ACE2055D610CEA03")
val dave_uid = "<dave@other.org>"
val daveFpr = Fingerprint("C1BC6794A6C6281B968A6A41ACE2055D610CEA03")
val daveUid = "<dave@other.org>"
// Certified by: 9CA36907B46FE7B6B9EE9601E78064C12B6D7902
override fun getResourceName(): String {

View file

@ -29,29 +29,29 @@ import org.pgpainless.wot.network.Fingerprint
*/
class MultipleUserIds2Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("F1C99C4019837703DD17C45440F8A0141DF278EA")
val alice_uid = "<alice@example.org>"
val aliceFpr = Fingerprint("F1C99C4019837703DD17C45440F8A0141DF278EA")
val aliceUid = "<alice@example.org>"
val bob_fpr = Fingerprint("5528B9E5DAFC519ED2E37F0377B332E4111456CB")
val bob_uid = "<bob@other.org>"
val bobFpr = Fingerprint("5528B9E5DAFC519ED2E37F0377B332E4111456CB")
val bobUid = "<bob@other.org>"
// Certified by: F1C99C4019837703DD17C45440F8A0141DF278EA
val bob_some_org_uid = "<bob@some.org>"
val bobSomeOrgUid = "<bob@some.org>"
// Certified by: F1C99C4019837703DD17C45440F8A0141DF278EA
val carol_fpr = Fingerprint("6F8291428420AB53576BAB4BEFF6477D3E348D71")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("6F8291428420AB53576BAB4BEFF6477D3E348D71")
val carolUid = "<carol@example.org>"
// Certified by: 5528B9E5DAFC519ED2E37F0377B332E4111456CB
val dave_fpr = Fingerprint("62C57D90DAD253DEA01D5A86C7382FD6285C18F0")
val dave_uid = "<dave@other.org>"
val daveFpr = Fingerprint("62C57D90DAD253DEA01D5A86C7382FD6285C18F0")
val daveUid = "<dave@other.org>"
// Certified by: 6F8291428420AB53576BAB4BEFF6477D3E348D71
val ed_fpr = Fingerprint("0E974D0ACBA0C4D8F51D7CF68F048FF83B173504")
val ed_uid = "<ed@example.org>"
val edFpr = Fingerprint("0E974D0ACBA0C4D8F51D7CF68F048FF83B173504")
val edUid = "<ed@example.org>"
// Certified by: 6F8291428420AB53576BAB4BEFF6477D3E348D71
val frank_fpr = Fingerprint("5BEE3D41F85B2FCBC300DE4E18CB2BDA65465F03")
val frank_uid = "<frank@other.org>"
val frankFpr = Fingerprint("5BEE3D41F85B2FCBC300DE4E18CB2BDA65465F03")
val frankUid = "<frank@other.org>"
// Certified by: 5528B9E5DAFC519ED2E37F0377B332E4111456CB
override fun getResourceName(): String {

View file

@ -28,30 +28,30 @@ import org.pgpainless.wot.network.Fingerprint
*/
class MultipleUserIds3Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("DA3CFC60BD4B8835702A66782C7A431946C12DF7")
val alice_uid = "<alice@example.org>"
val aliceFpr = Fingerprint("DA3CFC60BD4B8835702A66782C7A431946C12DF7")
val aliceUid = "<alice@example.org>"
val bob_fpr = Fingerprint("28C108707090FCDFF630D1E141FB02F0E397D55E")
val bob_uid = "<bob@other.org>"
val bobFpr = Fingerprint("28C108707090FCDFF630D1E141FB02F0E397D55E")
val bobUid = "<bob@other.org>"
// Certified by: DA3CFC60BD4B8835702A66782C7A431946C12DF7
val bob_some_org_uid = "<bob@some.org>"
val bobSomeOrgUid = "<bob@some.org>"
// Certified by: DA3CFC60BD4B8835702A66782C7A431946C12DF7
val bob_third_org_uid = "<bob@third.org>"
val bobThirdOrgUid = "<bob@third.org>"
val carol_fpr = Fingerprint("9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8")
val carolUid = "<carol@example.org>"
// Certified by: 28C108707090FCDFF630D1E141FB02F0E397D55E
val dave_fpr = Fingerprint("0C131F8959F45D08B6136FDAAD2E16A26F73D48E")
val dave_uid = "<dave@example.org>"
val daveFpr = Fingerprint("0C131F8959F45D08B6136FDAAD2E16A26F73D48E")
val daveUid = "<dave@example.org>"
// Certified by: 28C108707090FCDFF630D1E141FB02F0E397D55E
val ed_fpr = Fingerprint("296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB")
val ed_uid = "<ed@example.org>"
val edFpr = Fingerprint("296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB")
val edUid = "<ed@example.org>"
// Certified by: 0C131F8959F45D08B6136FDAAD2E16A26F73D48E
val frank_fpr = Fingerprint("A72AA1B7D9D8CB04D988F1520A404E37A7766608")
val frank_uid = "<frank@example.org>"
val frankFpr = Fingerprint("A72AA1B7D9D8CB04D988F1520A404E37A7766608")
val frankUid = "<frank@example.org>"
// Certified by: 9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8
// Certified by: 296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB

View file

@ -27,27 +27,27 @@ import org.pgpainless.wot.network.Fingerprint
*/
class Regex1Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("3AD1F297E4B150F75DBFC43476FB81BFE0665C3A")
val alice_uid = "<alice@some.org>"
val aliceFpr = Fingerprint("3AD1F297E4B150F75DBFC43476FB81BFE0665C3A")
val aliceUid = "<alice@some.org>"
val bob_fpr = Fingerprint("20C812117FB2A3940EAE9160FEE6B4E47A096FD1")
val bob_uid = "<bob@example.org>"
val bobFpr = Fingerprint("20C812117FB2A3940EAE9160FEE6B4E47A096FD1")
val bobUid = "<bob@example.org>"
// Certified by: 3AD1F297E4B150F75DBFC43476FB81BFE0665C3A
val carol_fpr = Fingerprint("BC30978345D789CADECDE492F54B42E1625E1A1D")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("BC30978345D789CADECDE492F54B42E1625E1A1D")
val carolUid = "<carol@example.org>"
// Certified by: 20C812117FB2A3940EAE9160FEE6B4E47A096FD1
val dave_fpr = Fingerprint("319810FAD46CBE96DAD7F1F5B014902592999B21")
val dave_uid = "<dave@other.org>"
val daveFpr = Fingerprint("319810FAD46CBE96DAD7F1F5B014902592999B21")
val daveUid = "<dave@other.org>"
// Certified by: 20C812117FB2A3940EAE9160FEE6B4E47A096FD1
val ed_fpr = Fingerprint("23D7418EA0C6A42A54C32DBE8D4FE4911ED08467")
val ed_uid = "<ed@example.org>"
val edFpr = Fingerprint("23D7418EA0C6A42A54C32DBE8D4FE4911ED08467")
val edUid = "<ed@example.org>"
// Certified by: 319810FAD46CBE96DAD7F1F5B014902592999B21
val frank_fpr = Fingerprint("7FAE20D68EE87F74368AF275A0C40E741FC1C50F")
val frank_uid = "<frank@other.org>"
val frankFpr = Fingerprint("7FAE20D68EE87F74368AF275A0C40E741FC1C50F")
val frankUid = "<frank@other.org>"
// Certified by: 319810FAD46CBE96DAD7F1F5B014902592999B21
override fun getResourceName(): String {

View file

@ -23,23 +23,23 @@ import org.pgpainless.wot.network.Fingerprint
*/
class Regex2Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("5C396C920399898461F17CB747FDBF3EB3453919")
val alice_uid = "<alice@some.org>"
val aliceFpr = Fingerprint("5C396C920399898461F17CB747FDBF3EB3453919")
val aliceUid = "<alice@some.org>"
val bob_fpr = Fingerprint("584D195AD89CE0354D2CCBAEBCDD9EBC09692780")
val bob_uid = "<bob@some.org>"
val bobFpr = Fingerprint("584D195AD89CE0354D2CCBAEBCDD9EBC09692780")
val bobUid = "<bob@some.org>"
// Certified by: 5C396C920399898461F17CB747FDBF3EB3453919
val carol_fpr = Fingerprint("FC7A96D4810D0CF477031956AED58C644370C183")
val carol_uid = "<carol@other.org>"
val carolFpr = Fingerprint("FC7A96D4810D0CF477031956AED58C644370C183")
val carolUid = "<carol@other.org>"
// Certified by: 584D195AD89CE0354D2CCBAEBCDD9EBC09692780
val dave_fpr = Fingerprint("58077E659732526C1B8BF9837EFC0EDE07B506A8")
val dave_uid = "<dave@their.org>"
val daveFpr = Fingerprint("58077E659732526C1B8BF9837EFC0EDE07B506A8")
val daveUid = "<dave@their.org>"
// Certified by: FC7A96D4810D0CF477031956AED58C644370C183
val ed_fpr = Fingerprint("36089C49F18BF6FC6BCA35E3BB85877766C009E4")
val ed_uid = "<ed@example.org>"
val edFpr = Fingerprint("36089C49F18BF6FC6BCA35E3BB85877766C009E4")
val edUid = "<ed@example.org>"
// Certified by: 58077E659732526C1B8BF9837EFC0EDE07B506A8
override fun getResourceName(): String {

View file

@ -22,35 +22,35 @@ import org.pgpainless.wot.network.Fingerprint
*/
class Regex3Vectors: ArtifactVectors {
val alice_fpr = Fingerprint("D8CFEBBA006E2ED57CF45CC413F0BAE09D94FE4E")
val alice_uid = "<alice@some.org>"
val aliceFpr = Fingerprint("D8CFEBBA006E2ED57CF45CC413F0BAE09D94FE4E")
val aliceUid = "<alice@some.org>"
val bob_fpr = Fingerprint("A75DC1A1EDA5282F3A7381B51824E46BBCC801F0")
val bob_uid = "<bob@example.org>"
val bobFpr = Fingerprint("A75DC1A1EDA5282F3A7381B51824E46BBCC801F0")
val bobUid = "<bob@example.org>"
// Certified by: D8CFEBBA006E2ED57CF45CC413F0BAE09D94FE4E
val carol_fpr = Fingerprint("4BCD4325BDACA452F0301227A30CB4BCC329E769")
val carol_uid = "<carol@example.org>"
val carolFpr = Fingerprint("4BCD4325BDACA452F0301227A30CB4BCC329E769")
val carolUid = "<carol@example.org>"
// Certified by: A75DC1A1EDA5282F3A7381B51824E46BBCC801F0
val dave_fpr = Fingerprint("2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380")
val dave_uid = "<dave@other.org>"
val daveFpr = Fingerprint("2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380")
val daveUid = "<dave@other.org>"
// Certified by: A75DC1A1EDA5282F3A7381B51824E46BBCC801F0
val ed_fpr = Fingerprint("F645D081F480BE26C7D2C84D941B3E2CE53FAF16")
val ed_uid = "<ed@example.org>"
val edFpr = Fingerprint("F645D081F480BE26C7D2C84D941B3E2CE53FAF16")
val edUid = "<ed@example.org>"
// Certified by: 2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380
val frank_fpr = Fingerprint("AFAB11F1A37FD20C85CF8093F4941D1A0EC5749F")
val frank_uid = "<frank@other.org>"
val frankFpr = Fingerprint("AFAB11F1A37FD20C85CF8093F4941D1A0EC5749F")
val frankUid = "<frank@other.org>"
// Certified by: 2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380
val george_fpr = Fingerprint("D01C8752D9BA9F3F5F06B21F394E911938D6DB0A")
val george_uid = "<george@their.org>"
val georgeFpr = Fingerprint("D01C8752D9BA9F3F5F06B21F394E911938D6DB0A")
val georgeUid = "<george@their.org>"
// Certified by: 2E1AAA8D9A22C94ACCA362A22B34031CD5CB9380
val henry_fpr = Fingerprint("B99A8696FD820192CEEE285D3A253E49F1D97109")
val henry_uid = "<henry@their.org>"
val henryFpr = Fingerprint("B99A8696FD820192CEEE285D3A253E49F1D97109")
val henryUid = "<henry@their.org>"
// Certified by: A75DC1A1EDA5282F3A7381B51824E46BBCC801F0
override fun getResourceName(): String {

View file

@ -34,7 +34,7 @@ class SelfSignedVectors: ArtifactVectors {
val carolFpr = Fingerprint("830230061426EE99A0455E6ADA869CF879A5630D")
val carolUid = "<carol@example.org>"
// Certified by: 7A7B5DE6C8F464CAB78BEFB9CE14BEE51D4DEC01
val carol_other_orgUid = "<carol@other.org>"
val carolOtherOrgUid = "<carol@other.org>"
val daveFpr = Fingerprint("51A5E15F87AC6ECAFBEA930FA5F30AF6EB6EF14A")
val daveUid = "<dave@example.org>"