From 6e40c7dc17e746916a39b6769bb5837527bb97f2 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 12 Jan 2023 16:55:47 +0100 Subject: [PATCH] Add initial tests for all operations --- .../operation/DetachedSignExternal.java | 3 +- .../ExternalArmorDearmorRoundTripTest.java | 39 ++++++++ .../ExternalDecryptWithSessionKeyTest.java | 54 +++++++++++ ...ternalDetachedSignVerifyRoundTripTest.java | 74 +++++++++++++++ ... ExternalEncryptDecryptRoundTripTest.java} | 34 ++++++- ...alInlineSignDetachVerifyRoundTripTest.java | 49 ++++++++++ .../ExternalInlineSignVerifyTest.java | 89 +++++++++++++++++++ 7 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 external-sop/src/test/java/sop/external/ExternalArmorDearmorRoundTripTest.java create mode 100644 external-sop/src/test/java/sop/external/ExternalDecryptWithSessionKeyTest.java create mode 100644 external-sop/src/test/java/sop/external/ExternalDetachedSignVerifyRoundTripTest.java rename external-sop/src/test/java/sop/external/{EncryptDecryptRoundTripTest.java => ExternalEncryptDecryptRoundTripTest.java} (77%) create mode 100644 external-sop/src/test/java/sop/external/ExternalInlineSignDetachVerifyRoundTripTest.java create mode 100644 external-sop/src/test/java/sop/external/ExternalInlineSignVerifyTest.java diff --git a/external-sop/src/main/java/sop/external/operation/DetachedSignExternal.java b/external-sop/src/main/java/sop/external/operation/DetachedSignExternal.java index 9cdf6ec..e48bfa0 100644 --- a/external-sop/src/main/java/sop/external/operation/DetachedSignExternal.java +++ b/external-sop/src/main/java/sop/external/operation/DetachedSignExternal.java @@ -109,7 +109,8 @@ public class DetachedSignExternal implements DetachedSign { BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(micAlgOut))); String line = reader.readLine(); if (line != null && !line.trim().isEmpty()) { - builder.setMicAlg(MicAlg.fromHashAlgorithmId(Integer.parseInt(line))); + MicAlg micAlg = new MicAlg(line.trim()); + builder.setMicAlg(micAlg); } reader.close(); micAlgOut.delete(); diff --git a/external-sop/src/test/java/sop/external/ExternalArmorDearmorRoundTripTest.java b/external-sop/src/test/java/sop/external/ExternalArmorDearmorRoundTripTest.java new file mode 100644 index 0000000..0a4dbdf --- /dev/null +++ b/external-sop/src/test/java/sop/external/ExternalArmorDearmorRoundTripTest.java @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.external; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static sop.external.JUtils.arrayStartsWith; +import static sop.external.JUtils.assertArrayStartsWith; + +@EnabledIf("sop.external.AbstractExternalSOPTest#isExternalSopInstalled") +public class ExternalArmorDearmorRoundTripTest extends AbstractExternalSOPTest { + + private static final String BEGIN_PGP_PRIVATE_KEY_BLOCK = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"; + private static final byte[] BEGIN_PGP_PRIVATE_KEY_BLOCK_BYTES = BEGIN_PGP_PRIVATE_KEY_BLOCK.getBytes(StandardCharsets.UTF_8); + + @Test + public void dearmorArmorAliceKey() throws IOException { + byte[] aliceKey = TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8); + + byte[] dearmored = getSop().dearmor() + .data(aliceKey) + .getBytes(); + + assertFalse(arrayStartsWith(dearmored, BEGIN_PGP_PRIVATE_KEY_BLOCK_BYTES)); + + byte[] armored = getSop().armor() + .data(dearmored) + .getBytes(); + + assertArrayStartsWith(armored, BEGIN_PGP_PRIVATE_KEY_BLOCK_BYTES); + } +} diff --git a/external-sop/src/test/java/sop/external/ExternalDecryptWithSessionKeyTest.java b/external-sop/src/test/java/sop/external/ExternalDecryptWithSessionKeyTest.java new file mode 100644 index 0000000..fcff3e9 --- /dev/null +++ b/external-sop/src/test/java/sop/external/ExternalDecryptWithSessionKeyTest.java @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.external; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import sop.ByteArrayAndResult; +import sop.DecryptionResult; +import sop.SessionKey; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@EnabledIf("sop.external.AbstractExternalSOPTest#isExternalSopInstalled") +public class ExternalDecryptWithSessionKeyTest extends AbstractExternalSOPTest { + + private static final String CIPHERTEXT = "-----BEGIN PGP MESSAGE-----\n" + + "\n" + + "wV4DR2b2udXyHrYSAQdAy+Et2hCh4ubh8KsmM8ctRDN6Pee+UHVVcI6YXpY9S2cw\n" + + "1QEROCgfm6xGb+hgxmoFrWhtZU03Arb27ZmpWA6e6Ha9jFdB4/DDbqbhlVuFOmti\n" + + "0j8BqGjEvEYAon+8F9TwMaDbPjjy9SdgQBorlM88ChIW14KQtpG9FZN+r+xVKPG1\n" + + "8EIOxI4qOZaH3Wejraca31M=\n" + + "=1imC\n" + + "-----END PGP MESSAGE-----\n"; + private static final String SESSION_KEY = "9:ED682800F5FEA829A82E8B7DDF8CE9CF4BF9BB45024B017764462EE53101C36A"; + + @Test + public void testDecryptAndExtractSessionKey() throws IOException { + ByteArrayAndResult bytesAndResult = getSop().decrypt() + .withKey(TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8)) + .ciphertext(CIPHERTEXT.getBytes(StandardCharsets.UTF_8)) + .toByteArrayAndResult(); + + assertEquals(SESSION_KEY, bytesAndResult.getResult().getSessionKey().get().toString()); + + assertArrayEquals("Hello, World!\n".getBytes(StandardCharsets.UTF_8), bytesAndResult.getBytes()); + } + + @Test + public void testDecryptWithSessionKey() throws IOException { + byte[] decrypted = getSop().decrypt() + .withSessionKey(SessionKey.fromString(SESSION_KEY)) + .ciphertext(CIPHERTEXT.getBytes(StandardCharsets.UTF_8)) + .toByteArrayAndResult() + .getBytes(); + + assertArrayEquals("Hello, World!\n".getBytes(StandardCharsets.UTF_8), decrypted); + } +} diff --git a/external-sop/src/test/java/sop/external/ExternalDetachedSignVerifyRoundTripTest.java b/external-sop/src/test/java/sop/external/ExternalDetachedSignVerifyRoundTripTest.java new file mode 100644 index 0000000..4832770 --- /dev/null +++ b/external-sop/src/test/java/sop/external/ExternalDetachedSignVerifyRoundTripTest.java @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.external; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import sop.Verification; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static sop.external.JUtils.assertArrayStartsWith; + +@EnabledIf("sop.external.AbstractExternalSOPTest#isExternalSopInstalled") +public class ExternalDetachedSignVerifyRoundTripTest extends AbstractExternalSOPTest { + + private static final String BEGIN_PGP_SIGNATURE = "-----BEGIN PGP SIGNATURE-----\n"; + private static final byte[] BEGIN_PGP_SIGNATURE_BYTES = BEGIN_PGP_SIGNATURE.getBytes(StandardCharsets.UTF_8); + + @Test + public void signVerifyWithAliceKey() throws IOException { + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + byte[] signature = getSop().detachedSign() + .key(TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8)) + .data(message) + .toByteArrayAndResult() + .getBytes(); + + List verificationList = getSop().detachedVerify() + .cert(TestKeys.ALICE_CERT.getBytes(StandardCharsets.UTF_8)) + .signatures(signature) + .data(message); + + assertFalse(verificationList.isEmpty()); + assertTrue(verificationList.get(0).toString().contains("EB85BB5FA33A75E15E944E63F231550C4F47E38E EB85BB5FA33A75E15E944E63F231550C4F47E38E")); + } + + @Test + public void signVerifyWithFreshEncryptedKey() throws IOException { + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + byte[] keyPassword = "sw0rdf1sh".getBytes(StandardCharsets.UTF_8); + byte[] key = getSop().generateKey() + .userId("Alice ") + .withKeyPassword(keyPassword) + .generate() + .getBytes(); + + byte[] cert = getSop().extractCert() + .key(key) + .getBytes(); + + byte[] signature = getSop().detachedSign() + .key(key) + .withKeyPassword(keyPassword) + .data(message) + .toByteArrayAndResult() + .getBytes(); + + assertArrayStartsWith(signature, BEGIN_PGP_SIGNATURE_BYTES); + + List verificationList = getSop().detachedVerify() + .cert(cert) + .signatures(signature) + .data(message); + + assertFalse(verificationList.isEmpty()); + } +} diff --git a/external-sop/src/test/java/sop/external/EncryptDecryptRoundTripTest.java b/external-sop/src/test/java/sop/external/ExternalEncryptDecryptRoundTripTest.java similarity index 77% rename from external-sop/src/test/java/sop/external/EncryptDecryptRoundTripTest.java rename to external-sop/src/test/java/sop/external/ExternalEncryptDecryptRoundTripTest.java index 4a5ad01..95bf15a 100644 --- a/external-sop/src/test/java/sop/external/EncryptDecryptRoundTripTest.java +++ b/external-sop/src/test/java/sop/external/ExternalEncryptDecryptRoundTripTest.java @@ -16,11 +16,12 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @EnabledIf("sop.external.AbstractExternalSOPTest#isExternalSopInstalled") -public class EncryptDecryptRoundTripTest extends AbstractExternalSOPTest { +public class ExternalEncryptDecryptRoundTripTest extends AbstractExternalSOPTest { @Test public void encryptDecryptRoundTripPasswordTest() throws IOException { @@ -119,4 +120,35 @@ public class EncryptDecryptRoundTripTest extends AbstractExternalSOPTest { assertEquals(1, verificationList.size()); assertTrue(verificationList.get(0).toString().contains("EB85BB5FA33A75E15E944E63F231550C4F47E38E EB85BB5FA33A75E15E944E63F231550C4F47E38E")); } + + @Test + public void encryptSignDecryptVerifyRoundTripWithFreshEncryptedKeyTest() throws IOException { + byte[] keyPassword = "sw0rdf1sh".getBytes(StandardCharsets.UTF_8); + byte[] key = getSop().generateKey() + .withKeyPassword(keyPassword) + .userId("Alice ") + .generate() + .getBytes(); + byte[] cert = getSop().extractCert() + .key(key) + .getBytes(); + + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + byte[] ciphertext = getSop().encrypt() + .withCert(cert) + .signWith(key) + .withKeyPassword(keyPassword) + .plaintext(message) + .getBytes(); + + ByteArrayAndResult bytesAndResult = getSop().decrypt() + .withKey(key) + .withKeyPassword(keyPassword) + .verifyWithCert(cert) + .ciphertext(ciphertext) + .toByteArrayAndResult(); + + assertFalse(bytesAndResult.getResult().getVerifications().isEmpty()); + assertArrayEquals(message, bytesAndResult.getBytes()); + } } diff --git a/external-sop/src/test/java/sop/external/ExternalInlineSignDetachVerifyRoundTripTest.java b/external-sop/src/test/java/sop/external/ExternalInlineSignDetachVerifyRoundTripTest.java new file mode 100644 index 0000000..6a47f46 --- /dev/null +++ b/external-sop/src/test/java/sop/external/ExternalInlineSignDetachVerifyRoundTripTest.java @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.external; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import sop.ByteArrayAndResult; +import sop.Signatures; +import sop.Verification; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +@EnabledIf("sop.external.AbstractExternalSOPTest#isExternalSopInstalled") +public class ExternalInlineSignDetachVerifyRoundTripTest extends AbstractExternalSOPTest { + + @Test + public void inlineSignThenDetachThenDetachedVerifyTest() throws IOException { + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + byte[] inlineSigned = getSop().inlineSign() + .key(TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8)) + .data(message) + .getBytes(); + + ByteArrayAndResult bytesAndResult = getSop().inlineDetach() + .message(inlineSigned) + .toByteArrayAndResult(); + + byte[] plaintext = bytesAndResult.getBytes(); + assertArrayEquals(message, plaintext); + + byte[] signatures = bytesAndResult.getResult() + .getBytes(); + + List verifications = getSop().detachedVerify() + .cert(TestKeys.ALICE_CERT.getBytes(StandardCharsets.UTF_8)) + .signatures(signatures) + .data(plaintext); + + assertFalse(verifications.isEmpty()); + } +} diff --git a/external-sop/src/test/java/sop/external/ExternalInlineSignVerifyTest.java b/external-sop/src/test/java/sop/external/ExternalInlineSignVerifyTest.java new file mode 100644 index 0000000..31687e9 --- /dev/null +++ b/external-sop/src/test/java/sop/external/ExternalInlineSignVerifyTest.java @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.external; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIf; +import sop.ByteArrayAndResult; +import sop.Verification; +import sop.enums.InlineSignAs; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +@EnabledIf("sop.external.AbstractExternalSOPTest#isExternalSopInstalled") +public class ExternalInlineSignVerifyTest extends AbstractExternalSOPTest { + + private static final String BEGIN_PGP_MESSAGE = "-----BEGIN PGP MESSAGE-----\n"; + private static final byte[] BEGIN_PGP_MESSAGE_BYTES = BEGIN_PGP_MESSAGE.getBytes(StandardCharsets.UTF_8); + private static final String BEGIN_PGP_SIGNED_MESSAGE = "-----BEGIN PGP SIGNED MESSAGE-----\n"; + private static final byte[] BEGIN_PGP_SIGNED_MESSAGE_BYTES = BEGIN_PGP_SIGNED_MESSAGE.getBytes(StandardCharsets.UTF_8); + + @Test + public void inlineSignVerifyAlice() throws IOException { + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + byte[] inlineSigned = getSop().inlineSign() + .key(TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8)) + .data(message) + .getBytes(); + + JUtils.assertArrayStartsWith(inlineSigned, BEGIN_PGP_MESSAGE_BYTES); + + ByteArrayAndResult> bytesAndResult = getSop().inlineVerify() + .cert(TestKeys.ALICE_CERT.getBytes(StandardCharsets.UTF_8)) + .data(inlineSigned) + .toByteArrayAndResult(); + + assertArrayEquals(message, bytesAndResult.getBytes()); + assertFalse(bytesAndResult.getResult().isEmpty()); + } + + @Test + public void inlineSignVerifyAliceNoArmor() throws IOException { + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + byte[] inlineSigned = getSop().inlineSign() + .key(TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8)) + .noArmor() + .data(message) + .getBytes(); + + assertFalse(JUtils.arrayStartsWith(inlineSigned, BEGIN_PGP_MESSAGE_BYTES)); + + ByteArrayAndResult> bytesAndResult = getSop().inlineVerify() + .cert(TestKeys.ALICE_CERT.getBytes(StandardCharsets.UTF_8)) + .data(inlineSigned) + .toByteArrayAndResult(); + + assertArrayEquals(message, bytesAndResult.getBytes()); + assertFalse(bytesAndResult.getResult().isEmpty()); + } + + @Test + public void clearsignVerifyAlice() throws IOException { + byte[] message = "Hello, World!\n".getBytes(StandardCharsets.UTF_8); + + byte[] clearsigned = getSop().inlineSign() + .key(TestKeys.ALICE_KEY.getBytes(StandardCharsets.UTF_8)) + .mode(InlineSignAs.clearsigned) + .data(message) + .getBytes(); + + JUtils.assertArrayStartsWith(clearsigned, BEGIN_PGP_SIGNED_MESSAGE_BYTES); + + ByteArrayAndResult> bytesAndResult = getSop().inlineVerify() + .cert(TestKeys.ALICE_CERT.getBytes(StandardCharsets.UTF_8)) + .data(clearsigned) + .toByteArrayAndResult(); + + assertArrayEquals(message, bytesAndResult.getBytes()); + assertFalse(bytesAndResult.getResult().isEmpty()); + } +}