mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
Base WebOfTrust on PGPCertificateStore instead of PGPCertificateDirectory
This commit is contained in:
parent
55e39d85c5
commit
630c263918
4 changed files with 78 additions and 33 deletions
|
@ -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()
|
||||||
|
|
||||||
|
@ArgGroup(exclusive = true, multiplicity = "1")
|
||||||
|
lateinit var certificateSource: CertificateSource
|
||||||
|
|
||||||
|
class CertificateSource {
|
||||||
@Option(names = ["--keyring", "-k"], description = ["Specify a keyring file."], required = true)
|
@Option(names = ["--keyring", "-k"], description = ["Specify a keyring file."], required = true)
|
||||||
var keyring: File? = null
|
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."])
|
@Option(names = ["--gpg"], description = ["Read trust roots and keyring from GnuPG."])
|
||||||
var gpg = false
|
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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue