mirror of
https://codeberg.org/PGPainless/wkd-java.git
synced 2024-12-22 13:47:58 +01:00
Create basic WKDCLI implementation
This commit is contained in:
parent
a006aa11b9
commit
9abe217de0
8 changed files with 168 additions and 30 deletions
|
@ -72,7 +72,7 @@ allprojects {
|
|||
project.ext {
|
||||
junitVersion = '5.8.2'
|
||||
slf4jVersion = '1.7.32'
|
||||
logbackVersion = '1.2.9'
|
||||
logbackVersion = '1.2.10'
|
||||
rootConfigDir = new File(rootDir, 'config')
|
||||
gitCommit = getGitCommit()
|
||||
isContinuousIntegrationEnvironment = Boolean.parseBoolean(System.getenv('CI'))
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
88
wkd-java-cli/src/main/java/pgp/wkd/cli/command/Fetch.java
Normal file
88
wkd-java-cli/src/main/java/pgp/wkd/cli/command/Fetch.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
8
wkd-java-cli/src/main/java/pgp/wkd/cli/package-info.java
Normal file
8
wkd-java-cli/src/main/java/pgp/wkd/cli/package-info.java
Normal 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;
|
|
@ -26,16 +26,17 @@ public class JavaHttpRequestWKDFetcher implements IWKDFetcher {
|
|||
return tryFetchUri(advanced);
|
||||
} catch (IOException e) {
|
||||
advancedException = e;
|
||||
LOGGER.debug("Could not fetch key using advanced method from " + advanced.toString(), e);
|
||||
LOGGER.debug("Could not fetch key using advanced method from " + advanced.toString(), advancedException);
|
||||
}
|
||||
|
||||
URI direct = address.getDirectMethodURI();
|
||||
try {
|
||||
return tryFetchUri(direct);
|
||||
} catch (IOException e) {
|
||||
advancedException.addSuppressed(e);
|
||||
// we would like to use addSuppressed eventually, but Android API 10 does no support it
|
||||
// e.addSuppressed(advancedException);
|
||||
LOGGER.debug("Could not fetch key using direct method from " + direct.toString(), e);
|
||||
throw advancedException;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,9 +50,8 @@ public class JavaHttpRequestWKDFetcher implements IWKDFetcher {
|
|||
|
||||
int status = con.getResponseCode();
|
||||
if (status != 200) {
|
||||
throw new ConnectException("Connection was unsuccessful");
|
||||
throw new ConnectException("Connecting to '" + uri + "' failed. Status: " + status);
|
||||
}
|
||||
LOGGER.debug("Successfully fetched key from " + uri);
|
||||
return con.getInputStream();
|
||||
}
|
||||
|
||||
|
@ -59,28 +59,4 @@ public class JavaHttpRequestWKDFetcher implements IWKDFetcher {
|
|||
URL url = uri.toURL();
|
||||
return (HttpURLConnection) url.openConnection();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 1) {
|
||||
throw new IllegalArgumentException("Expect a single argument email address");
|
||||
}
|
||||
|
||||
String email = args[0];
|
||||
WKDAddress address = WKDAddress.fromEmail(email);
|
||||
|
||||
JavaHttpRequestWKDFetcher fetch = new JavaHttpRequestWKDFetcher();
|
||||
try {
|
||||
InputStream inputStream = fetch.fetch(address);
|
||||
byte[] buf = new byte[4096];
|
||||
int read;
|
||||
while ((read = inputStream.read(buf)) != -1) {
|
||||
System.out.write(buf, 0, read);
|
||||
}
|
||||
inputStream.close();
|
||||
System.exit(0);
|
||||
} catch (IOException e) {
|
||||
LOGGER.debug("Could not fetch key.", e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue