diff --git a/sop-java/src/main/java/sop/Verification.java b/sop-java/src/main/java/sop/Verification.java index 6ff63f6..de5b2d3 100644 --- a/sop-java/src/main/java/sop/Verification.java +++ b/sop-java/src/main/java/sop/Verification.java @@ -6,6 +6,7 @@ package sop; import java.util.Date; +import sop.enums.SignatureMode; import sop.util.UTCUtil; public class Verification { @@ -13,20 +14,52 @@ public class Verification { private final Date creationTime; private final String signingKeyFingerprint; private final String signingCertFingerprint; + private final SignatureMode signatureMode; + private final String description; + + public static final String MODE = "mode:"; + public Verification(Date creationTime, String signingKeyFingerprint, String signingCertFingerprint) { + this(creationTime, signingKeyFingerprint, signingCertFingerprint, null, null); + } + + public Verification(Date creationTime, String signingKeyFingerprint, String signingCertFingerprint, SignatureMode signatureMode, String description) { this.creationTime = creationTime; this.signingKeyFingerprint = signingKeyFingerprint; this.signingCertFingerprint = signingCertFingerprint; + this.signatureMode = signatureMode; + this.description = description == null ? null : description.trim(); } public static Verification fromString(String toString) { String[] split = toString.trim().split(" "); - if (split.length != 3) { + if (split.length < 3) { throw new IllegalArgumentException("Verification must be of the format 'UTC-DATE OpenPGPFingerprint OpenPGPFingerprint'"); } - return new Verification(UTCUtil.parseUTCDate(split[0]), split[1], split[2]); + SignatureMode mode = null; + int index = 3; + if (split[index].startsWith(MODE)) { + mode = SignatureMode.valueOf(split[3].substring(MODE.length())); + index++; + } + + StringBuilder sb = new StringBuilder(); + for (int i = index; i < split.length; i++) { + if (sb.length() != 0) { + sb.append(' '); + } + sb.append(split[i]); + } + + return new Verification( + UTCUtil.parseUTCDate(split[0]), + split[1], // key FP + split[2], // cert FP + mode, + sb.length() != 0 ? sb.toString() : null // description + ); } /** @@ -56,13 +89,42 @@ public class Verification { return signingCertFingerprint; } + /** + * Return the mode of the signature. + * + * @return signature mode + */ + public SignatureMode getSignatureMode() { + return signatureMode; + } + + /** + * Return an optional description. + * + * @return description + */ + public String getDescription() { + return description; + } + @Override public String toString() { - return UTCUtil.formatUTCDate(getCreationTime()) + - ' ' + - getSigningKeyFingerprint() + - ' ' + - getSigningCertFingerprint(); + StringBuilder sb = new StringBuilder() + .append(UTCUtil.formatUTCDate(getCreationTime())) + .append(' ') + .append(getSigningKeyFingerprint()) + .append(' ') + .append(getSigningCertFingerprint()); + + if (signatureMode != null) { + sb.append(' ').append(MODE).append(signatureMode); + } + + if (description != null) { + sb.append(' ').append(description); + } + + return sb.toString(); } @Override diff --git a/sop-java/src/main/java/sop/enums/SignatureMode.java b/sop-java/src/main/java/sop/enums/SignatureMode.java new file mode 100644 index 0000000..b41f6ce --- /dev/null +++ b/sop-java/src/main/java/sop/enums/SignatureMode.java @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.enums; + +public enum SignatureMode { + binary, + text +} diff --git a/sop-java/src/test/java/sop/util/VerificationTest.java b/sop-java/src/test/java/sop/util/VerificationTest.java new file mode 100644 index 0000000..3688d6d --- /dev/null +++ b/sop-java/src/test/java/sop/util/VerificationTest.java @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.util; + +import org.junit.jupiter.api.Test; +import sop.Verification; +import sop.enums.SignatureMode; + +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class VerificationTest { + + @Test + public void limitedConstructorTest() { + Date signDate = UTCUtil.parseUTCDate("2022-11-07T15:01:24Z"); + String keyFP = "F9E6F53F7201C60A87064EAB0B27F2B0760A1209"; + String certFP = "4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B"; + Verification verification = new Verification(signDate, keyFP, certFP); + assertEquals("2022-11-07T15:01:24Z F9E6F53F7201C60A87064EAB0B27F2B0760A1209 4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B", verification.toString()); + } + + public void limitedParsingTest() { + String string = "2022-11-07T15:01:24Z F9E6F53F7201C60A87064EAB0B27F2B0760A1209 4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B"; + Verification verification = Verification.fromString(string); + assertEquals(string, verification.toString()); + } + + @Test + public void extendedConstructorTest() { + Date signDate = UTCUtil.parseUTCDate("2022-11-07T15:01:24Z"); + String keyFP = "F9E6F53F7201C60A87064EAB0B27F2B0760A1209"; + String certFP = "4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B"; + SignatureMode mode = SignatureMode.binary; + String description = "certificate from dkg.asc"; + Verification verification = new Verification(signDate, keyFP, certFP, mode, description); + assertEquals("2022-11-07T15:01:24Z F9E6F53F7201C60A87064EAB0B27F2B0760A1209 4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B mode:binary certificate from dkg.asc", verification.toString()); + assertEquals(SignatureMode.binary, verification.getSignatureMode()); + assertEquals(description, verification.getDescription()); + } + + @Test + public void extendedParsingTest() { + String string = "2022-11-07T15:01:24Z F9E6F53F7201C60A87064EAB0B27F2B0760A1209 4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B mode:binary certificate from dkg.asc"; + Verification verification = Verification.fromString(string); + assertEquals(string, verification.toString()); + + // no mode + string = "2022-11-07T15:01:24Z F9E6F53F7201C60A87064EAB0B27F2B0760A1209 4E2C78519512C2AE9A8BFE7EB3298EB2FBE5F51B certificate from dkg.asc"; + verification = Verification.fromString(string); + assertEquals(string, verification.toString()); + } +}