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 f23ca707c8d4abd45bb139c6871d76dc30a3fc15 Author: Benoit TELLIER <[email protected]> AuthorDate: Fri Oct 30 08:37:24 2026 +0100 [FIX] TagValue: decode b= and bh= as strict base64 once FWS is removed The MIME decoder silently skips characters outside the base64 alphabet and data after the padding, so junk could be inserted into b= of a valid signature. The b64PadFixPattern workaround only repaired one folding shape of the padding. b= and bh= now use the same decoder as p=: FWS is removed anywhere, then the value is decoded with the strict decoder. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../org/apache/james/jdkim/tagvalue/TagValue.java | 7 +----- .../james/jdkim/SignatureRecordImplTest.java | 25 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 6 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 400a06b..cf48ae4 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 @@ -45,7 +45,6 @@ public class TagValue { // Use possessive matching to avoid heavy stack usage private static final Pattern valuePattern = Pattern.compile("^(?:" + tval + "(?:(?:(?:\r\n)?[\t ])++" + tval + ")*+)?$"); - private static final Pattern b64PadFixPattern = Pattern.compile("=(\r?\n\\s*)=$"); private static final Pattern fwsPattern = Pattern.compile("[ \t\r\n]"); // we may use a TreeMap because we may need to know original order. @@ -224,11 +223,7 @@ public class TagValue { } protected byte[] decodeBase64TagValue(String key) { - // When a base64 string ends with a newline between two '=', java.util.Base64 fails. - String value = getValue(key).toString(); - return Base64.getMimeDecoder().decode( - b64PadFixPattern.matcher(value).replaceAll("$1==") - ); + return decodeBase64(getValue(key)); } /** diff --git a/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java b/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java index a67cb1c..e75eb46 100644 --- a/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java +++ b/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java @@ -254,4 +254,29 @@ public class SignatureRecordImplTest { Locale.setDefault(saved); } } + + @Test + public void signatureWithCharactersOutsideTheBase64AlphabetShouldNotDecode() { + SignatureRecordImpl record = new SignatureRecordImpl( + "v=1; a=rsa-sha256; d=example.com; s=s; h=from; bh=AA==; b=AAÿAA"); + + assertThatThrownBy(record::getSignature).isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void bodyHashWithDataAfterThePaddingShouldNotDecode() { + SignatureRecordImpl record = new SignatureRecordImpl( + "v=1; a=rsa-sha256; d=example.com; s=s; h=from; bh= AA== === ; b=AA=="); + + assertThatThrownBy(record::getBodyHash).isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void base64FoldedBetweenThePaddingCharactersShouldDecode() { + SignatureRecordImpl record = new SignatureRecordImpl( + "v=1; a=rsa-sha256; d=example.com; s=s; h=from; bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU\r\n =; b=AA= ="); + + assertThat(record.getBodyHash()).hasSize(32); + assertThat(record.getSignature()).containsExactly(0); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
