mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2025-09-09 10:19:47 +02:00
WiP: Implement first prototypes of all SOP commands for external binaries
This commit is contained in:
parent
efec4d9110
commit
a63b29fe80
21 changed files with 1473 additions and 146 deletions
40
external-sop/src/main/java/sop/external/operation/ArmorExternal.java
vendored
Normal file
40
external-sop/src/main/java/sop/external/operation/ArmorExternal.java
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.Ready;
|
||||
import sop.enums.ArmorLabel;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.Armor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Properties;
|
||||
import java.util.List;
|
||||
|
||||
public class ArmorExternal implements Armor {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
public ArmorExternal(String binary, Properties environment) {
|
||||
commandList.add(binary);
|
||||
commandList.add("armor");
|
||||
envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Armor label(ArmorLabel label) throws SOPGPException.UnsupportedOption {
|
||||
commandList.add("--label=" + label);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ready data(InputStream data) throws SOPGPException.BadData, IOException {
|
||||
return ExternalSOP.ready(Runtime.getRuntime(), commandList, envList);
|
||||
}
|
||||
}
|
33
external-sop/src/main/java/sop/external/operation/DearmorExternal.java
vendored
Normal file
33
external-sop/src/main/java/sop/external/operation/DearmorExternal.java
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.Ready;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.Dearmor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class DearmorExternal implements Dearmor {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
public DearmorExternal(String binary, Properties environment) {
|
||||
commandList.add(binary);
|
||||
commandList.add("dearmor");
|
||||
envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ready data(InputStream data) throws SOPGPException.BadData, IOException {
|
||||
return ExternalSOP.ready(Runtime.getRuntime(), commandList, envList);
|
||||
}
|
||||
}
|
139
external-sop/src/main/java/sop/external/operation/DecryptExternal.java
vendored
Normal file
139
external-sop/src/main/java/sop/external/operation/DecryptExternal.java
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.DecryptionResult;
|
||||
import sop.ReadyWithResult;
|
||||
import sop.SessionKey;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.Decrypt;
|
||||
import sop.util.UTCUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class DecryptExternal implements Decrypt {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
private int verifyWithCounter = 0;
|
||||
private int withSessionKeyCounter = 0;
|
||||
private int withPasswordCounter = 0;
|
||||
private int keyCounter = 0;
|
||||
private int withKeyPasswordCounter = 0;
|
||||
|
||||
public DecryptExternal(String binary, Properties environment) {
|
||||
this.commandList.add(binary);
|
||||
this.commandList.add("decrypt");
|
||||
this.envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt verifyNotBefore(Date timestamp)
|
||||
throws SOPGPException.UnsupportedOption {
|
||||
this.commandList.add("--not-before=" + UTCUtil.formatUTCDate(timestamp));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt verifyNotAfter(Date timestamp)
|
||||
throws SOPGPException.UnsupportedOption {
|
||||
this.commandList.add("--not-after=" + UTCUtil.formatUTCDate(timestamp));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt verifyWithCert(InputStream cert)
|
||||
throws SOPGPException.BadData, SOPGPException.UnsupportedAsymmetricAlgo, IOException {
|
||||
String envVar = "VERIFY_WITH_" + verifyWithCounter++;
|
||||
commandList.add("--verify-with=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(cert));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt withSessionKey(SessionKey sessionKey)
|
||||
throws SOPGPException.UnsupportedOption {
|
||||
String envVar = "SESSION_KEY_" + withSessionKeyCounter++;
|
||||
commandList.add("--with-session-key=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + sessionKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt withPassword(String password)
|
||||
throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
String envVar = "PASSWORD_" + withPasswordCounter++;
|
||||
commandList.add("--with-password=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + password);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt withKey(InputStream key)
|
||||
throws SOPGPException.BadData, SOPGPException.UnsupportedAsymmetricAlgo, IOException {
|
||||
String envVar = "KEY_" + keyCounter++;
|
||||
commandList.add("@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(key));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt withKeyPassword(byte[] password)
|
||||
throws SOPGPException.UnsupportedOption, SOPGPException.PasswordNotHumanReadable {
|
||||
String envVar = "KEY_PASSWORD_" + withKeyPasswordCounter++;
|
||||
commandList.add("--with-key-password=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + new String(password));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadyWithResult<DecryptionResult> ciphertext(InputStream ciphertext)
|
||||
throws SOPGPException.BadData, SOPGPException.MissingArg, SOPGPException.CannotDecrypt,
|
||||
SOPGPException.KeyIsProtected, IOException {
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command, env);
|
||||
OutputStream processOut = process.getOutputStream();
|
||||
InputStream processIn = process.getInputStream();
|
||||
|
||||
return new ReadyWithResult<DecryptionResult>() {
|
||||
@Override
|
||||
public DecryptionResult writeTo(OutputStream outputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = ciphertext.read(buf)) > 0) {
|
||||
processOut.write(buf, 0, r);
|
||||
}
|
||||
|
||||
ciphertext.close();
|
||||
processOut.close();
|
||||
|
||||
while ((r = processIn.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0 , r);
|
||||
}
|
||||
|
||||
processIn.close();
|
||||
outputStream.close();
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
|
||||
return new DecryptionResult(null, Collections.emptyList()); // TODO
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +1,102 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.ReadyWithResult;
|
||||
import sop.SigningResult;
|
||||
import sop.enums.SignAs;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.DetachedSign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class DetachedSignExternal implements DetachedSign {
|
||||
|
||||
private boolean noArmor;
|
||||
private byte[] keyPassword;
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
private int withKeyPasswordCounter = 0;
|
||||
private int keyCounter = 0;
|
||||
|
||||
public DetachedSignExternal(String binary, Properties properties) {
|
||||
commandList.add(binary);
|
||||
commandList.add("sign");
|
||||
envList = ExternalSOP.propertiesToEnv(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedSign noArmor() {
|
||||
this.noArmor = true;
|
||||
commandList.add("--no-armor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedSign key(InputStream key) throws SOPGPException.KeyCannotSign, SOPGPException.BadData, SOPGPException.UnsupportedAsymmetricAlgo, IOException {
|
||||
return null;
|
||||
String envVar = "KEY_" + keyCounter++;
|
||||
commandList.add("@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(key));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedSign withKeyPassword(byte[] password) throws SOPGPException.UnsupportedOption, SOPGPException.PasswordNotHumanReadable {
|
||||
this.keyPassword = password;
|
||||
String envVar = "WITH_KEY_PASSWORD_" + withKeyPasswordCounter++;
|
||||
commandList.add("--with-key-password=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + new String(password));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedSign mode(SignAs mode) throws SOPGPException.UnsupportedOption {
|
||||
return null;
|
||||
commandList.add("--as=" + mode);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadyWithResult<SigningResult> data(InputStream data) throws IOException, SOPGPException.KeyIsProtected, SOPGPException.ExpectedText {
|
||||
return null;
|
||||
public ReadyWithResult<SigningResult> data(InputStream data)
|
||||
throws IOException, SOPGPException.KeyIsProtected, SOPGPException.ExpectedText {
|
||||
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command, env);
|
||||
OutputStream processOut = process.getOutputStream();
|
||||
InputStream processIn = process.getInputStream();
|
||||
|
||||
return new ReadyWithResult<SigningResult>() {
|
||||
@Override
|
||||
public SigningResult writeTo(OutputStream outputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = data.read(buf)) > 0) {
|
||||
processOut.write(buf, 0, r);
|
||||
}
|
||||
|
||||
data.close();
|
||||
processOut.close();
|
||||
|
||||
while ((r = processIn.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0 , r);
|
||||
}
|
||||
|
||||
processIn.close();
|
||||
outputStream.close();
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
|
||||
return SigningResult.builder().build();
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
108
external-sop/src/main/java/sop/external/operation/DetachedVerifyExternal.java
vendored
Normal file
108
external-sop/src/main/java/sop/external/operation/DetachedVerifyExternal.java
vendored
Normal file
|
@ -0,0 +1,108 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.Verification;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.DetachedVerify;
|
||||
import sop.operation.VerifySignatures;
|
||||
import sop.util.UTCUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
public class DetachedVerifyExternal implements DetachedVerify {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
private Set<InputStream> certs = new HashSet<>();
|
||||
private InputStream signatures;
|
||||
private int certCounter = 0;
|
||||
|
||||
public DetachedVerifyExternal(String binary, Properties environment) {
|
||||
commandList.add(binary);
|
||||
commandList.add("verify");
|
||||
envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedVerify notBefore(Date timestamp) throws SOPGPException.UnsupportedOption {
|
||||
commandList.add("--not-before=" + UTCUtil.formatUTCDate(timestamp));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedVerify notAfter(Date timestamp) throws SOPGPException.UnsupportedOption {
|
||||
commandList.add("--not-after=" + UTCUtil.formatUTCDate(timestamp));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachedVerify cert(InputStream cert) throws SOPGPException.BadData, IOException {
|
||||
this.certs.add(cert);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifySignatures signatures(InputStream signatures) throws SOPGPException.BadData, IOException {
|
||||
this.signatures = signatures;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Verification> data(InputStream data) throws IOException, SOPGPException.NoSignature, SOPGPException.BadData {
|
||||
commandList.add("@ENV:SIGNATURE");
|
||||
envList.add("SIGNATURE=" + ExternalSOP.readFully(signatures));
|
||||
|
||||
for (InputStream cert : certs) {
|
||||
String envVar = "CERT_" + certCounter++;
|
||||
commandList.add("@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(cert));
|
||||
}
|
||||
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command, env);
|
||||
OutputStream processOut = process.getOutputStream();
|
||||
InputStream processIn = process.getInputStream();
|
||||
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = data.read(buf)) > 0) {
|
||||
processOut.write(buf, 0, r);
|
||||
}
|
||||
|
||||
data.close();
|
||||
processOut.close();
|
||||
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(processIn));
|
||||
List<Verification> verifications = new ArrayList<>();
|
||||
|
||||
String line = null;
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
verifications.add(Verification.fromString(line));
|
||||
}
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
|
||||
return verifications;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
90
external-sop/src/main/java/sop/external/operation/EncryptExternal.java
vendored
Normal file
90
external-sop/src/main/java/sop/external/operation/EncryptExternal.java
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.Ready;
|
||||
import sop.enums.EncryptAs;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.Encrypt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class EncryptExternal implements Encrypt {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
private int SIGN_WITH_COUNTER = 0;
|
||||
private int KEY_PASSWORD_COUNTER = 0;
|
||||
private int PASSWORD_COUNTER = 0;
|
||||
private int CERT_COUNTER = 0;
|
||||
|
||||
public EncryptExternal(String binary, Properties environment) {
|
||||
this.commandList.add(binary);
|
||||
this.commandList.add("encrypt");
|
||||
this.envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt noArmor() {
|
||||
this.commandList.add("--no-armor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt mode(EncryptAs mode)
|
||||
throws SOPGPException.UnsupportedOption {
|
||||
this.commandList.add("--as=" + mode);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt signWith(InputStream key)
|
||||
throws SOPGPException.KeyCannotSign, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData,
|
||||
IOException {
|
||||
String envVar = "SIGN_WITH_" + SIGN_WITH_COUNTER++;
|
||||
commandList.add("--sign-with=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(key));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt withKeyPassword(byte[] password)
|
||||
throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
String envVar = "KEY_PASSWORD_" + KEY_PASSWORD_COUNTER++;
|
||||
commandList.add("--with-key-password=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + new String(password));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt withPassword(String password)
|
||||
throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
String envVar = "PASSWORD_" + PASSWORD_COUNTER++;
|
||||
commandList.add("--with-password=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + password);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt withCert(InputStream cert)
|
||||
throws SOPGPException.CertCannotEncrypt, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData,
|
||||
IOException {
|
||||
String envVar = "CERT_" + CERT_COUNTER++;
|
||||
commandList.add("@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(cert));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ready plaintext(InputStream plaintext)
|
||||
throws IOException, SOPGPException.KeyIsProtected {
|
||||
return ExternalSOP.ready(Runtime.getRuntime(), commandList, envList, plaintext);
|
||||
}
|
||||
}
|
|
@ -9,77 +9,30 @@ import sop.exception.SOPGPException;
|
|||
import sop.external.ExternalSOP;
|
||||
import sop.operation.ExtractCert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class ExtractCertExternal implements ExtractCert {
|
||||
|
||||
private final String binary;
|
||||
private final Runtime runtime = Runtime.getRuntime();
|
||||
private final Properties environment;
|
||||
|
||||
private boolean noArmor;
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
public ExtractCertExternal(String binary, Properties properties) {
|
||||
this.binary = binary;
|
||||
this.environment = properties;
|
||||
this.commandList.add(binary);
|
||||
this.commandList.add("extract-cert");
|
||||
this.envList = ExternalSOP.propertiesToEnv(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractCert noArmor() {
|
||||
this.noArmor = true;
|
||||
this.commandList.add("--no-armor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ready key(InputStream keyInputStream) throws SOPGPException.BadData {
|
||||
List<String> commandList = new ArrayList<>();
|
||||
|
||||
commandList.add(binary);
|
||||
commandList.add("extract-cert");
|
||||
|
||||
if (noArmor) {
|
||||
commandList.add("--no-armor");
|
||||
}
|
||||
|
||||
List<String> envList = ExternalSOP.propertiesToEnv(environment);
|
||||
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
|
||||
try {
|
||||
Process process = runtime.exec(command, env);
|
||||
OutputStream extractOut = process.getOutputStream();
|
||||
InputStream extractIn = process.getInputStream();
|
||||
|
||||
return new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = keyInputStream.read(buf)) > 0) {
|
||||
extractOut.write(buf, 0, r);
|
||||
}
|
||||
|
||||
keyInputStream.close();
|
||||
extractOut.close();
|
||||
|
||||
while ((r = extractIn.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0 , r);
|
||||
}
|
||||
|
||||
extractIn.close();
|
||||
outputStream.close();
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return ExternalSOP.ready(Runtime.getRuntime(), commandList, envList, keyInputStream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,93 +9,48 @@ import sop.exception.SOPGPException;
|
|||
import sop.external.ExternalSOP;
|
||||
import sop.operation.GenerateKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class GenerateKeyExternal implements GenerateKey {
|
||||
|
||||
private final String binary;
|
||||
private boolean noArmor = false;
|
||||
private List<String> userIds = new ArrayList<>();
|
||||
private String keyPassword;
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
private final Runtime runtime = Runtime.getRuntime();
|
||||
private final Properties properties;
|
||||
private int keyPasswordCounter = 0;
|
||||
|
||||
public GenerateKeyExternal(String binary, Properties environment) {
|
||||
this.binary = binary;
|
||||
this.properties = environment;
|
||||
this.commandList.add(binary);
|
||||
this.commandList.add("generate-key");
|
||||
this.envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerateKey noArmor() {
|
||||
this.noArmor = true;
|
||||
this.commandList.add("--no-armor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerateKey userId(String userId) {
|
||||
this.userIds.add(userId);
|
||||
this.commandList.add(userId);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerateKey withKeyPassword(String password)
|
||||
throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
this.keyPassword = password;
|
||||
this.commandList.add("--with-key-password=@ENV:KEY_PASSWORD_" + keyPasswordCounter);
|
||||
this.envList.add("KEY_PASSWORD_" + keyPasswordCounter + "=" + password);
|
||||
keyPasswordCounter++;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ready generate()
|
||||
throws SOPGPException.MissingArg, SOPGPException.UnsupportedAsymmetricAlgo {
|
||||
List<String> commandList = new ArrayList<>();
|
||||
|
||||
commandList.add(binary);
|
||||
commandList.add("generate-key");
|
||||
|
||||
if (noArmor) {
|
||||
commandList.add("--no-armor");
|
||||
}
|
||||
|
||||
if (keyPassword != null) {
|
||||
commandList.add("--with-key-password");
|
||||
commandList.add("@ENV:key_password");
|
||||
}
|
||||
|
||||
for (String userId : userIds) {
|
||||
commandList.add(userId);
|
||||
}
|
||||
|
||||
List<String> envList = ExternalSOP.propertiesToEnv(properties);
|
||||
if (keyPassword != null) {
|
||||
envList.add("key_password=" + keyPassword);
|
||||
}
|
||||
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
try {
|
||||
Process process = runtime.exec(command, env);
|
||||
InputStream stdIn = process.getInputStream();
|
||||
|
||||
return new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = stdIn.read(buf)) >= 0) {
|
||||
outputStream.write(buf, 0, r);
|
||||
}
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return ExternalSOP.ready(Runtime.getRuntime(), commandList, envList);
|
||||
}
|
||||
}
|
||||
|
|
75
external-sop/src/main/java/sop/external/operation/InlineDetachExternal.java
vendored
Normal file
75
external-sop/src/main/java/sop/external/operation/InlineDetachExternal.java
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.ReadyWithResult;
|
||||
import sop.Signatures;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.InlineDetach;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class InlineDetachExternal implements InlineDetach {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
public InlineDetachExternal(String binary, Properties environment) {
|
||||
commandList.add(binary);
|
||||
commandList.add("inline-detach");
|
||||
envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineDetach noArmor() {
|
||||
commandList.add("--no-armor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadyWithResult<Signatures> message(InputStream messageInputStream) throws IOException, SOPGPException.BadData {
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command, env);
|
||||
OutputStream processOut = process.getOutputStream();
|
||||
InputStream processIn = process.getInputStream();
|
||||
|
||||
return new ReadyWithResult<Signatures>() {
|
||||
@Override
|
||||
public Signatures writeTo(OutputStream outputStream) throws IOException {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = messageInputStream.read(buf)) > 0) {
|
||||
processOut.write(buf, 0, r);
|
||||
}
|
||||
|
||||
messageInputStream.close();
|
||||
processOut.close();
|
||||
|
||||
while ((r = processIn.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0 , r);
|
||||
}
|
||||
|
||||
processIn.close();
|
||||
outputStream.close();
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
|
||||
return null; // TODO
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
65
external-sop/src/main/java/sop/external/operation/InlineSignExternal.java
vendored
Normal file
65
external-sop/src/main/java/sop/external/operation/InlineSignExternal.java
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.Ready;
|
||||
import sop.enums.InlineSignAs;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.InlineSign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class InlineSignExternal implements InlineSign {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
private int keyCounter = 0;
|
||||
private int withKeyPasswordCounter = 0;
|
||||
|
||||
public InlineSignExternal(String binary, Properties environment) {
|
||||
commandList.add(binary);
|
||||
commandList.add("inline-sign");
|
||||
envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineSign noArmor() {
|
||||
commandList.add("--no-armor");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineSign key(InputStream key) throws SOPGPException.KeyCannotSign, SOPGPException.BadData, SOPGPException.UnsupportedAsymmetricAlgo, IOException {
|
||||
String envVar = "KEY_" + keyCounter++;
|
||||
commandList.add("@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(key));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineSign withKeyPassword(byte[] password) throws SOPGPException.UnsupportedOption, SOPGPException.PasswordNotHumanReadable {
|
||||
String envVar = "WITH_KEY_PASSWORD_" + withKeyPasswordCounter++;
|
||||
commandList.add("--with-key-password=@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + new String(password));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineSign mode(InlineSignAs mode) throws SOPGPException.UnsupportedOption {
|
||||
commandList.add("--as=" + mode);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ready data(InputStream data) throws IOException, SOPGPException.KeyIsProtected, SOPGPException.ExpectedText {
|
||||
return ExternalSOP.ready(Runtime.getRuntime(), commandList, envList, data);
|
||||
}
|
||||
}
|
94
external-sop/src/main/java/sop/external/operation/InlineVerifyExternal.java
vendored
Normal file
94
external-sop/src/main/java/sop/external/operation/InlineVerifyExternal.java
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.external.operation;
|
||||
|
||||
import sop.ReadyWithResult;
|
||||
import sop.Verification;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.external.ExternalSOP;
|
||||
import sop.operation.InlineVerify;
|
||||
import sop.util.UTCUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class InlineVerifyExternal implements InlineVerify {
|
||||
|
||||
private final List<String> commandList = new ArrayList<>();
|
||||
private final List<String> envList;
|
||||
|
||||
private int certCounter = 0;
|
||||
|
||||
public InlineVerifyExternal(String binary, Properties environment) {
|
||||
commandList.add(binary);
|
||||
commandList.add("inline-verify");
|
||||
envList = ExternalSOP.propertiesToEnv(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineVerify notBefore(Date timestamp) throws SOPGPException.UnsupportedOption {
|
||||
commandList.add("--not-before=" + UTCUtil.formatUTCDate(timestamp));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineVerify notAfter(Date timestamp) throws SOPGPException.UnsupportedOption {
|
||||
commandList.add("--not-after=" + UTCUtil.formatUTCDate(timestamp));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InlineVerify cert(InputStream cert) throws SOPGPException.BadData, IOException {
|
||||
String envVar = "CERT_" + certCounter++;
|
||||
commandList.add("@ENV:" + envVar);
|
||||
envList.add(envVar + "=" + ExternalSOP.readFully(cert));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadyWithResult<List<Verification>> data(InputStream data) throws IOException, SOPGPException.NoSignature, SOPGPException.BadData {
|
||||
String[] command = commandList.toArray(new String[0]);
|
||||
String[] env = envList.toArray(new String[0]);
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(command, env);
|
||||
OutputStream processOut = process.getOutputStream();
|
||||
InputStream processIn = process.getInputStream();
|
||||
|
||||
return new ReadyWithResult<List<Verification>>() {
|
||||
@Override
|
||||
public List<Verification> writeTo(OutputStream outputStream) throws IOException, SOPGPException.NoSignature {
|
||||
byte[] buf = new byte[4096];
|
||||
int r;
|
||||
while ((r = data.read(buf)) > 0) {
|
||||
processOut.write(buf, 0, r);
|
||||
}
|
||||
|
||||
data.close();
|
||||
processOut.close();
|
||||
|
||||
|
||||
while ((r = processIn.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0 , r);
|
||||
}
|
||||
|
||||
processIn.close();
|
||||
outputStream.close();
|
||||
|
||||
ExternalSOP.finish(process);
|
||||
|
||||
return null; // TODO
|
||||
}
|
||||
};
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue