mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-10 18:59:39 +02:00
Wip: Start implementing a SOP client
This commit is contained in:
parent
ff8c6d8b6d
commit
9d3ad01dfc
8 changed files with 254 additions and 1 deletions
|
@ -0,0 +1,48 @@
|
|||
package org.pgpainless.sop;
|
||||
|
||||
import org.pgpainless.sop.commands.ExtractCert;
|
||||
import org.pgpainless.sop.commands.GenerateKey;
|
||||
import org.pgpainless.sop.commands.Sign;
|
||||
import org.pgpainless.sop.commands.Version;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(
|
||||
subcommands = {
|
||||
Version.class,
|
||||
GenerateKey.class,
|
||||
ExtractCert.class,
|
||||
Sign.class
|
||||
}
|
||||
)
|
||||
public class PGPainlessCLI implements Runnable {
|
||||
|
||||
public static void main(String[] args) {
|
||||
interpret(args);
|
||||
// generateKey();
|
||||
}
|
||||
|
||||
public static void interpret(String... args) {
|
||||
CommandLine.run(new PGPainlessCLI(), args);
|
||||
}
|
||||
|
||||
private static void version() {
|
||||
CommandLine.run(new PGPainlessCLI(), "version");
|
||||
}
|
||||
|
||||
private static void generateKey() {
|
||||
interpret("generate-key", "--armor", "Alice Example <alice@wonderland.lit>");
|
||||
}
|
||||
|
||||
private static void extractCert() {
|
||||
CommandLine.run(new PGPainlessCLI(), "extract-cert");
|
||||
}
|
||||
|
||||
private static void sign() {
|
||||
interpret("sign", "--armor", "--as=text", "alice.sec");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
}
|
16
pgpainless-sop/src/main/java/org/pgpainless/sop/Print.java
Normal file
16
pgpainless-sop/src/main/java/org/pgpainless/sop/Print.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
package org.pgpainless.sop;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.pgpainless.util.ArmorUtils;
|
||||
|
||||
public class Print {
|
||||
|
||||
public static String toString(byte[] bytes, boolean armor) throws IOException {
|
||||
if (armor) {
|
||||
return ArmorUtils.toAsciiArmoredString(bytes);
|
||||
} else {
|
||||
return new String(bytes, "UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.pgpainless.sop.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.sop.Print;
|
||||
import org.pgpainless.util.BCUtil;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "extract-cert")
|
||||
public class ExtractCert implements Runnable {
|
||||
|
||||
@CommandLine.Option(names = {"--armor"}, description = "ASCII Armor the output")
|
||||
boolean armor = false;
|
||||
|
||||
@CommandLine.Option(names = {"--no-armor"})
|
||||
boolean noArmor = false;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.readKeyRing().secretKeyRing(System.in);
|
||||
PGPPublicKeyRing publicKeys = BCUtil.publicKeyRingFromSecretKeyRing(secretKeys);
|
||||
|
||||
System.out.println(Print.toString(publicKeys.getEncoded(), !noArmor));
|
||||
} catch (IOException | PGPException e) {
|
||||
System.err.println("Error extracting certificate from keys;");
|
||||
System.err.println(e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package org.pgpainless.sop.commands;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.sop.Print;
|
||||
import org.pgpainless.util.ArmorUtils;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "generate-key")
|
||||
public class GenerateKey implements Runnable {
|
||||
|
||||
@CommandLine.Option(names = {"--armor"}, description = "ASCII Armor the output")
|
||||
boolean armor = false;
|
||||
|
||||
@CommandLine.Option(names = {"--no-armor"})
|
||||
boolean noArmor = false;
|
||||
|
||||
@CommandLine.Parameters
|
||||
String userId;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing().simpleEcKeyRing(userId).getSecretKeys();
|
||||
|
||||
System.out.println(Print.toString(secretKeys.getEncoded(), !noArmor));
|
||||
|
||||
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | PGPException | IOException e) {
|
||||
System.err.println("Error creating OpenPGP key:");
|
||||
System.err.println(e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package org.pgpainless.sop.commands;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPException;
|
||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||
import org.bouncycastle.openpgp.PGPSignature;
|
||||
import org.bouncycastle.util.io.Streams;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.encryption_signing.EncryptionStream;
|
||||
import org.pgpainless.key.protection.UnprotectedKeysProtector;
|
||||
import org.pgpainless.sop.Print;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "sign")
|
||||
public class Sign implements Runnable {
|
||||
|
||||
public enum Type {
|
||||
binary,
|
||||
text
|
||||
}
|
||||
|
||||
@CommandLine.Option(names = {"--armor"}, description = "ASCII Armor the output")
|
||||
boolean armor = false;
|
||||
|
||||
@CommandLine.Option(names = {"--no-armor"})
|
||||
boolean noArmor = false;
|
||||
|
||||
@CommandLine.Option(names = "--as", description = "Defaults to 'binary'. If '--as=text' and the input data is not valid UTF-8, sign fails with return code 53.")
|
||||
Type type;
|
||||
|
||||
@CommandLine.Parameters
|
||||
File secretKeyFile;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PGPSecretKeyRing secretKeys;
|
||||
try {
|
||||
secretKeys = PGPainless.readKeyRing().secretKeyRing(new FileInputStream(secretKeyFile));
|
||||
} catch (IOException | PGPException e) {
|
||||
System.err.println("Error reading secret key ring.");
|
||||
System.err.println(e.getMessage());
|
||||
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
EncryptionStream encryptionStream = PGPainless.createEncryptor()
|
||||
.onOutputStream(out)
|
||||
.doNotEncrypt()
|
||||
.createDetachedSignature()
|
||||
.signWith(new UnprotectedKeysProtector(), secretKeys)
|
||||
.noArmor();
|
||||
|
||||
Streams.pipeAll(System.in, encryptionStream);
|
||||
encryptionStream.close();
|
||||
|
||||
PGPSignature signature = encryptionStream.getResult().getSignatures().iterator().next();
|
||||
|
||||
System.out.println(Print.toString(signature.getEncoded(), !noArmor));
|
||||
} catch (PGPException | IOException e) {
|
||||
System.err.println("Error signing data.");
|
||||
System.err.println(e.getMessage());
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.pgpainless.sop.commands;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "version")
|
||||
public class Version implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("PGPainless CLI version 0.0.1");
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue