From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id AC8DF1FF0E5 for ; Wed, 12 Aug 2026 13:51:34 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 275A221562; Wed, 12 Aug 2026 13:51:34 +0200 (CEST) From: Thomas Ellmenreich To: pve-devel@lists.proxmox.com Subject: [PATCH proxmox-acme v3 1/1] fix #7749: always serialize in same order Date: Wed, 12 Aug 2026 13:51:28 +0200 Message-ID: <20260812115128.135004-1-t.ellmenreich@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1786535474109 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.820 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: MVAP5RWNE7RLSBFG5GPHOGD55YPIDOQ5 X-Message-ID-Hash: MVAP5RWNE7RLSBFG5GPHOGD55YPIDOQ5 X-MailFrom: t.ellmenreich@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Thomas Ellmenreich X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: All objects are now serialized with "canonical => 1" so that the resulting bytes are directly comparable. Perls randomized hash key orders lead to different serialization outputs even with the same input. The 'tojs' function also now explicitly overrides the utf8 and canonical options to make sure that they are always set. Signed-off-by: Thomas Ellmenreich --- Serializing acme responses to json, because of perls randomized hash key order, would lead to unequal serialized responses if they were compared as bytes. By setting "canonical => 1" the serializations now always have the same order and can thus be compared bytewise. I have tested the patch against a local instance of HashiCorp Vault PKI and the EAB registration works. It seems that "canonical" can have performance implications when serialising larger objects, but since the objects produced in our acme client are relatively small, I consider this acceptable. Changes since v2 (thanks @Elias) -------------------------------- - The options were beeing passed to the 'to_json' function as a hash instead of a hash reference. This is now fixed. src/PVE/ACME.pm | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/PVE/ACME.pm b/src/PVE/ACME.pm index e6fb9c2..3756ac0 100644 --- a/src/PVE/ACME.pm +++ b/src/PVE/ACME.pm @@ -64,9 +64,13 @@ sub encode($) { # acme requires 'base64url' encoding return encode_base64url($_[0]); } -sub tojs($;%) { # shortcut for to_json with utf8=>1 - my ($data, %data) = @_; - return to_json($data, { utf8 => 1, %data }); +sub tojs($;%) { # shortcut for to_json with utf8=>1 and canonical=>1 + my ($data, %opts) = @_; + + $opts{utf8} = 1; + $opts{canonical} = 1; + + return to_json($data, \%opts); } sub fromjs($) { @@ -155,7 +159,7 @@ sub save { } # pretty => 1 for readability # canonical => 1 to reduce churn - file_set_contents($self->{path}, tojs($o, pretty => 1, canonical => 1)); + file_set_contents($self->{path}, tojs($o, pretty => 1)); } # Load serialized account JSON file into $self @@ -196,7 +200,7 @@ sub jwk { sub jwk_thumbprint { my ($self) = @_; my $jwk = $self->jwk(1); # $pure = 1 - return encode(sha256(tojs($jwk, canonical => 1))); # canonical sorts + return encode(sha256(tojs($jwk))); } # A key authorization string in acme is a challenge token dot-connected with -- 2.47.3