1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-12-25 04:17:59 +01:00

Base WebOfTrust on PGPCertificateStore instead of PGPCertificateDirectory

This commit is contained in:
Paul Schaub 2023-06-29 19:23:40 +02:00
parent 55e39d85c5
commit 630c263918
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 78 additions and 33 deletions

View file

@ -4,9 +4,14 @@
package org.pgpainless.wot.cli package org.pgpainless.wot.cli
import org.pgpainless.certificate_store.PGPainlessCertD
import org.pgpainless.util.DateUtil import org.pgpainless.util.DateUtil
import org.pgpainless.wot.cli.subcommands.* import org.pgpainless.wot.cli.subcommands.*
import org.pgpainless.wot.dijkstra.sq.ReferenceTime import org.pgpainless.wot.dijkstra.sq.ReferenceTime
import pgp.cert_d.PGPCertificateDirectory
import pgp.cert_d.PGPCertificateStoreAdapter
import pgp.cert_d.subkey_lookup.InMemorySubkeyLookupFactory
import pgp.certificate_store.PGPCertificateStore
import picocli.CommandLine import picocli.CommandLine
import picocli.CommandLine.* import picocli.CommandLine.*
import java.io.File import java.io.File
@ -28,13 +33,22 @@ class WotCLI: Callable<Int> {
@Option(names = ["--trust-root", "-r"], required = true) @Option(names = ["--trust-root", "-r"], required = true)
var trustRoot: Array<String> = arrayOf() var trustRoot: Array<String> = arrayOf()
@Option(names = ["--keyring", "-k"], description = ["Specify a keyring file."], required = true) @ArgGroup(exclusive = true, multiplicity = "1")
var keyring: File? = null lateinit var certificateSource: CertificateSource
class CertificateSource {
@Option(names = ["--keyring", "-k"], description = ["Specify a keyring file."], required = true)
var keyring: File? = null
@Option(names = ["--cert-d"], description = ["Specify a pgp-cert-d base directory."], required = true)
var pgpCertD: File? = null
@Option(names = ["--gpg"], description = ["Read trust roots and keyring from GnuPG."])
var gpg = false
}
/* /*
@Option(names = ["--gpg"], description = ["Read trust roots and keyring from GnuPG."])
var gpg = false
@Option(names = ["--network"], description = ["Look for missing certificates on a key server or the WKD."]) @Option(names = ["--network"], description = ["Look for missing certificates on a key server or the WKD."])
var keyServer = "hkps://keyserver.ubuntu.com" var keyServer = "hkps://keyserver.ubuntu.com"
@ -60,6 +74,17 @@ class WotCLI: Callable<Int> {
} }
} }
fun getCertificateStore(): PGPCertificateStore {
requireNotNull(certificateSource.pgpCertD) {
"Currently, only --cert-d is supported."
}
val certD = PGPainlessCertD.fileBased(
certificateSource.pgpCertD,
InMemorySubkeyLookupFactory())
return PGPCertificateStoreAdapter(certD)
}
/** /**
* Execute the command. * Execute the command.
* *

View file

@ -25,29 +25,49 @@ import org.pgpainless.wot.util.CertificationFactory.Companion.fromCertification
import org.pgpainless.wot.util.CertificationFactory.Companion.fromDelegation import org.pgpainless.wot.util.CertificationFactory.Companion.fromDelegation
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import pgp.cert_d.PGPCertificateDirectory import pgp.cert_d.PGPCertificateDirectory
import pgp.cert_d.PGPCertificateStoreAdapter
import pgp.cert_d.SpecialNames
import pgp.certificate_store.PGPCertificateStore
import pgp.certificate_store.certificate.Certificate import pgp.certificate_store.certificate.Certificate
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
class WebOfTrust(private val certificateStore: PGPCertificateDirectory) { /**
* Create a [WebOfTrust] based on a [PGPCertificateStore] instance.
*
* @param certificateStore certificate store
*/
class WebOfTrust(private val certificateStore: PGPCertificateStore) {
/**
* Create a [WebOfTrust] based on a [PGPCertificateDirectory] instance, which gets adapted to the
* [PGPCertificateStore] interface.
*
* @param certificateDirectory PGP-Certificate-Directory instance
*/
constructor(certificateDirectory: PGPCertificateDirectory): this(PGPCertificateStoreAdapter(certificateDirectory))
lateinit var network: Network lateinit var network: Network
fun initialize() { fun initialize() {
val certificates = getAllCertificatesFromTheStore()
network = fromCertificates(certificates, PGPainless.getPolicy(), now())
}
private fun getAllCertificatesFromTheStore(): Sequence<Certificate> {
var trustRoot: Certificate? = null var trustRoot: Certificate? = null
try { try {
trustRoot = certificateStore.trustRootCertificate trustRoot = certificateStore.getCertificate(SpecialNames.TRUST_ROOT)
} catch (e: NoSuchElementException) { } catch (e: NoSuchElementException) {
// ignore // ignore
} }
val certificates = if (trustRoot == null) { val certificates = if (trustRoot == null) {
certificateStore.items().asSequence() certificateStore.certificates.asSequence()
} else { } else {
sequenceOf(trustRoot) + certificateStore.items().asSequence() sequenceOf(trustRoot) + certificateStore.certificates.asSequence()
} }
return certificates
network = fromCertificates(certificates, PGPainless.getPolicy(), now())
} }
companion object { companion object {

View file

@ -35,8 +35,8 @@ public class WebOfTrustTest {
@Test @Test
public void testWithTwoNodesAndOneDelegation() throws BadDataException, IOException, InterruptedException { public void testWithTwoNodesAndOneDelegation() throws BadDataException, IOException, InterruptedException {
PGPCertificateDirectory store = TestCertificateStores.oneDelegationGraph(); PGPCertificateDirectory certD = TestCertificateStores.oneDelegationGraph();
WebOfTrust wot = new WebOfTrust(store); WebOfTrust wot = new WebOfTrust(certD);
wot.initialize(); wot.initialize();
Network network = wot.getNetwork(); Network network = wot.getNetwork();
@ -52,8 +52,8 @@ public class WebOfTrustTest {
@Test @Test
public void testWithCrossSignedCertificates() public void testWithCrossSignedCertificates()
throws BadDataException, IOException, InterruptedException { throws BadDataException, IOException, InterruptedException {
PGPCertificateDirectory store = TestCertificateStores.disconnectedGraph(); PGPCertificateDirectory certD = TestCertificateStores.disconnectedGraph();
WebOfTrust wot = new WebOfTrust(store); WebOfTrust wot = new WebOfTrust(certD);
wot.initialize(); wot.initialize();
Network network = wot.getNetwork(); Network network = wot.getNetwork();
@ -140,8 +140,8 @@ public class WebOfTrustTest {
@Test @Test
public void testWotCreationOfEmptyCertificates() { public void testWotCreationOfEmptyCertificates() {
PGPCertificateDirectory store = TestCertificateStores.emptyGraph(); PGPCertificateDirectory certD = TestCertificateStores.emptyGraph();
WebOfTrust wot = new WebOfTrust(store); WebOfTrust wot = new WebOfTrust(certD);
wot.initialize(); wot.initialize();
Network network = wot.getNetwork(); Network network = wot.getNetwork();

View file

@ -29,37 +29,37 @@ public class TestCertificateStores {
public static PGPCertificateDirectory disconnectedGraph() public static PGPCertificateDirectory disconnectedGraph()
throws BadDataException, IOException, InterruptedException { throws BadDataException, IOException, InterruptedException {
PGPCertificateDirectory wotStore = createInMemoryStore(); PGPCertificateDirectory certD = createInMemoryCertificateDirectory();
wotStore.insertTrustRoot(getTestVector("cross_signed/foobankCaCert.asc"), merger); certD.insertTrustRoot(getTestVector("cross_signed/foobankCaCert.asc"), merger);
wotStore.insert(getTestVector("cross_signed/foobankEmployeeCert.asc"), merger); certD.insert(getTestVector("cross_signed/foobankEmployeeCert.asc"), merger);
wotStore.insert(getTestVector("cross_signed/foobankAdminCert.asc"), merger); certD.insert(getTestVector("cross_signed/foobankAdminCert.asc"), merger);
wotStore.insert(getTestVector("cross_signed/barbankCaCert.asc"), merger); certD.insert(getTestVector("cross_signed/barbankCaCert.asc"), merger);
wotStore.insert(getTestVector("cross_signed/barbankEmployeeCert.asc"), merger); certD.insert(getTestVector("cross_signed/barbankEmployeeCert.asc"), merger);
return wotStore; return certD;
} }
public static PGPCertificateDirectory emptyGraph() { public static PGPCertificateDirectory emptyGraph() {
PGPCertificateDirectory wotStore = createInMemoryStore(); PGPCertificateDirectory certD = createInMemoryCertificateDirectory();
return wotStore; return certD;
} }
public static PGPCertificateDirectory oneDelegationGraph() throws BadDataException, IOException, InterruptedException { public static PGPCertificateDirectory oneDelegationGraph() throws BadDataException, IOException, InterruptedException {
PGPCertificateDirectory wotStore = createInMemoryStore(); PGPCertificateDirectory certD = createInMemoryCertificateDirectory();
wotStore.insert(getTestVector("cross_signed/foobankAdminCert.asc"), merger); certD.insert(getTestVector("cross_signed/foobankAdminCert.asc"), merger);
wotStore.insert(getTestVector("cross_signed/barbankCaCert.asc"), merger); certD.insert(getTestVector("cross_signed/barbankCaCert.asc"), merger);
return wotStore; return certD;
} }
private static PGPCertificateDirectory createInMemoryStore() { private static PGPCertificateDirectory createInMemoryCertificateDirectory() {
SubkeyLookup subkeyLookup = new InMemorySubkeyLookup(); SubkeyLookup subkeyLookup = new InMemorySubkeyLookup();
KeyMaterialReaderBackend readerBackend = new KeyMaterialReader(); KeyMaterialReaderBackend readerBackend = new KeyMaterialReader();
PGPCertificateDirectory.Backend backend = new InMemoryCertificateDirectoryBackend(readerBackend); PGPCertificateDirectory.Backend backend = new InMemoryCertificateDirectoryBackend(readerBackend);
PGPCertificateDirectory store = new PGPCertificateDirectory(backend, subkeyLookup); PGPCertificateDirectory certD = new PGPCertificateDirectory(backend, subkeyLookup);
return store; return certD;
} }
private static InputStream requireResource(String resourceName) { private static InputStream requireResource(String resourceName) {