1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-25 04:54:49 +02:00

Remove pgpainless-core dependency from wot-dijkstra

This commit is contained in:
Paul Schaub 2023-06-29 20:18:01 +02:00
parent 630c263918
commit ae92b01cbb
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
9 changed files with 120 additions and 42 deletions

View file

@ -8,7 +8,6 @@ import org.bouncycastle.openpgp.PGPPublicKey
import org.bouncycastle.openpgp.PGPSignature
import org.pgpainless.PGPainless
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.algorithm.RevocationState
import org.pgpainless.exception.SignatureValidationException
import org.pgpainless.key.OpenPgpFingerprint
import org.pgpainless.key.info.KeyRingInfo
@ -122,6 +121,11 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
RevocationState.softRevoked(revocation.creationTime)
}
@JvmStatic
private fun OpenPgpFingerprint.map(): Fingerprint {
return Fingerprint(toString())
}
/**
* Class for building the [Flow network][Network] from the given set of OpenPGP keys.
*
@ -133,19 +137,19 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
private val LOGGER = LoggerFactory.getLogger(NetworkBuilder::class.java)
// certificates keyed by fingerprint
private val byFingerprint: MutableMap<OpenPgpFingerprint, KeyRingInfo> = HashMap()
private val byFingerprint: MutableMap<Fingerprint, KeyRingInfo> = HashMap()
// certificates keyed by (sub-) key-id
private val byKeyId: MutableMap<Long, MutableList<KeyRingInfo>> = HashMap()
// certificate synopses keyed by fingerprint
private val certSynopsisMap: MutableMap<OpenPgpFingerprint, CertSynopsis> = HashMap()
private val certSynopsisMap: MutableMap<Fingerprint, CertSynopsis> = HashMap()
// Issuer -> Targets, edges keyed by issuer
private val edges: MutableMap<OpenPgpFingerprint, MutableList<CertificationSet>> = HashMap()
private val edges: MutableMap<Fingerprint, MutableList<CertificationSet>> = HashMap()
// Target -> Issuers, edges keyed by target
private val reverseEdges: MutableMap<OpenPgpFingerprint, MutableList<CertificationSet>> = HashMap()
private val reverseEdges: MutableMap<Fingerprint, MutableList<CertificationSet>> = HashMap()
init {
synopsizeCertificates(validatedCertificates)
@ -161,8 +165,9 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
private fun synopsize(cert: KeyRingInfo) {
// index by fingerprint
if (!byFingerprint.containsKey(cert.fingerprint)) {
byFingerprint[cert.fingerprint] = cert
val certFingerprint = cert.fingerprint.map()
if (!byFingerprint.containsKey(certFingerprint)) {
byFingerprint[certFingerprint] = cert
}
// index by key-ID
@ -189,7 +194,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
// Some keys are malformed and have no KeyFlags
return
}
certSynopsisMap[cert.fingerprint] = CertSynopsis(cert.fingerprint,
certSynopsisMap[certFingerprint] = CertSynopsis(certFingerprint,
expirationDate,
revocationStateFromSignature(cert.revocationSelfSignature),
userIds)
@ -205,7 +210,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
private fun findEdgesWithTarget(validatedTarget: KeyRingInfo) {
val validatedTargetKeyRing = KeyRingUtils.publicKeys(validatedTarget.keys)
val targetFingerprint = OpenPgpFingerprint.of(validatedTargetKeyRing)
val targetFingerprint = OpenPgpFingerprint.of(validatedTargetKeyRing).map()
val targetPrimaryKey = validatedTargetKeyRing.publicKey!!
val target = certSynopsisMap[targetFingerprint]!!
@ -231,7 +236,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
?: return
for (candidate in issuerCandidates) {
val issuerKeyRing = KeyRingUtils.publicKeys(candidate.keys)
val issuerFingerprint = OpenPgpFingerprint.of(issuerKeyRing)
val issuerFingerprint = OpenPgpFingerprint.of(issuerKeyRing).map()
val issuerSigningKey = issuerKeyRing.getPublicKey(delegation.keyID)
val issuer = certSynopsisMap[issuerFingerprint]
?: continue
@ -257,7 +262,7 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
?: continue
for (candidate in issuerCandidates) {
val issuerKeyRing = KeyRingUtils.publicKeys(candidate.keys)
val issuerFingerprint = OpenPgpFingerprint.of(issuerKeyRing)
val issuerFingerprint = OpenPgpFingerprint.of(issuerKeyRing).map()
val issuerSigningKey = issuerKeyRing.getPublicKey(certification.keyID)
?: continue
val issuer = certSynopsisMap[issuerFingerprint]

View file

@ -12,9 +12,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.util.List;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.junit.jupiter.api.Test;
import org.pgpainless.key.OpenPgpFingerprint;
import org.pgpainless.wot.dijkstra.sq.CertificationSet;
import org.pgpainless.wot.dijkstra.sq.Fingerprint;
import org.pgpainless.wot.dijkstra.sq.Network;
import org.pgpainless.wot.testfixtures.TestCertificateStores;
import org.pgpainless.wot.testfixtures.WotTestVectors;
@ -23,16 +25,20 @@ import pgp.certificate_store.exception.BadDataException;
public class WebOfTrustTest {
OpenPgpFingerprint fooBankCa = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshFooBankCaCert());
OpenPgpFingerprint fooBankEmployee = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshFooBankEmployeeCert());
OpenPgpFingerprint fooBankAdmin = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshFooBankAdminCert());
OpenPgpFingerprint barBankCa = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshBarBankCaCert());
OpenPgpFingerprint barBankEmployee = OpenPgpFingerprint.of(WotTestVectors.getTestVectors().getFreshBarBankEmployeeCert());
Fingerprint fooBankCa = fingerprintOf(WotTestVectors.getTestVectors().getFreshFooBankCaCert());
Fingerprint fooBankEmployee = fingerprintOf(WotTestVectors.getTestVectors().getFreshFooBankEmployeeCert());
Fingerprint fooBankAdmin = fingerprintOf(WotTestVectors.getTestVectors().getFreshFooBankAdminCert());
Fingerprint barBankCa = fingerprintOf(WotTestVectors.getTestVectors().getFreshBarBankCaCert());
Fingerprint barBankEmployee = fingerprintOf(WotTestVectors.getTestVectors().getFreshBarBankEmployeeCert());
public WebOfTrustTest() throws IOException {
}
private static Fingerprint fingerprintOf(PGPPublicKeyRing cert) {
return new Fingerprint(OpenPgpFingerprint.of(cert).toString());
}
@Test
public void testWithTwoNodesAndOneDelegation() throws BadDataException, IOException, InterruptedException {
PGPCertificateDirectory certD = TestCertificateStores.oneDelegationGraph();
@ -87,30 +93,30 @@ public class WebOfTrustTest {
// CHECKSTYLE:ON
}
private void assertHasIssuerAndTarget(CertificationSet certifications, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private void assertHasIssuerAndTarget(CertificationSet certifications, Fingerprint issuer, Fingerprint target) {
assertEquals(issuer, certifications.getIssuer().getFingerprint());
assertEquals(target, certifications.getTarget().getFingerprint());
}
private void assertHasEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private void assertHasEdge(Network network, Fingerprint issuer, Fingerprint target) {
assertNotNull(getEdgeFromTo(network, issuer, target), "Expected edge from " + issuer + " to " + target + " but got none.");
}
private void assertHasReverseEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private void assertHasReverseEdge(Network network, Fingerprint issuer, Fingerprint target) {
assertNotNull(getReverseEdgeFromTo(network, issuer, target), "Expected reverse edge to " + target + " from " + issuer + " but got none.");
}
private void assertHasNoEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private void assertHasNoEdge(Network network, Fingerprint issuer, Fingerprint target) {
CertificationSet edge = getEdgeFromTo(network, issuer, target);
assertNull(edge, "Expected no edge from " + issuer + " to " + target + " but got " + edge);
}
private void assertHasNoReverseEdge(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private void assertHasNoReverseEdge(Network network, Fingerprint issuer, Fingerprint target) {
CertificationSet reverseEdge = getReverseEdgeFromTo(network, issuer, target);
assertNull(reverseEdge, "Expected no reverse edge on " + target + " from " + issuer + " but got " + reverseEdge);
}
private CertificationSet getEdgeFromTo(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private CertificationSet getEdgeFromTo(Network network, Fingerprint issuer, Fingerprint target) {
List<CertificationSet> edges = network.getEdges().get(issuer);
if (edges == null) {
return null;
@ -124,7 +130,7 @@ public class WebOfTrustTest {
return null;
}
private CertificationSet getReverseEdgeFromTo(Network network, OpenPgpFingerprint issuer, OpenPgpFingerprint target) {
private CertificationSet getReverseEdgeFromTo(Network network, Fingerprint issuer, Fingerprint target) {
List<CertificationSet> revEdges = network.getReverseEdges().get(target);
if (revEdges == null) {
return null;

View file

@ -34,9 +34,6 @@ dependencies {
// @Nullable, @Nonnull annotations
implementation "com.google.code.findbugs:jsr305:3.0.2"
// OpenPgpFingerprint, RevocationState
implementation(project(":pgpainless-core"))
}
test {

View file

@ -4,20 +4,18 @@
package org.pgpainless.wot.dijkstra.sq
import org.pgpainless.algorithm.RevocationState
import org.pgpainless.key.OpenPgpFingerprint
import java.util.*
/**
* A [CertSynopsis] is a proxy object containing information about a certificate.
*
* @param fingerprint [OpenPgpFingerprint] of the certificate
* @param fingerprint [Fingerprint] of the certificate
* @param expirationTime optional expiration time of the certificate
* @param revocationState [RevocationState] denoting whether the certificate is revoked or not
* @param userIds [Map] of user-ids on the certificate, along with their revocation states
*/
data class CertSynopsis(
val fingerprint: OpenPgpFingerprint,
val fingerprint: Fingerprint,
val expirationTime: Date?,
val revocationState: RevocationState,
val userIds : Map<String, RevocationState>) {

View file

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.sq
class Fingerprint(fingerprint: String) {
val fingerprint: String
init {
this.fingerprint = fingerprint.uppercase()
}
override fun equals(other: Any?): Boolean {
if (other == null) {
return false
}
return if (other is Fingerprint) {
toString() == other.toString()
} else {
false
}
}
override fun hashCode(): Int {
return toString().hashCode()
}
override fun toString(): String {
return fingerprint.uppercase()
}
}

View file

@ -4,23 +4,21 @@
package org.pgpainless.wot.dijkstra.sq
import org.pgpainless.key.OpenPgpFingerprint
/**
* A network consists of nodes, and edges between them.
* For the Web of Trust, nodes consist of [CertSynopses][CertSynopsis], while the edges between the nodes are
* [CertificationSets][CertificationSet].
*
* @constructor creates a new network
* @param nodes contains a [Map] of [CertSynopsis] keyed by their [OpenPgpFingerprint]
* @param edges [Map] keyed by the [fingerprint][OpenPgpFingerprint] of an issuer, whose values are [Lists][List] containing all edges originating from the issuer.
* @param reverseEdges [Map] keyed by the [fingerprint][OpenPgpFingerprint] of a target, whose values are [Lists][List] containing all edges pointing to the target
* @param nodes contains a [Map] of [CertSynopsis] keyed by their [Fingerprint]
* @param edges [Map] keyed by the [fingerprint][Fingerprint] of an issuer, whose values are [Lists][List] containing all edges originating from the issuer.
* @param reverseEdges [Map] keyed by the [fingerprint][Fingerprint] of a target, whose values are [Lists][List] containing all edges pointing to the target
* @param referenceTime reference time at which the [Network] was built
*/
class Network(
val nodes: Map<OpenPgpFingerprint, CertSynopsis>,
val edges: Map<OpenPgpFingerprint, List<CertificationSet>>,
val reverseEdges: Map<OpenPgpFingerprint, List<CertificationSet>>,
val nodes: Map<Fingerprint, CertSynopsis>,
val edges: Map<Fingerprint, List<CertificationSet>>,
val reverseEdges: Map<Fingerprint, List<CertificationSet>>,
val referenceTime: ReferenceTime) {
companion object {

View file

@ -15,9 +15,9 @@ import kotlin.math.min
* @param residualDepth residual depth that is decreased each time another edge is appended
*/
class Path(
val root: CertSynopsis,
val edges: MutableList<Certification>,
var residualDepth: Depth
private val root: CertSynopsis,
private val edges: MutableList<Certification>,
private var residualDepth: Depth
) {
/**

View file

@ -9,7 +9,7 @@ package org.pgpainless.wot.dijkstra.sq
*
* @param paths list of paths
*/
class Paths(val paths: MutableList<Item>) {
class Paths(private val paths: MutableList<Item>) {
/**
* Empty collection of paths.

View file

@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.dijkstra.sq
import java.util.*
/**
* Revocation State of
*/
class RevocationState private constructor(val type: Type, val timestamp: Date?) {
enum class Type {
Soft,
Hard,
None
}
companion object {
@JvmStatic
fun notRevoked(): RevocationState = RevocationState(Type.None, null)
@JvmStatic
fun softRevoked(timestamp: Date): RevocationState = RevocationState(Type.Soft, timestamp)
@JvmStatic
fun hardRevoked(): RevocationState = RevocationState(Type.Hard, null)
}
fun isHardRevocation(): Boolean = type == Type.Hard
fun isSoftRevocation(): Boolean = type == Type.Soft
fun isNotRevoked(): Boolean = type == Type.None
fun isEffective(referenceTime: ReferenceTime): Boolean {
return isHardRevocation() ||
(isSoftRevocation() && referenceTime.timestamp.after(timestamp))
}
}