1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-14 00:12:06 +01:00

Move the API definition to wot-dijkstra

This commit is contained in:
Paul Schaub 2023-07-07 15:41:17 +02:00
parent 3d8840116c
commit 8029d031bc
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
13 changed files with 64 additions and 39 deletions

View file

@ -8,6 +8,8 @@ SPDX-License-Identifier: Apache-2.0
This module contains a command line interface application that acts as a front-end for
[`pgpainless-wot`](../pgpainless-wot).
The interface of the application is modelled after the [sq-wot](https://gitlab.com/sequoia-pgp/sequoia-wot/)
reference implementation.
## Build

View file

@ -6,10 +6,11 @@ package org.pgpainless.wot.cli
import org.pgpainless.certificate_store.PGPainlessCertD
import org.pgpainless.util.DateUtil
import org.pgpainless.wot.api.WoTAPI
import org.pgpainless.wot.WebOfTrust
import org.pgpainless.wot.cli.subcommands.*
import org.pgpainless.wot.dijkstra.sq.Fingerprint
import org.pgpainless.wot.dijkstra.sq.ReferenceTime
import org.pgpainless.wot.dijkstra.sq.api.WoTAPI
import pgp.cert_d.PGPCertificateStoreAdapter
import pgp.cert_d.subkey_lookup.InMemorySubkeyLookupFactory
import pgp.certificate_store.PGPCertificateStore
@ -19,6 +20,11 @@ import java.io.File
import java.util.concurrent.Callable
import kotlin.system.exitProcess
/**
* Command Line Interface for pgpainless-wot, modelled after the reference implementation "sq-wot".
*
* @see <a href="https://gitlab.com/sequoia-pgp/sequoia-wot/">Sequoia Web of Trust Reference Implementation</a>
*/
@Command(name = "pgpainless-wot",
subcommands = [
AuthenticateCmd::class,
@ -110,8 +116,10 @@ class WotCLI: Callable<Int> {
val api: WoTAPI
get() {
val network = WebOfTrust(certificateStore)
.buildNetwork(referenceTime = referenceTime)
return WoTAPI(
certStores = listOf(certificateStore),
network = network,
trustRoots = trustRoots,
gossip = false,
certificationNetwork = false,

View file

@ -4,7 +4,7 @@
package org.pgpainless.wot.cli.subcommands
import org.pgpainless.wot.api.AuthenticateAPI
import org.pgpainless.wot.dijkstra.sq.api.AuthenticateAPI
import org.pgpainless.wot.cli.WotCLI
import org.pgpainless.wot.dijkstra.sq.Fingerprint
import org.pgpainless.wot.dijkstra.sq.Path
@ -15,18 +15,33 @@ import picocli.CommandLine.ParentCommand
import java.text.SimpleDateFormat
import java.util.concurrent.Callable
/**
* Authenticate a binding between a certification and one of its user-ids.
*/
@Command(name = "authenticate")
class AuthenticateCmd: Callable<Int> {
/**
* Parent command to acquire global options from.
*/
@ParentCommand
lateinit var parent: WotCLI
/**
* Fingerprint of the certificate.
*/
@Parameters(index = "0")
lateinit var fingerprint: String
/**
* User-ID to authenticate.
*/
@Parameters(index = "1")
lateinit var userId: String
/**
* Handle the User-ID as an email address.
*/
@CommandLine.Option(names = ["--email"], description = ["Consider all user-IDs that contain the given email address."])
var email = false
@ -46,6 +61,9 @@ class AuthenticateCmd: Callable<Int> {
return 0
}
/**
* Format the [AuthenticateAPI.Result] as a [String] which can be printed to standard out.
*/
internal fun formatResult(result: AuthenticateAPI.Result): String {
if (result.percentage < 100) {
return "No paths found."

View file

@ -1,7 +1,7 @@
package org.pgpainless.wot.cli.subcommands
import org.junit.jupiter.api.Test
import org.pgpainless.wot.api.AuthenticateAPI
import org.pgpainless.wot.dijkstra.sq.api.AuthenticateAPI
import org.pgpainless.wot.dijkstra.sq.*
import java.text.SimpleDateFormat
import kotlin.test.assertEquals

View file

@ -43,14 +43,23 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
*
* @param certificateDirectory PGP-Certificate-Directory instance
*/
constructor(certificateDirectory: PGPCertificateDirectory): this(PGPCertificateStoreAdapter(certificateDirectory))
constructor(certificateDirectory: PGPCertificateDirectory):
this(PGPCertificateStoreAdapter(certificateDirectory))
fun buildNetwork(policy: Policy = PGPainless.getPolicy(), referenceTime: ReferenceTime = now()): Network {
/**
*
*/
fun buildNetwork(policy: Policy = PGPainless.getPolicy(),
referenceTime: ReferenceTime = now()): Network {
val certificates = getAllCertificatesFromTheStore()
val networkFactory = PGPNetworkFactory.fromCertificates(certificates, policy, referenceTime)
return networkFactory.buildNetwork()
}
/**
* Return a [Sequence] containing all [Certificates][Certificate] in the [PGPCertificateStore],
* with the specially named "trust-root" certificate optionally appended if present.
*/
private fun getAllCertificatesFromTheStore(): Sequence<Certificate> {
var trustRoot: Certificate? = null
try {
@ -157,7 +166,8 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
while (userIds.hasNext()) {
val userId = userIds.next()
// There are potentially multiple certifications per user-ID
val userIdSigs = SignatureUtils.get3rdPartyCertificationsFor(userId, validatedTargetKeyRing)
val userIdSigs = SignatureUtils.get3rdPartyCertificationsFor(
userId, validatedTargetKeyRing)
userIdSigs.forEach {
processCertificationOnUserId(targetPrimaryKey, target, userId, it)
}
@ -194,7 +204,8 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
}
} catch (e: SignatureValidationException) {
val targetFingerprint = OpenPgpFingerprint.of(targetPrimaryKey)
LOGGER.warn("Cannot verify signature by $issuerFingerprint on cert of $targetFingerprint", e)
LOGGER.warn("Cannot verify signature by $issuerFingerprint" +
" on cert of $targetFingerprint", e)
}
}
}
@ -321,7 +332,8 @@ class WebOfTrust(private val certificateStore: PGPCertificateStore) {
referenceTime: ReferenceTime): List<KeyRingInfo> {
return certificates
.mapNotNull {
try { PGPainless.readKeyRing().publicKeyRing(it.inputStream) } catch (e: IOException) { null }
try { PGPainless.readKeyRing().publicKeyRing(it.inputStream) }
catch (e: IOException) { null }
}
.map { KeyRingInfo(it, policy, referenceTime.timestamp) }
.toList()

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
import org.pgpainless.wot.dijkstra.sq.Fingerprint
import org.pgpainless.wot.dijkstra.sq.Paths

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
/**
* Enum for different levels of Trust.

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.cli.subcommands
package org.pgpainless.wot.dijkstra.sq.api
/**
* Enum listing possible output formats.

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
import org.pgpainless.wot.dijkstra.sq.Fingerprint
import org.pgpainless.wot.dijkstra.sq.Paths

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
import org.pgpainless.wot.dijkstra.sq.Paths

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
import org.pgpainless.wot.dijkstra.sq.Paths

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
import org.pgpainless.wot.dijkstra.sq.Fingerprint

View file

@ -2,20 +2,16 @@
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.wot.api
package org.pgpainless.wot.dijkstra.sq.api
import org.pgpainless.certificate_store.PGPainlessCertD
import org.pgpainless.util.NotationRegistry
import org.pgpainless.wot.dijkstra.sq.Fingerprint
import org.pgpainless.wot.dijkstra.sq.Network
import org.pgpainless.wot.dijkstra.sq.ReferenceTime
import pgp.cert_d.PGPCertificateStoreAdapter
import pgp.cert_d.subkey_lookup.InMemorySubkeyLookupFactory
import pgp.certificate_store.PGPCertificateStore
/**
* Web of Trust API, offering different operations.
*
* @param certStores one or more [PGPCertificateStores][PGPCertificateStore] to retrieve certificates from.
* @param network initialized [Network] containing certificates as nodes and certifications as edges.
* @param trustRoots one or more [Fingerprints][Fingerprint] of trust-roots.
* @param gossip if true, consider all certificates as weakly trusted trust-roots
* @param certificationNetwork if true, all certifications are treated as delegations with infinite trust depth and no regular expressions
@ -24,35 +20,24 @@ import pgp.certificate_store.PGPCertificateStore
* @param knownNotationRegistry registry of known notations
*/
class WoTAPI(
val certStores: List<PGPCertificateStore> = getDefaultCertStores(),
val network: Network,
val trustRoots: List<Fingerprint>,
val gossip: Boolean = false,
val certificationNetwork: Boolean = false,
val trustAmount: Int = AuthenticationLevel.Fully.amount,
val referenceTime: ReferenceTime = ReferenceTime.now(),
val knownNotationRegistry: NotationRegistry = NotationRegistry()
val referenceTime: ReferenceTime = ReferenceTime.now()
): AuthenticateAPI, IdentifyAPI, ListAPI, LookupAPI, PathAPI {
/**
* Secondary constructor, taking an [AuthenticationLevel] instead of an [Int].
*/
constructor(certStores: List<PGPCertificateStore> = getDefaultCertStores(),
constructor(network: Network,
trustRoots: List<Fingerprint>,
gossip: Boolean = false,
certificationNetwork: Boolean = false,
trustAmount: AuthenticationLevel = AuthenticationLevel.Fully,
referenceTime: ReferenceTime = ReferenceTime.now(),
knownNotationRegistry: NotationRegistry = NotationRegistry()):
this(certStores,trustRoots, gossip,certificationNetwork, trustAmount.amount, referenceTime, knownNotationRegistry)
companion object {
@JvmStatic
fun getDefaultCertStores(): List<PGPCertificateStore> {
val certD = PGPainlessCertD.fileBased(InMemorySubkeyLookupFactory())
val asStore = PGPCertificateStoreAdapter(certD)
return listOf(asStore)
}
}
referenceTime: ReferenceTime = ReferenceTime.now()):
this(network,trustRoots, gossip,certificationNetwork, trustAmount.amount, referenceTime)
override fun authenticate(arguments: AuthenticateAPI.Arguments): AuthenticateAPI.Result {
TODO("Not yet implemented")