diff --git a/pgpainless-core/src/main/java/org/pgpainless/util/ArmorUtils.java b/pgpainless-core/src/main/java/org/pgpainless/util/ArmorUtils.java index 10258606..555a3369 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/util/ArmorUtils.java +++ b/pgpainless-core/src/main/java/org/pgpainless/util/ArmorUtils.java @@ -22,6 +22,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.regex.Pattern; import org.bouncycastle.bcpg.ArmoredInputStream; import org.bouncycastle.bcpg.ArmoredOutputStream; @@ -34,6 +35,9 @@ import org.pgpainless.key.OpenPgpV4Fingerprint; public class ArmorUtils { + // MessageIDs are 32 printable characters + private static final Pattern PATTERN_MESSAGE_ID = Pattern.compile("^\\S{32}$"); + public static final String HEADER_COMMENT = "Comment"; public static final String HEADER_VERSION = "Version"; public static final String HEADER_MESSAGEID = "MessageID"; @@ -74,6 +78,24 @@ public class ArmorUtils { return toAsciiArmoredString(inputStream, null); } + public static void addHashAlgorithmHeader(ArmoredOutputStream armor, HashAlgorithm hashAlgorithm) { + armor.addHeader(HEADER_HASH, hashAlgorithm.getAlgorithmName()); + } + + public static void addCommentHeader(ArmoredOutputStream armor, String comment) { + armor.addHeader(HEADER_COMMENT, comment); + } + + public static void addMessageIdHeader(ArmoredOutputStream armor, String messageId) { + if (messageId == null) { + throw new NullPointerException("MessageID cannot be null."); + } + if (!PATTERN_MESSAGE_ID.matcher(messageId).matches()) { + throw new IllegalArgumentException("MessageIDs MUST consist of 32 printable characters."); + } + armor.addHeader(HEADER_MESSAGEID, messageId); + } + public static String toAsciiArmoredString(InputStream inputStream, MultiMap additionalHeaderValues) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ArmoredOutputStream armor = ArmoredOutputStreamFactory.get(out); @@ -104,9 +126,12 @@ public class ArmorUtils { public static List getHashAlgorithms(ArmoredInputStream armor) { List algorithmNames = getHashHeaderValues(armor); - List algorithms = new ArrayList<>(algorithmNames.size()); + List algorithms = new ArrayList<>(); for (String name : algorithmNames) { - algorithms.add(HashAlgorithm.fromName(name)); + HashAlgorithm algorithm = HashAlgorithm.fromName(name); + if (algorithm != null) { + algorithms.add(algorithm); + } } return algorithms; } diff --git a/pgpainless-core/src/test/java/org/pgpainless/util/ArmorUtilsTest.java b/pgpainless-core/src/test/java/org/pgpainless/util/ArmorUtilsTest.java index cd030bf2..e254dea7 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/util/ArmorUtilsTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/util/ArmorUtilsTest.java @@ -16,13 +16,16 @@ package org.pgpainless.util; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; import org.bouncycastle.bcpg.ArmoredInputStream; +import org.bouncycastle.bcpg.ArmoredOutputStream; import org.junit.jupiter.api.Test; import org.pgpainless.algorithm.HashAlgorithm; @@ -74,4 +77,16 @@ public class ArmorUtilsTest { // MessageID assertEquals(0, ArmorUtils.getMessageIdHeaderValues(armorIn).size()); } + + @Test + public void testSetMessageId() { + ArmoredOutputStream armor = new ArmoredOutputStream(new ByteArrayOutputStream()); + ArmorUtils.addMessageIdHeader(armor, "abcdefghi01234567890123456789012"); + + assertThrows(NullPointerException.class, () -> ArmorUtils.addMessageIdHeader(armor, null)); + assertThrows(IllegalArgumentException.class, () -> ArmorUtils.addMessageIdHeader(armor, "tooShort")); + assertThrows(IllegalArgumentException.class, () -> ArmorUtils.addMessageIdHeader(armor, "toLooooooooooooooooooooooooooooooooooong")); + assertThrows(IllegalArgumentException.class, () -> ArmorUtils.addMessageIdHeader(armor, "contains spaces 7890123456789012")); + assertThrows(IllegalArgumentException.class, () -> ArmorUtils.addMessageIdHeader(armor, "contains\nnewlines\n12345678901234")); + } }