Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk5 min

Why Your JSON Signatures Break: Deterministic Canonical Serialization in Python

Python’s JSON encoder can make output repeatable without making it RFC 8785 compliant. Understand the byte-level causes of signature mismatches and the checks that matter.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python’s json.dumps(sort_keys=True) can make output more repeatable in a limited application, but it does not by itself guarantee that another language will produce the same bytes—or that the bytes conform to RFC 8785. A digital signature covers bytes, not the abstract meaning of a JSON object. If the signer and verifier serialize that object differently, their signatures can disagree even when both appear to be working with the same data.

Why can equivalent JSON produce different signatures?

JSON objects can represent the same data while having different byte sequences. A space after a colon, a different property order, a different spelling of a number, or a different string-escaping choice can change the bytes. Hashing or signing those different byte sequences produces different results.

For example, {"name":"Ada","active":true} and { "active": true, "name": "Ada" } describe equivalent JSON objects, but they are not the same byte string. A cryptographic operation does not compare their meanings; it processes the precise bytes it receives.

This is why a signature protocol needs an agreed serialization contract as well as an agreed algorithm and key. Both sides must identify the same data to sign, apply the same canonicalization rules, and pass the resulting bytes to the cryptographic operation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What RFC 8785 requires

RFC 8785, “JSON Canonicalization Scheme (JCS),” is an Informational RFC published in June 2020. It defines an invariant JSON representation for repeatable cryptographic operations. The RFC abstract puts the goal this way: “Cryptographic operations like hashing and signing need the data to be expressed in an invariant format so that the operations are reliably repeatable.”

JCS is a complete scheme, not just a property-sorting option. It constrains the input to the I-JSON subset, uses ECMAScript-compatible serialization for JSON primitives, and sorts object properties recursively according to specified rules.

  • Object names: Duplicate property names are not allowed. Properties are sorted by their unescaped names, ordered as UTF-16 code units, independently of locale. Objects inside arrays are sorted in the same way; the array elements themselves stay in their original order.
  • Numbers: Values must be expressible as IEEE 754 double-precision numbers. JCS uses ECMAScript-compatible number serialization, so a parsed decimal spelling may be rounded to its binary64 value and emitted in a different canonical decimal or exponent form. NaN and positive or negative infinity are invalid.
  • Strings: String data is preserved as-is; JCS does not perform Unicode normalization. Strings must be representable as Unicode, and lone surrogates must cause an error rather than produce potentially divergent output.
  • Whitespace and primitives: Canonical output removes whitespace between tokens and applies the specified serialization to literals, strings, and numbers.

For numbers that need more precision or a wider integer range than binary64 can represent reliably, the RFC recommends representing them as JSON strings instead of JSON numbers.

What Python’s built-in encoder does—and does not—guarantee

The Python 3.13.16 standard-library documentation describes sort_keys=True as sorting dictionary output. It also documents controls for separators, string escaping, and non-finite floats. Those options are useful for producing compact, repeatable output for a constrained application, but the documentation does not promise RFC 8785 compliance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Question Python json.dumps options RFC 8785 JCS
Can object keys be sorted? sort_keys=True sorts dictionary output. Sorts object properties recursively using UTF-16 code-unit ordering.
Can output whitespace be controlled? separators controls item and key separators. Canonical output has no whitespace between tokens.
Are non-finite floats accepted? By default, allow_nan=True; allow_nan=False raises ValueError for out-of-range float values. NaN and positive or negative infinity are invalid.
Are number rendering and key order defined for cross-language canonicalization? The documented options do not establish ECMAScript number serialization or JCS’s UTF-16 ordering contract. Both are specified parts of the scheme.

For common ASCII property names, Python’s sorted output may look like the order you expect. That does not establish the required UTF-16 ordering for every non-ASCII name. Nor do the encoder options alone address duplicate names in input, invalid Unicode, binary64 edge cases, or agreement about which exact bytes are signed.

A deliberately limited, single-runtime application might use this pattern:

import json


def application_json_bytes(value):
    text = json.dumps(
        value,
        sort_keys=True,
        separators=(",", ":"),
        allow_nan=False,
    )
    return text.encode("utf-8")

This creates compact UTF-8 bytes under the chosen application rules and rejects non-finite floats. It is an application-specific deterministic encoding, not a claim of RFC 8785 conformance. Use that label only if the implementation actually meets JCS requirements and passes suitable conformance tests.

How to trace a signature mismatch

Debug the bytes at the boundary of the signing operation, not just the dictionaries before serialization. Record the canonicalization profile and compare the exact byte sequences supplied to signing and verification.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Confirm the signed content. Check that both sides select the same object and exclude the same signature field, if the protocol excludes one. Differences in the data being signed cannot be repaired by changing JSON formatting.
  2. Inspect the serialized bytes. Compare length and a safe hexadecimal or escaped representation of the bytes, rather than relying on a pretty-printed JSON view. Look for whitespace, property order, escaping, and number spelling differences.
  3. Check input validity before canonicalization. Establish a policy for duplicate property names, unsupported numeric values, and invalid Unicode. Once duplicate names have been collapsed into a normal mapping, their original presence may no longer be visible to later serialization.
  4. Test edge cases from the protocol. Include non-ASCII property names, strings that differ only by Unicode representation, floating-point boundary cases, and nested objects inside arrays. Confirm that array order remains intact.
  5. Verify the cryptographic boundary. Ensure both sides feed the agreed bytes—not a re-encoded display string or a different representation—to the agreed cryptographic algorithm.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How signing and verification should agree

RFC 8785 describes a workflow in which a producer creates the data, serializes and canonicalizes it, signs the canonical form, and then adds the signature property to the original JSON data. A verifier parses the signed JSON, saves and removes that signature property, serializes and canonicalizes the remaining data, and verifies the saved signature using the agreed algorithm and key.

The field excluded from signing and the canonicalization scheme are protocol details, not implementation preferences. If one side signs an object including a signature field while the other removes it, or if they canonicalize under different rules, verification will fail.

Choosing a Python JCS implementation

The RFC appendix lists a Python implementation in the cyberphone/json-canonicalization project. The listing identifies a possible implementation to evaluate; it does not by itself establish current maintenance status or prove conformance for a particular release.

Before depending on a library, check its documentation and tests for the specific behaviors your protocol requires:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Explicit RFC 8785/JCS conformance claims and maintained test vectors.
  • ECMAScript-compatible number rendering, including exponent formatting and binary64 rounding.
  • Recursive UTF-16 code-unit key ordering for non-ASCII names, while preserving array element order.
  • A documented policy for detecting duplicate property names.
  • Unicode preservation without normalization and rejection of lone surrogates.
  • Clear errors for NaN, infinities, and inputs outside the scheme.
  • Agreement between the signing and verification sides on signature-field exclusion and the bytes passed to the cryptographic operation.

Test the implementation you deploy with the protocol’s actual input domain and conformance vectors. Similar-looking JSON output is not a substitute for passing those tests.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.