This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-jdkim.git
commit 23e4227e9a3a6cd06a8c68c512f76efb3c684fa5 Author: Benoit TELLIER <[email protected]> AuthorDate: Wed Nov 4 15:00:37 2026 +0100 [FIX] DKIMSigner: do not fold next to the FWS a template's h= holds When the h= piece is too long for one line, foldedRepresentation splits the value on ":" and folds before the name that would pass column 78. A template may already fold the list (h=from:\r\n\tsubject:...): the names then start with "\r\n\t", their CRLF and tab were counted on the current line, and the "\r\n " added before such a name left a line holding a single SP, obsolete FWS the signer must not generate. The names are now stripped of their FWS before the list is re-folded, and the column restarts after a CRLF held by a tag written in one piece. --- .../org/apache/james/jdkim/tagvalue/TagValue.java | 18 ++++++++++++++--- .../test/java/org/apache/james/jdkim/DKIMTest.java | 23 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/main/src/main/java/org/apache/james/jdkim/tagvalue/TagValue.java b/main/src/main/java/org/apache/james/jdkim/tagvalue/TagValue.java index a16d4de..4e47f5e 100644 --- a/main/src/main/java/org/apache/james/jdkim/tagvalue/TagValue.java +++ b/main/src/main/java/org/apache/james/jdkim/tagvalue/TagValue.java @@ -426,15 +426,16 @@ public class TagValue { breakBeforeNextTag = false; if (column + piece.length() <= FOLDING_WIDTH || !"h".equals(tag)) { res.append(piece); - column += piece.length(); + column = columnAfter(column, piece); continue; } - // SPEC: sig-h-tag = hdr-name *( [FWS] ":" [FWS] hdr-name ): fold after a ":" + // SPEC: sig-h-tag = hdr-name *( [FWS] ":" [FWS] hdr-name ): fold after a ":". The FWS the + // value may already hold is dropped, so that a fold never lands next to an existing one. res.append(" h="); column += 3; String[] names = value.split(":", -1); for (int i = 0; i < names.length; i++) { - String name = names[i] + (i < names.length - 1 ? ":" : ";"); + String name = fwsPattern.matcher(names[i]).replaceAll("") + (i < names.length - 1 ? ":" : ";"); if (column + name.length() > FOLDING_WIDTH) { res.append("\r\n "); column = 1; @@ -446,4 +447,15 @@ public class TagValue { return res.toString(); } + /** + * @return the column after appending text at column: a CRLF the text holds starts a new line + */ + private static int columnAfter(int column, String text) { + int crlf = text.lastIndexOf("\r\n"); + if (crlf == -1) { + return column + text.length(); + } + return text.length() - crlf - 2; + } + } diff --git a/main/src/test/java/org/apache/james/jdkim/DKIMTest.java b/main/src/test/java/org/apache/james/jdkim/DKIMTest.java index 725c698..12b9d36 100644 --- a/main/src/test/java/org/apache/james/jdkim/DKIMTest.java +++ b/main/src/test/java/org/apache/james/jdkim/DKIMTest.java @@ -763,4 +763,27 @@ public class DKIMTest { } } + @Test + public void signedFieldShouldNotHoldWhitespaceOnlyLinesWhenTemplateFoldsH() throws Exception { + String message = "From: [email protected]\r\nSubject: hi\r\n\r\nbody\r\n"; + for (int repeats = 1; repeats < 20; repeats++) { + for (String c : new String[] {"simple/simple", "relaxed/relaxed"}) { + String template = "v=1; a=rsa-sha256; c=" + c + "; d=messiah.edu; s=selector2; h=from" + + ":\r\n\tsubject".repeat(repeats) + ";"; + String field = new DKIMSigner(template, TestKeys.privateKey) + .sign(new ByteArrayInputStream(message.getBytes(StandardCharsets.US_ASCII))); + + for (String line : field.split("\r\n", -1)) { + assertThat(line.trim()).as("line in [%s]", field).isNotEmpty(); + assertThat(line.length()).as("line [%s]", line).isLessThanOrEqualTo(78); + } + verifier.resetResults(); + String signed = field + "\r\n" + message; + assertThat(verifier.verify(new ByteArrayInputStream(signed.getBytes(StandardCharsets.US_ASCII)))) + .as("c=%s, %d names", c, repeats) + .hasSize(1); + } + } + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
