1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-25 04:54:49 +02: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
import org.pgpainless.certificate_store.PGPainlessCertD
import org.pgpainless.util.DateUtil
import org.pgpainless.wot.cli.subcommands.*
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 java.io.File
@ -28,13 +33,22 @@ class WotCLI: Callable<Int> {
@Option(names = ["--trust-root", "-r"], required = true)
var trustRoot: Array<String> = arrayOf()
@Option(names = ["--keyring", "-k"], description = ["Specify a keyring file."], required = true)
var keyring: File? = null
@ArgGroup(exclusive = true, multiplicity = "1")
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."])
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.
*

View file

@ -25,29 +25,49 @@ import org.pgpainless.wot.util.CertificationFactory.Companion.fromCertification
import org.pgpainless.wot.util.CertificationFactory.Companion.fromDelegation
import org.slf4j.LoggerFactory
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 java.io.IOException
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
fun initialize() {
val certificates = getAllCertificatesFromTheStore()
network = fromCertificates(certificates, PGPainless.getPolicy(), now())
}
private fun getAllCertificatesFromTheStore(): Sequence<Certificate> {
var trustRoot: Certificate? = null
try {
trustRoot = certificateStore.trustRootCertificate
trustRoot = certificateStore.getCertificate(SpecialNames.TRUST_ROOT)
} catch (e: NoSuchElementException) {
// ignore
}
val certificates = if (trustRoot == null) {
certificateStore.items().asSequence()
certificateStore.certificates.asSequence()
} else {
sequenceOf(trustRoot) + certificateStore.items().asSequence()
sequenceOf(trustRoot) + certificateStore.certificates.asSequence()
}
network = fromCertificates(certificates, PGPainless.getPolicy(), now())
return certificates
}
companion object {

View file

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

View file

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