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)

Reply via email to