Introduce SigningResult class to allow for additional signing information to be returned

This commit is contained in:
Paul Schaub 2022-01-08 17:28:19 +01:00
parent 987c328ad8
commit f2d88d8a86
5 changed files with 70 additions and 15 deletions

View File

@ -28,6 +28,7 @@ import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.util.ArmoredOutputStreamFactory; import org.pgpainless.util.ArmoredOutputStreamFactory;
import sop.MicAlg; import sop.MicAlg;
import sop.ReadyWithResult; import sop.ReadyWithResult;
import sop.SigningResult;
import sop.enums.SignAs; import sop.enums.SignAs;
import sop.exception.SOPGPException; import sop.exception.SOPGPException;
import sop.operation.Sign; import sop.operation.Sign;
@ -69,7 +70,7 @@ public class SignImpl implements Sign {
} }
@Override @Override
public ReadyWithResult<MicAlg> data(InputStream data) throws IOException { public ReadyWithResult<SigningResult> data(InputStream data) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try { try {
EncryptionStream signingStream = PGPainless.encryptAndOrSign() EncryptionStream signingStream = PGPainless.encryptAndOrSign()
@ -77,9 +78,9 @@ public class SignImpl implements Sign {
.withOptions(ProducerOptions.sign(signingOptions) .withOptions(ProducerOptions.sign(signingOptions)
.setAsciiArmor(armor)); .setAsciiArmor(armor));
return new ReadyWithResult<MicAlg>() { return new ReadyWithResult<SigningResult>() {
@Override @Override
public MicAlg writeTo(OutputStream outputStream) throws IOException { public SigningResult writeTo(OutputStream outputStream) throws IOException {
if (signingStream.isClosed()) { if (signingStream.isClosed()) {
throw new IllegalStateException("EncryptionStream is already closed."); throw new IllegalStateException("EncryptionStream is already closed.");
@ -106,7 +107,9 @@ public class SignImpl implements Sign {
out.close(); out.close();
outputStream.close(); // armor out does not close underlying stream outputStream.close(); // armor out does not close underlying stream
return micAlgFromSignatures(signatures); return SigningResult.builder()
.setMicAlg(micAlgFromSignatures(signatures))
.build();
} }
}; };

View File

@ -15,6 +15,7 @@ import java.util.List;
import picocli.CommandLine; import picocli.CommandLine;
import sop.MicAlg; import sop.MicAlg;
import sop.ReadyWithResult; import sop.ReadyWithResult;
import sop.SigningResult;
import sop.cli.picocli.Print; import sop.cli.picocli.Print;
import sop.cli.picocli.SopCLI; import sop.cli.picocli.SopCLI;
import sop.enums.SignAs; import sop.enums.SignAs;
@ -93,9 +94,10 @@ public class SignCmd implements Runnable {
} }
try { try {
ReadyWithResult<MicAlg> ready = sign.data(System.in); ReadyWithResult<SigningResult> ready = sign.data(System.in);
MicAlg micAlg = ready.writeTo(System.out); SigningResult result = ready.writeTo(System.out);
MicAlg micAlg = result.getMicAlg();
if (micAlgOut != null) { if (micAlgOut != null) {
// Write micalg out // Write micalg out
micAlgOut.createNewFile(); micAlgOut.createNewFile();

View File

@ -19,9 +19,9 @@ import java.io.OutputStream;
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus; import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import sop.MicAlg;
import sop.ReadyWithResult; import sop.ReadyWithResult;
import sop.SOP; import sop.SOP;
import sop.SigningResult;
import sop.cli.picocli.SopCLI; import sop.cli.picocli.SopCLI;
import sop.exception.SOPGPException; import sop.exception.SOPGPException;
import sop.operation.Sign; import sop.operation.Sign;
@ -34,10 +34,10 @@ public class SignCmdTest {
@BeforeEach @BeforeEach
public void mockComponents() throws IOException, SOPGPException.ExpectedText { public void mockComponents() throws IOException, SOPGPException.ExpectedText {
sign = mock(Sign.class); sign = mock(Sign.class);
when(sign.data((InputStream) any())).thenReturn(new ReadyWithResult<MicAlg>() { when(sign.data((InputStream) any())).thenReturn(new ReadyWithResult<SigningResult>() {
@Override @Override
public MicAlg writeTo(OutputStream outputStream) { public SigningResult writeTo(OutputStream outputStream) {
return MicAlg.fromHashAlgorithmId(10); return SigningResult.builder().build();
} }
}); });
@ -110,9 +110,9 @@ public class SignCmdTest {
@Test @Test
@ExpectSystemExitWithStatus(1) @ExpectSystemExitWithStatus(1)
public void data_ioExceptionCausesExit1() throws IOException, SOPGPException.ExpectedText { public void data_ioExceptionCausesExit1() throws IOException, SOPGPException.ExpectedText {
when(sign.data((InputStream) any())).thenReturn(new ReadyWithResult<MicAlg>() { when(sign.data((InputStream) any())).thenReturn(new ReadyWithResult<SigningResult>() {
@Override @Override
public MicAlg writeTo(OutputStream outputStream) throws IOException { public SigningResult writeTo(OutputStream outputStream) throws IOException {
throw new IOException(); throw new IOException();
} }
}); });

View File

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package sop;
/**
* This class contains various information about a signed message.
*/
public final class SigningResult {
private final MicAlg micAlg;
private SigningResult(MicAlg micAlg) {
this.micAlg = micAlg;
}
/**
* Return a string identifying the digest mechanism used to create the signed message.
* This is useful for setting the micalg= parameter for the multipart/signed
* content type of a PGP/MIME object as described in section 5 of [RFC3156].
*
* If more than one signature was generated and different digest mechanisms were used,
* the value of the micalg object is an empty string.
*
* @return micalg
*/
public MicAlg getMicAlg() {
return micAlg;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private MicAlg micAlg;
public Builder setMicAlg(MicAlg micAlg) {
this.micAlg = micAlg;
return this;
}
public SigningResult build() {
SigningResult signingResult = new SigningResult(micAlg);
return signingResult;
}
}
}

View File

@ -8,8 +8,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import sop.MicAlg;
import sop.ReadyWithResult; import sop.ReadyWithResult;
import sop.SigningResult;
import sop.enums.SignAs; import sop.enums.SignAs;
import sop.exception.SOPGPException; import sop.exception.SOPGPException;
@ -55,7 +55,7 @@ public interface Sign {
* @param data input stream containing data * @param data input stream containing data
* @return ready * @return ready
*/ */
ReadyWithResult<MicAlg> data(InputStream data) throws IOException, SOPGPException.ExpectedText; ReadyWithResult<SigningResult> data(InputStream data) throws IOException, SOPGPException.ExpectedText;
/** /**
* Signs data. * Signs data.
@ -63,7 +63,7 @@ public interface Sign {
* @param data byte array containing data * @param data byte array containing data
* @return ready * @return ready
*/ */
default ReadyWithResult<MicAlg> data(byte[] data) throws IOException, SOPGPException.ExpectedText { default ReadyWithResult<SigningResult> data(byte[] data) throws IOException, SOPGPException.ExpectedText {
return data(new ByteArrayInputStream(data)); return data(new ByteArrayInputStream(data));
} }
} }