Babak Vahdat created CAMEL-26425:
------------------------------------
Summary: camel-as2 - signature verification and MDN MIC are
computed over a re-serialisation of the signed part, not over the bytes received
Key: CAMEL-26425
URL: https://issues.apache.org/jira/browse/CAMEL-26425
Project: Camel
Issue Type: Bug
Components: camel-as2
Affects Versions: 4.22.0
Reporter: Babak Vahdat
Assignee: Babak Vahdat
Fix For: 4.18.6, 4.22.3
An AS2 server built on camel-as2 (as2:server/listen) refuses a correctly signed
message with the MDN
disposition "processed/error: authentication-failed" when the signed part uses
Content-Transfer-Encoding: base64 or quoted-printable and was produced by
another AS2 implementation
(openssl cms, Lobster_data, OpenAS2, ...). The same message sent as binary,
7bit or 8bit is accepted.
Cause: SigningUtils.isValid(MultipartSignedEntity, Certificate[]) serialises
the parsed first body part
again (MimeEntity.writeTo) and verifies the signature over that. The
re-serialisation re-encodes the
decoded content with camel-as2's own encoder (base64 wrapped at 76 characters,
quoted-printable with its
own escaping) and rewrites the headers, so it differs from the bytes the sender
signed whenever the
sender's encoding differs in line length or escaping. RFC 1847 section 2.1
defines the signature over the
first body part as transmitted, headers included, after the transfer encoding
is applied.
For the same reason MicUtils.createReceivedContentMic computes the
Received-Content-MIC of the MDN over
the re-serialised part, so the MIC in the receipt does not match the one the
sender computed over what it
sent (RFC 4130 section 7.1) - the sender's MDN check fails even for an accepted
message.
camel-as2's own client is not affected, because client and server re-encode
identically; that is why the
component's tests never show it.
Reproduction:
- Unit test (in the pull request): sign the bytes
"Content-Type: application/edifact\r\nContent-Transfer-Encoding:
base64\r\n\r\n" + base64 of the
payload wrapped at 64 characters
with a detached PKCS#7 signature (BouncyCastle, as openssl cms -sign does),
assemble the
multipart/signed, parse it with EntityParser.parseEntity and call
SigningUtils.isValid: false. The same
with a quoted-printable part that escapes characters camel-as2 would not
escape.
- By hand: openssl cms -sign over such a part, openssl cms -encrypt for the
server's certificate, POST
with curl to as2:server/listen - the MDN says processed/error:
authentication-failed. Seen in
production-like use with Lobster_data as the partner: small EDI files (sent
binary) accepted, larger
ones (sent base64) refused.
Fix (pull request follows):
- The parser keeps the first body part of a multipart/signed exactly as received
(AS2SessionInputBuffer raw capture, MultipartSignedEntity.getSignedDataRaw()).
- SigningUtils.isValid and MicUtils use those bytes
(MultipartSignedEntity.getSignedDataContent()),
falling back to the serialisation for entities built locally, so the client
side is unchanged.
- Tests MultipartSignedEntityAsReceivedTest (base64, quoted-printable and
binary parts; inside an
encrypted message; a locally built entity) and AS2SessionInputBufferTest.
- Upgrade guide entry for 4.24.
_This text was prepared with Claude Code (Claude Fable 5.1) on behalf of Babak
Vahdat (bvahdat), who analysed, reproduced and verified the issue._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)