From b0eaf0f6ccb13c17b00ad283110649f9e60688a5 Mon Sep 17 00:00:00 2001 From: Claude Agent Date: Mon, 19 Jan 2026 09:41:03 +0000 Subject: [PATCH] fix: preserve signed `content-digest` key in JSON messages When decoding HTTP messages, `content-digest` was unconditionally removed from the message map before commitment verification. This caused HMAC commitment verification to fail for JSON messages that included `content-digest` as part of their signed fields. This fix applies the same pattern used for `ao-body-key`: check if `content-digest` is a signed key before removing it. If it was part of the commitment, it is preserved for verification. Reproducer: - Send a JSON message with a `data` field and explicit `content-digest` - The hbsig library computes content-digest for the data field - HyperBEAM strips content-digest before HMAC verification - Verification fails with `invalid_commitment` This is similar to the fix in PR #610 for `content-type` preservation. Co-Authored-By: Claude Opus 4.5 --- src/dev_codec_httpsig_conv.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dev_codec_httpsig_conv.erl b/src/dev_codec_httpsig_conv.erl index 5a0db779b..b652a1582 100644 --- a/src/dev_codec_httpsig_conv.erl +++ b/src/dev_codec_httpsig_conv.erl @@ -77,7 +77,10 @@ from(HTTP, _Req, Opts) -> hb_maps:without( Removed = hb_maps:keys(Commitments) ++ - [<<"content-digest">>] ++ + case hb_message:is_signed_key(<<"content-digest">>, MsgWithSigs, Opts) of + true -> []; + false -> [<<"content-digest">>] + end ++ case maps:get(<<"content-type">>, MsgWithSigs, undefined) of <<"multipart/", _/binary>> -> [<<"content-type">>]; _ -> []