From 016c9dfc03bef0ae0d56fe87fc9c039a858211c1 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Wed, 5 Jul 2023 16:52:31 +0200 Subject: [PATCH] Port more test vectors to kotlin --- pgpainless-wot/build.gradle | 11 +- .../kotlin/org/pgpainless/wot/AdHocTest.kt | 14 + .../org/pgpainless/wot/WebOfTrustTest.kt | 10 +- .../wot/testfixtures/WotTestVectors.java | 290 ------------------ .../wot/testfixtures/AdHocVectors.kt | 113 +++++++ .../wot/testfixtures/WotTestVectors.kt | 245 +++++++++++++++ 6 files changed, 384 insertions(+), 299 deletions(-) create mode 100644 pgpainless-wot/src/test/kotlin/org/pgpainless/wot/AdHocTest.kt delete mode 100644 pgpainless-wot/src/testFixtures/java/org/pgpainless/wot/testfixtures/WotTestVectors.java create mode 100644 pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/AdHocVectors.kt create mode 100644 pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/WotTestVectors.kt diff --git a/pgpainless-wot/build.gradle b/pgpainless-wot/build.gradle index 49323cd2..db8b2818 100644 --- a/pgpainless-wot/build.gradle +++ b/pgpainless-wot/build.gradle @@ -34,16 +34,19 @@ dependencies { testFixturesImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" testFixturesImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" testFixturesRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" + testFixturesApi(project(":pgpainless-core")) // Logging testImplementation "ch.qos.logback:logback-classic:$logbackVersion" - implementation(project(":pgpainless-core")) - api(project(":wot-dijkstra")) - // Certificate store api "org.pgpainless:pgp-certificate-store:$certDJavaVersion" - api "org.pgpainless:pgpainless-cert-d:$pgpainlessCertDVersion" + api ("org.pgpainless:pgpainless-cert-d:$pgpainlessCertDVersion") { + exclude(group: "org.pgpainless", module: "pgpainless-core") + } + + implementation(project(":pgpainless-core")) + api(project(":wot-dijkstra")) } test { diff --git a/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/AdHocTest.kt b/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/AdHocTest.kt new file mode 100644 index 00000000..d7803112 --- /dev/null +++ b/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/AdHocTest.kt @@ -0,0 +1,14 @@ +package org.pgpainless.wot + +import org.junit.jupiter.api.Test +import org.pgpainless.wot.testfixtures.AdHocVectors + +class AdHocTest { + + @Test + fun test() { + val store = AdHocVectors.BestViaRoot().pgpCertificateStore + val wot = WebOfTrust(store).also { it.initialize() } + val network = wot.network + } +} \ No newline at end of file diff --git a/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/WebOfTrustTest.kt b/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/WebOfTrustTest.kt index df70ee6c..a606e227 100644 --- a/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/WebOfTrustTest.kt +++ b/pgpainless-wot/src/test/kotlin/org/pgpainless/wot/WebOfTrustTest.kt @@ -20,11 +20,11 @@ import kotlin.test.Test class WebOfTrustTest { - private val fooBankCa = fingerprintOf(WotTestVectors.getTestVectors().freshFooBankCaCert) - private val fooBankEmployee = fingerprintOf(WotTestVectors.getTestVectors().freshFooBankEmployeeCert) - private val fooBankAdmin = fingerprintOf(WotTestVectors.getTestVectors().freshFooBankAdminCert) - private val barBankCa = fingerprintOf(WotTestVectors.getTestVectors().freshBarBankCaCert) - private val barBankEmployee = fingerprintOf(WotTestVectors.getTestVectors().freshBarBankEmployeeCert) + private val fooBankCa = fingerprintOf(WotTestVectors.freshFooBankCaCert) + private val fooBankEmployee = fingerprintOf(WotTestVectors.freshFooBankEmployeeCert) + private val fooBankAdmin = fingerprintOf(WotTestVectors.freshFooBankAdminCert) + private val barBankCa = fingerprintOf(WotTestVectors.freshBarBankCaCert) + private val barBankEmployee = fingerprintOf(WotTestVectors.freshBarBankEmployeeCert) private fun fingerprintOf(cert: PGPPublicKeyRing): Fingerprint { return Fingerprint(OpenPgpFingerprint.of(cert).toString()) diff --git a/pgpainless-wot/src/testFixtures/java/org/pgpainless/wot/testfixtures/WotTestVectors.java b/pgpainless-wot/src/testFixtures/java/org/pgpainless/wot/testfixtures/WotTestVectors.java deleted file mode 100644 index d5bacfdd..00000000 --- a/pgpainless-wot/src/testFixtures/java/org/pgpainless/wot/testfixtures/WotTestVectors.java +++ /dev/null @@ -1,290 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package org.pgpainless.wot.testfixtures; - -import java.io.IOException; -import java.io.InputStream; - -import org.bouncycastle.openpgp.PGPException; -import org.bouncycastle.openpgp.PGPPublicKeyRing; -import org.bouncycastle.openpgp.PGPSecretKeyRing; -import org.pgpainless.PGPainless; -import org.pgpainless.algorithm.Trustworthiness; -import org.pgpainless.key.protection.SecretKeyRingProtector; -import org.pgpainless.signature.subpackets.CertificationSubpackets; -import org.pgpainless.util.Passphrase; - -public class WotTestVectors { - - private static WotTestVectors INSTANCE = null; - - public static WotTestVectors getTestVectors() { - if (INSTANCE == null) { - INSTANCE = new WotTestVectors(); - } - return INSTANCE; - } - - public PGPSecretKeyRing getFreshFooBankCaKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCaKey.asc")); - } - - public PGPPublicKeyRing getFreshFooBankCaCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCaCert.asc")); - } - - public String getFooBankCaPassphrase() { - return "superS3cureP4ssphrase"; - } - - public SecretKeyRingProtector getFooBankCaProtector() { - return SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(getFooBankCaPassphrase())); - } - - public PGPSecretKeyRing getFreshFooBankEmployeeKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankEmployeeKey.asc")); - } - - public PGPPublicKeyRing getFreshFooBankEmployeeCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankEmployeeCert.asc")); - } - - public String getFooBankEmployeePassphrase() { - return "iLoveWorking@FooBank"; - } - - public SecretKeyRingProtector getFooBankEmployeeProtector() { - return SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(getFooBankEmployeePassphrase())); - } - - public PGPSecretKeyRing getFreshFooBankAdminKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankAdminKey.asc")); - } - - public PGPPublicKeyRing getFreshFooBankAdminCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankAdminCert.asc")); - } - - public String getFooBankAdminPassphrase() { - return "keepFooBankSecure"; - } - - public SecretKeyRingProtector getFooBankAdminProtector() { - return SecretKeyRingProtector.unlockAnyKeyWith(Passphrase.fromPassword(getFooBankAdminPassphrase())); - } - - public PGPSecretKeyRing getFreshFooBankCustomerKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCustomerKey.asc")); - } - - public PGPPublicKeyRing getFreshFooBankCustomerCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/foobankCustomerCert.asc")); - } - - public PGPSecretKeyRing getFreshBarBankCaKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankCaKey.asc")); - } - - public PGPPublicKeyRing getFreshBarBankCaCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankCaCert.asc")); - } - - public PGPSecretKeyRing getFreshBarBankEmployeeKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankEmployeeKey.asc")); - } - - public PGPPublicKeyRing getFreshBarBankEmployeeCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/barbankEmployeeCert.asc")); - } - - public PGPSecretKeyRing getFreshFakeFooBankEmployeeKey() throws IOException { - return PGPainless.readKeyRing().secretKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/fakeFoobankEmployeeKey.asc")); - } - - public PGPPublicKeyRing getFreshFakeFooBankEmployeeCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/freshly_generated/fakeFoobankEmployeeCert.asc")); - } - - public PGPPublicKeyRing getCrossSignedBarBankCaCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/barbankCaCert.asc")); - } - - public PGPPublicKeyRing getCrossSignedBarBankEmployeeCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/barbankEmployeeCert.asc")); - } - - public PGPPublicKeyRing getCrossSignedFooBankAdminCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/foobankAdminCert.asc")); - } - - public PGPPublicKeyRing getCrossSignedFooBankCaCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/foobankCaCert.asc")); - } - - public PGPPublicKeyRing getCrossSignedFooBankEmployeeCert() throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("cross_signed/foobankEmployeeCert.asc")); - } - - public static void main(String[] args) throws PGPException, IOException { - new WotTestVectors().crossSign(); - } - - // Generate cross signed test vectors from freshly generated - public void crossSign() throws IOException, PGPException { - PGPSecretKeyRing freshFooBankCaKey = getFreshFooBankCaKey(); - PGPPublicKeyRing freshFooBankCaCert = getFreshFooBankCaCert(); - - PGPSecretKeyRing freshFooBankEmployeeKey = getFreshFooBankEmployeeKey(); - PGPPublicKeyRing freshFooBankEmployeeCert = getFreshFooBankEmployeeCert(); - - PGPSecretKeyRing freshFooBankAdminKey = getFreshFooBankAdminKey(); - PGPPublicKeyRing freshFooBankAdminCert = getFreshFooBankAdminCert(); - - PGPSecretKeyRing freshFooBankCustomerKey = getFreshFooBankCustomerKey(); - PGPPublicKeyRing freshFooBankCustomerCert = getFreshFooBankCustomerCert(); - - PGPSecretKeyRing freshBarBankCaKey = getFreshBarBankCaKey(); - PGPPublicKeyRing freshBarBankCaCert = getFreshBarBankCaCert(); - - PGPSecretKeyRing freshBarBankEmployeeKey = getFreshBarBankEmployeeKey(); - PGPPublicKeyRing freshBarBankEmployeeCert = getFreshBarBankEmployeeCert(); - - PGPSecretKeyRing freshFakeFooBankEmployeeKey = getFreshFakeFooBankEmployeeKey(); - PGPPublicKeyRing freshFakeFooBankEmployeeCert = getFreshFakeFooBankEmployeeCert(); - - final String fooBankRegex = "<[^>]+[@.]foobank\\.com>$"; - final String barBankRegex = "<[^>]+[@.]barbank\\.com>$"; - - // Foo CA signs Foo Employee - PGPPublicKeyRing caCertifiedFooBankEmployeeCert = PGPainless.certify() - .userIdOnCertificate("Foo Bank Employee ", freshFooBankEmployeeCert) - .withKey(freshFooBankCaKey, getFooBankCaProtector()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.addNotationData(false, "affiliation@foobank.com", "employee"); - } - }) - .getCertifiedCertificate(); - - // Foo CA signs Foo Admin - PGPPublicKeyRing caCertifiedFooBankAdminCert = PGPainless.certify() - .userIdOnCertificate("Foo Bank Admin ", freshFooBankAdminCert) - .withKey(freshFooBankCaKey, getFooBankCaProtector()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.addNotationData(false, "affiliation@foobank.com", "administrator"); - } - }) - .getCertifiedCertificate(); - - // Foo Employee delegates trust to Foo CA - PGPPublicKeyRing employeeDelegatedCaCert = PGPainless.certify() - .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) - .withKey(freshFooBankEmployeeKey, getFooBankEmployeeProtector()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.setRegularExpression(fooBankRegex); - } - }) - .getCertifiedCertificate(); - - // Foo Admin delegates trust to Foo CA - PGPPublicKeyRing adminDelegatedCaCert = PGPainless.certify() - .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) - .withKey(freshFooBankAdminKey, getFooBankAdminProtector()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.setRegularExpression(fooBankRegex); - } - }) - .getCertifiedCertificate(); - - // Customer delegates trust to Foo CA - PGPPublicKeyRing customerDelegatedCaCert = PGPainless.certify() - .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) - .withKey(freshFooBankCustomerKey, SecretKeyRingProtector.unprotectedKeys()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.setRegularExpression(fooBankRegex); - } - }) - .getCertifiedCertificate(); - - PGPPublicKeyRing mergedFooCa = PGPPublicKeyRing.join(employeeDelegatedCaCert, adminDelegatedCaCert); - mergedFooCa = PGPPublicKeyRing.join(mergedFooCa, customerDelegatedCaCert); - - // Foo Admin delegates trust to Bar CA - PGPPublicKeyRing fooAdminDelegatedBarCa = PGPainless.certify() - .certificate(freshBarBankCaCert, Trustworthiness.fullyTrusted().introducer()) - .withKey(freshFooBankAdminKey, getFooBankAdminProtector()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.setRegularExpression("<[^>]+[@.]barbank\\.com>$"); - } - }).getCertifiedCertificate(); - - // Bar Employee delegates Bar CA - PGPPublicKeyRing barEmployeeDelegatesBarCa = PGPainless.certify() - .certificate(freshBarBankCaCert, Trustworthiness.fullyTrusted().introducer()) - .withKey(freshBarBankEmployeeKey, SecretKeyRingProtector.unprotectedKeys()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.setRegularExpression(barBankRegex); - } - }) - .getCertifiedCertificate(); - - PGPPublicKeyRing mergedBarCa = PGPPublicKeyRing.join(fooAdminDelegatedBarCa, barEmployeeDelegatesBarCa); - - // Bar CA signs Bar Employee - PGPPublicKeyRing barCaCertifiedEmployeeCert = PGPainless.certify() - .userIdOnCertificate("Bar Bank Employee ", freshBarBankEmployeeCert) - .withKey(freshBarBankCaKey, SecretKeyRingProtector.unprotectedKeys()) - .buildWithSubpackets(new CertificationSubpackets.Callback() { - @Override - public void modifyHashedSubpackets(CertificationSubpackets hashedSubpackets) { - hashedSubpackets.addNotationData(false, "affiliation@barbank.com", "employee"); - } - }) - .getCertifiedCertificate(); - - // CHECKSTYLE:OFF - System.out.println("Foo Employee"); - System.out.println(PGPainless.asciiArmor(caCertifiedFooBankEmployeeCert)); - - System.out.println("Foo Admin"); - System.out.println(PGPainless.asciiArmor(caCertifiedFooBankAdminCert)); - - System.out.println("Foo CA"); - System.out.println(PGPainless.asciiArmor(mergedFooCa)); - - System.out.println("Bar CA"); - System.out.println(PGPainless.asciiArmor(mergedBarCa)); - - System.out.println("Bar Employee"); - System.out.println(PGPainless.asciiArmor(barCaCertifiedEmployeeCert)); - // CHECKSTYLE:ON - } - - private static InputStream getTestResourceInputStream(String resource) { - InputStream inputStream = WotTestVectors.class.getClassLoader().getResourceAsStream(resource); - if (inputStream == null) { - throw new IllegalArgumentException(String.format("Unknown resource %s", resource)); - } - return inputStream; - } - - public PGPPublicKeyRing getFelixKey() - throws IOException { - return PGPainless.readKeyRing().publicKeyRing(getTestResourceInputStream("test_vectors/anomalies/felix.pub")); - } -} diff --git a/pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/AdHocVectors.kt b/pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/AdHocVectors.kt new file mode 100644 index 00000000..20f1c4f1 --- /dev/null +++ b/pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/AdHocVectors.kt @@ -0,0 +1,113 @@ +package org.pgpainless.wot.testfixtures + +import org.bouncycastle.openpgp.PGPKeyRing +import org.bouncycastle.openpgp.PGPPublicKeyRing +import org.bouncycastle.openpgp.PGPPublicKeyRingCollection +import org.bouncycastle.openpgp.PGPSecretKeyRing +import org.pgpainless.PGPainless +import org.pgpainless.key.OpenPgpFingerprint +import org.pgpainless.key.generation.type.rsa.RsaLength +import org.pgpainless.key.protection.SecretKeyRingProtector +import org.pgpainless.signature.subpackets.CertificationSubpackets +import org.pgpainless.signature.subpackets.CertificationSubpackets.Callback +import org.pgpainless.wot.KeyRingCertificateStore +import org.pgpainless.wot.dijkstra.sq.Fingerprint +import pgp.certificate_store.PGPCertificateStore + +interface AdHocVectors { + + /** + * When doing backwards propagation, we find paths from all nodes to the + * target. Since we don't stop when we reach a root, the returned path + * should still be optimal. Consider: + * + * A --- 120/10 ---> B --- 120/10 ---> C --- 120/10 ---> Target + * \ / + * `--- 50/10 ---> Y --- 50/10 ---> Z --- 50/10 --------' + * When the root is B, then the path that we find for A should be A -> B -> C -> Target, not A -> Y -> Z -> Target. + */ + class BestViaRoot : AdHocVectors { + val aliceUID: String = "Alice " + val aliceKey: PGPSecretKeyRing = PGPainless.generateKeyRing().modernKeyRing(aliceUID) + val aliceCert = PGPPublicKeyRing(aliceKey) + val aliceFingerprint = Fingerprint(aliceKey) + + val bobUID = "Bob " + val bobKey: PGPSecretKeyRing = PGPainless.generateKeyRing().simpleRsaKeyRing(bobUID, RsaLength._3072) + val bobCert = PGPPublicKeyRing(bobKey) + val bobFingerprint = Fingerprint(bobKey) + + val carolUID = "Carol " + val carolKey: PGPSecretKeyRing = PGPainless.generateKeyRing().simpleEcKeyRing(carolUID) + val carolCert = PGPPublicKeyRing(carolKey) + val carolFingerprint = Fingerprint(carolKey) + + val targetUID = "Tanja " + val targetKey: PGPSecretKeyRing = PGPainless.generateKeyRing().modernKeyRing(targetUID) + val targetCert = PGPPublicKeyRing(targetKey) + val targetFingerprint = Fingerprint(targetKey) + + val yellowUID = "Yellow " + val yellowKey: PGPSecretKeyRing = PGPainless.generateKeyRing().modernKeyRing(yellowUID) + val yellowCert = PGPPublicKeyRing(yellowKey) + val yellowFingerprint = Fingerprint(yellowKey) + + val zebraUID = "Zebra " + val zebraKey: PGPSecretKeyRing = PGPainless.generateKeyRing().modernKeyRing(zebraUID) + val zebraCert = PGPPublicKeyRing(zebraKey) + val zebraFingerprint = Fingerprint(zebraKey) + + override val publicKeyRingCollection: PGPPublicKeyRingCollection + get() { + val signedCerts = listOf( + targetCert.let { + // C ---120/10--> Target + certify(issuer = carolKey, target = it, amount = 120, depth = 10) + }.let { + // Z ---50/10---> Target + certify(issuer = zebraKey, target = it, amount = 50, depth = 10) + }, + carolCert.let { + // B ---120/10--> C + certify(issuer = bobKey, target = it, amount = 120, depth = 10) + }, + bobCert.let { + // A ---120/10--> B + certify(issuer = aliceKey, target = it, amount = 120, depth = 10) + }, + zebraCert.let { + // Y ---50/10--> Z + certify(issuer = yellowKey, target = it, amount = 50, depth = 10) + }, + yellowCert.let { + // A ---50/10--> Y + certify(issuer = aliceKey, target = it, amount = 50, depth = 10) + }) + return PGPPublicKeyRingCollection(signedCerts) + } + } + + val publicKeyRingCollection: PGPPublicKeyRingCollection + + val pgpCertificateStore: PGPCertificateStore + get() = KeyRingCertificateStore(publicKeyRingCollection) + + fun certify(issuer: PGPSecretKeyRing, + target: PGPPublicKeyRing, + userId: String = target.publicKey.userIDs.next()!!, + amount: Int, + depth: Int): PGPPublicKeyRing = PGPainless.certify() + .userIdOnCertificate(userId, target) + .withKey(issuer, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(object : Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets?) { + hashedSubpackets!!.setTrust(depth, amount) + } + }).certifiedCertificate + + fun PGPPublicKeyRing(secretKey: PGPSecretKeyRing): PGPPublicKeyRing = + PGPainless.extractCertificate(secretKey) + + fun Fingerprint(keyRing: PGPKeyRing): Fingerprint = + Fingerprint(OpenPgpFingerprint.of(keyRing).toString()) +} \ No newline at end of file diff --git a/pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/WotTestVectors.kt b/pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/WotTestVectors.kt new file mode 100644 index 00000000..20451767 --- /dev/null +++ b/pgpainless-wot/src/testFixtures/kotlin/org/pgpainless/wot/testfixtures/WotTestVectors.kt @@ -0,0 +1,245 @@ +package org.pgpainless.wot.testfixtures + +import org.bouncycastle.openpgp.PGPException +import org.bouncycastle.openpgp.PGPPublicKeyRing +import org.bouncycastle.openpgp.PGPSecretKeyRing +import org.pgpainless.PGPainless +import org.pgpainless.algorithm.Trustworthiness +import org.pgpainless.key.protection.SecretKeyRingProtector +import org.pgpainless.signature.subpackets.CertificationSubpackets +import org.pgpainless.util.Passphrase +import java.io.IOException +import java.io.InputStream + +class WotTestVectors { + + companion object { + + @JvmStatic + fun getTestResource(resource: String): InputStream { + val input = WotTestVectors::class.java.classLoader.getResourceAsStream(resource) + return requireNotNull(input) { + "Unknown resource $resource" + } + } + + @JvmStatic + val freshFooBankCaKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/foobankCaKey.asc"))!! + + @JvmStatic + val freshFooBankCaCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/foobankCaCert.asc"))!! + + @JvmStatic + val fooBankCaPassphrase = "superS3cureP4ssphrase" + + @JvmStatic + val fooBankCaProtector: SecretKeyRingProtector = SecretKeyRingProtector.unlockAnyKeyWith( + Passphrase.fromPassword(fooBankCaPassphrase)) + + @JvmStatic + val freshFooBankEmployeeKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/foobankEmployeeKey.asc"))!! + + @JvmStatic + val freshFooBankEmployeeCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/foobankEmployeeCert.asc"))!! + + @JvmStatic + val fooBankEmployeePassphrase = "iLoveWorking@FooBank" + + @JvmStatic + val fooBankEmployeeProtector: SecretKeyRingProtector = SecretKeyRingProtector.unlockAnyKeyWith( + Passphrase.fromPassword(fooBankEmployeePassphrase)) + + @JvmStatic + val freshFooBankAdminKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/foobankAdminKey.asc"))!! + + @JvmStatic + val freshFooBankAdminCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/foobankAdminCert.asc"))!! + + @JvmStatic + val fooBankAdminPassphrase = "keepFooBankSecure" + + @JvmStatic + val fooBankAdminProtector: SecretKeyRingProtector = SecretKeyRingProtector.unlockAnyKeyWith( + Passphrase.fromPassword(fooBankAdminPassphrase)) + + @JvmStatic + val freshFooBankCustomerKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/foobankCustomerKey.asc"))!! + + @JvmStatic + val freshFooBankCustomerCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/foobankCustomerCert.asc"))!! + + @JvmStatic + val fooBankCustomerProtector: SecretKeyRingProtector = SecretKeyRingProtector.unprotectedKeys() + + @JvmStatic + val freshBarBankCaKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/barbankCaKey.asc"))!! + + @JvmStatic + val freshBarBankCaCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/barbankCaCert.asc"))!! + + @JvmStatic + val barBankCaProtector: SecretKeyRingProtector = SecretKeyRingProtector.unprotectedKeys() + + @JvmStatic + val freshBarBankEmployeeKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/barbankEmployeeKey.asc"))!! + + @JvmStatic + val freshBarBankEmployeeCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/barbankEmployeeCert.asc"))!! + + @JvmStatic + val freshFakeFooBankEmployeeKey: PGPSecretKeyRing = PGPainless.readKeyRing().secretKeyRing( + getTestResource("test_vectors/freshly_generated/fakeFoobankEmployeeKey.asc"))!! + + @JvmStatic + val freshFakeFooBankEmployeeCert: PGPPublicKeyRing = PGPainless.readKeyRing().publicKeyRing( + getTestResource("test_vectors/freshly_generated/fakeFoobankEmployeeCert.asc"))!! + + + @Throws(IOException::class) + fun getCrossSignedBarBankCaCert(): PGPPublicKeyRing? { + return PGPainless.readKeyRing().publicKeyRing(getTestResource("cross_signed/barbankCaCert.asc")) + } + + @Throws(IOException::class) + fun getCrossSignedBarBankEmployeeCert(): PGPPublicKeyRing? { + return PGPainless.readKeyRing().publicKeyRing(getTestResource("cross_signed/barbankEmployeeCert.asc")) + } + + @Throws(IOException::class) + fun getCrossSignedFooBankAdminCert(): PGPPublicKeyRing? { + return PGPainless.readKeyRing().publicKeyRing(getTestResource("cross_signed/foobankAdminCert.asc")) + } + + @Throws(IOException::class) + fun getCrossSignedFooBankCaCert(): PGPPublicKeyRing? { + return PGPainless.readKeyRing().publicKeyRing(getTestResource("cross_signed/foobankCaCert.asc")) + } + + @Throws(IOException::class) + fun getCrossSignedFooBankEmployeeCert(): PGPPublicKeyRing? { + return PGPainless.readKeyRing().publicKeyRing(getTestResource("cross_signed/foobankEmployeeCert.asc")) + } + + // Generate cross signed test vectors from freshly generated + @Throws(IOException::class, PGPException::class) + fun crossSign() { + val fooBankRegex = "<[^>]+[@.]foobank\\.com>$" + val barBankRegex = "<[^>]+[@.]barbank\\.com>$" + + // Foo CA signs Foo Employee + val caCertifiedFooBankEmployeeCert = PGPainless.certify() + .userIdOnCertificate("Foo Bank Employee ", freshFooBankEmployeeCert) + .withKey(freshFooBankCaKey, fooBankCaProtector) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.addNotationData(false, "affiliation@foobank.com", "employee") + } + }) + .certifiedCertificate + + // Foo CA signs Foo Admin + val caCertifiedFooBankAdminCert = PGPainless.certify() + .userIdOnCertificate("Foo Bank Admin ", freshFooBankAdminCert) + .withKey(freshFooBankCaKey, fooBankCaProtector) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.addNotationData(false, "affiliation@foobank.com", "administrator") + } + }) + .certifiedCertificate + + // Foo Employee delegates trust to Foo CA + val employeeDelegatedCaCert = PGPainless.certify() + .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankEmployeeKey, fooBankEmployeeProtector) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.setRegularExpression(fooBankRegex) + } + }) + .certifiedCertificate + + // Foo Admin delegates trust to Foo CA + val adminDelegatedCaCert = PGPainless.certify() + .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankAdminKey, fooBankAdminProtector) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.setRegularExpression(fooBankRegex) + } + }) + .certifiedCertificate + + // Customer delegates trust to Foo CA + val customerDelegatedCaCert = PGPainless.certify() + .certificate(freshFooBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankCustomerKey, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.setRegularExpression(fooBankRegex) + } + }) + .certifiedCertificate + var mergedFooCa = PGPPublicKeyRing.join(employeeDelegatedCaCert, adminDelegatedCaCert) + mergedFooCa = PGPPublicKeyRing.join(mergedFooCa, customerDelegatedCaCert) + + // Foo Admin delegates trust to Bar CA + val fooAdminDelegatedBarCa = PGPainless.certify() + .certificate(freshBarBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshFooBankAdminKey, fooBankAdminProtector) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.setRegularExpression("<[^>]+[@.]barbank\\.com>$") + } + }).certifiedCertificate + + // Bar Employee delegates Bar CA + val barEmployeeDelegatesBarCa = PGPainless.certify() + .certificate(freshBarBankCaCert, Trustworthiness.fullyTrusted().introducer()) + .withKey(freshBarBankEmployeeKey, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.setRegularExpression(barBankRegex) + } + }) + .certifiedCertificate + val mergedBarCa = PGPPublicKeyRing.join(fooAdminDelegatedBarCa, barEmployeeDelegatesBarCa) + + // Bar CA signs Bar Employee + val barCaCertifiedEmployeeCert = PGPainless.certify() + .userIdOnCertificate("Bar Bank Employee ", freshBarBankEmployeeCert) + .withKey(freshBarBankCaKey, SecretKeyRingProtector.unprotectedKeys()) + .buildWithSubpackets(object : CertificationSubpackets.Callback { + override fun modifyHashedSubpackets(hashedSubpackets: CertificationSubpackets) { + hashedSubpackets.addNotationData(false, "affiliation@barbank.com", "employee") + } + }) + .certifiedCertificate + + // CHECKSTYLE:OFF + println("Foo Employee") + println(PGPainless.asciiArmor(caCertifiedFooBankEmployeeCert)) + println("Foo Admin") + println(PGPainless.asciiArmor(caCertifiedFooBankAdminCert)) + println("Foo CA") + println(PGPainless.asciiArmor(mergedFooCa)) + println("Bar CA") + println(PGPainless.asciiArmor(mergedBarCa)) + println("Bar Employee") + println(PGPainless.asciiArmor(barCaCertifiedEmployeeCert)) + // CHECKSTYLE:ON + } + } +} \ No newline at end of file