mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-11-05 03:55:58 +01:00
Remove pgpainless-core dependency from wot-dijkstra
This commit is contained in:
parent
630c263918
commit
ae92b01cbb
9 changed files with 120 additions and 42 deletions
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -34,9 +34,6 @@ dependencies {
|
|||
|
||||
// @Nullable, @Nonnull annotations
|
||||
implementation "com.google.code.findbugs:jsr305:3.0.2"
|
||||
|
||||
// OpenPgpFingerprint, RevocationState
|
||||
implementation(project(":pgpainless-core"))
|
||||
}
|
||||
|
||||
test {
|
||||
|
|
|
@ -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>) {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
) {
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue