WiP: Implement first prototypes of all SOP commands for external binaries

This commit is contained in:
Paul Schaub 2023-01-09 19:48:25 +01:00
parent efec4d9110
commit a63b29fe80
21 changed files with 1473 additions and 146 deletions

View 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);
}
}

View 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);
}
}

View 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);
}
}
}

View file

@ -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);
}
}
}

View 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);
}
}
}

View 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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View 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);
}
}
}

View 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);
}
}

View 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);
}
}
}