Create basic WKDCLI implementation

This commit is contained in:
Paul Schaub 2022-02-21 14:16:55 +01:00
parent a006aa11b9
commit 9abe217de0
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
8 changed files with 168 additions and 30 deletions

View file

@ -16,12 +16,37 @@ dependencies {
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
// https://todd.ginsberg.com/post/testing-system-exit/
testImplementation 'com.ginsberg:junit5-system-exit:1.1.2'
testImplementation 'org.mockito:mockito-core:4.3.1'
implementation("org.pgpainless:pgpainless-core:1.1.0")
implementation project(':wkd-java')
implementation "info.picocli:picocli:4.6.3"
// Logging
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation 'org.slf4j:slf4j-nop:1.7.36'
}
test {
useJUnitPlatform()
}
mainClassName = 'pgp.wkd.cli.WKDCLI'
jar {
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
manifest {
attributes 'Main-Class': "$mainClassName"
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
}

View file

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.wkd.cli;
public class MissingUserIdException extends Exception {
public MissingUserIdException() {
super();
}
}

View file

@ -4,6 +4,27 @@
package pgp.wkd.cli;
import pgp.wkd.cli.command.Fetch;
import picocli.CommandLine;
@CommandLine.Command(
subcommands = {
CommandLine.HelpCommand.class,
Fetch.class
}
)
public class WKDCLI {
public static void main(String[] args) {
int exitCode = execute(args);
if (exitCode != 0) {
System.exit(exitCode);
}
}
public static int execute(String[] args) {
return new CommandLine(WKDCLI.class)
.setCommandName("wkdcli")
.execute(args);
}
}

View file

@ -0,0 +1,88 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package pgp.wkd.cli.command;
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.pgpainless.PGPainless;
import org.pgpainless.key.info.KeyRingInfo;
import pgp.wkd.IWKDFetcher;
import pgp.wkd.JavaHttpRequestWKDFetcher;
import pgp.wkd.WKDAddress;
import pgp.wkd.WKDAddressHelper;
import pgp.wkd.cli.MissingUserIdException;
import picocli.CommandLine;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
@CommandLine.Command(
name = "fetch",
description = "Fetch an OpenPGP Certificate via the Web Key Directory"
)
public class Fetch implements Runnable {
@CommandLine.Parameters(
index = "0",
arity = "1",
paramLabel = "USERID",
description = "Certificate User-ID"
)
String userId;
@CommandLine.Option(
names = {"-a", "--armor"},
description = "ASCII Armor the output"
)
boolean armor = false;
IWKDFetcher fetcher = new JavaHttpRequestWKDFetcher();
@Override
public void run() {
String email;
try {
email = WKDAddressHelper.emailFromUserId(userId);
} catch (IllegalArgumentException e) {
email = userId;
}
WKDAddress address = WKDAddress.fromEmail(email);
try (InputStream inputStream = fetcher.fetch(address)) {
PGPPublicKeyRing cert = PGPainless.readKeyRing().publicKeyRing(inputStream);
KeyRingInfo info = PGPainless.inspectKeyRing(cert);
List<String> userIds = info.getValidAndExpiredUserIds();
boolean containsEmail = false;
for (String certUserId : userIds) {
if (certUserId.contains("<" + email + ">") || certUserId.equals(email)) {
containsEmail = true;
break;
}
}
if (!containsEmail) {
throw new MissingUserIdException();
}
if (armor) {
OutputStream out = new ArmoredOutputStream(System.out);
cert.encode(out);
out.close();
} else {
cert.encode(System.out);
}
} catch (IOException e) {
System.err.println("Could not fetch certificate.");
e.printStackTrace();
System.exit(1);
} catch (MissingUserIdException e) {
System.err.println("Fetched certificate does not contain email address " + email);
System.exit(1);
}
}
}

View file

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
/**
* Subcommands of the WKDCLI tool.
*/
package pgp.wkd.cli.command;

View file

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
/**
* Command Line Interface for fetching OpenPGP Certificates from the Web Key Directory.
*/
package pgp.wkd.cli;