Hi Mauro,

I prefer using tag-value-pairs instead of more-or-less complex
JSON-objects, because it will preserve the O(n) parsing
efficiency. Since the Working Group already decided to introduce
JSON, I just suggested the flat array approach.

Regards,
Timo

It looks like Mauro De Gennaro aimed to say:
> Hi Timo,
> 
> Before we continue discussing JSON parsing performance and security concerns, 
> could you clarify your underlying motivation for replacing the current 
> tag=value design with JSON, given that you yourself have raised concerns 
> about JSON's issues? My apologies if this was addressed in an earlier thread 
> I may have missed.
> 
> As you know, the latest DKIM2 draft uses JSON only within the recipes, and 
> your proposal would extend this by replacing the tags with additional JSON, 
> despite the issues you've described with that format. Since none of those 
> issues arise when parsing tag=value signatures, I'd like to understand what 
> motivates the change.
> 
> 
> Best,
> Mauro
> 
> 
>> On 21 Sep 2026, at 1:43 pm, Timo Gerke <[email protected]> wrote:
>>
>> Hi Mauro,
>> hi all,
>>
>> sorry, for the delay. My own project needed some attention.
>>
>> serde_json (or similar to it) may have a strict duplicate name
>> handling, but not all parsers have it.
>>
>> In a heterogeneous infrastructure consisting of older C-ibraries,
>> Go webhooks, and proprietary middleboxes, duplicate name handling
>> is explicitly undefined according to RFC 8259, Section 4. This
>> creates parser differentials where an upstream gateway evaluates
>> one key and a downstream consumer reads another, opening a direct
>> vector for gateway-bypass attacks.
>>
>> To guarantee language-agnostic determinism, validation security
>> must be enforced by the protocol design through a flattened array
>> structure with linear O(n) evaluation, where any anomaly triggers
>> an immediate PERMFAIL.
>>
>> Let Rust handle O(n**m) with n greater than 1 and m equals n+1.
>> q.e.d.
>>
>> Regards,
>> Timo
>>
>>
>> It looks like Mauro De Gennaro aimed to say:
>>> Hi Timo,
>>>
>>> Then I am not sure I follow the proposal. Your argument has been that JSON 
>>> is a hazard in high throughput environments, yet the fields you are 
>>> describing are already plain tag=value in -06 and never reach a JSON 
>>> parser. Moving them into JSON would add a base64 decode and a parse to data 
>>> that currently needs neither, which seems to work against the goal.
>>>
>>>
>>> Best,
>>> Mauro
>>>
>>>
>>>>> On 16 Sep 2026, at 18:44, Timo Gerke <[email protected]> wrote:
>>>>
>>>> Ciao Mauro,
>>>> Hi all,
>>>>
>>>> Sorry, Mauro, I was talking about Revision 06 all the time.
>>>>
>>>> Regards,
>>>> Timo
>>>>
>>>> It looks like Mauro De Gennaro aimed to say:
>>>>> Hi Timo,
>>>>>
>>>>> I think I have found the source of the misunderstanding, all this time I 
>>>>> thought you were talking about flattening the JSON recipes but you might 
>>>>> be referring to an expired pre-adoption draft?
>>>>>
>>>>> The JSON objects holding selector, algorithm and signature value are from 
>>>>> draft-clayton-dkim2-spec, the individual submission that preceded the 
>>>>> working group document. Version -07 of that draft mapped various fields 
>>>>> of Message-Instance and DKIM2-Signature into JSON, but the draft expired 
>>>>> on 3 September. The WG document reversed that in its -00, whose changelog 
>>>>> records removing JSON for hashes, signatures and SMTP parameters.
>>>>>
>>>>> In draft-ietf-dkim-dkim2-spec-06, section 8.9, the s= tag is a comma 
>>>>> separated list of selector:algorithm:signature triples in plain ABNF. No 
>>>>> JSON, no base64 wrapping of a structure, no parser beyond the tag 
>>>>> scanner. Section 2 limits JSON to the Recipes in r= and nothing else. I 
>>>>> mention this because clayton-08's signature JSON was in fact an array of 
>>>>> positional three element arrays, so the design you are arguing against 
>>>>> was already the one without named keys, and your proposal would move 
>>>>> toward named objects rather than away from them.
>>>>>
>>>>> About the capability itself, -06 already supports what I think you may be 
>>>>> after. Section 8.9 permits more than one signature at a single hop using 
>>>>> different algorithms, plus one additional signature with the same 
>>>>> algorithm and a different key length provided a different Selector is 
>>>>> used. Both signatures sit in one DKIM2-Signature header field, sharing 
>>>>> one i= and one d=, so there is no extra hop and no distortion of the 
>>>>> Chain of Custody. Hybrid signing, classical alongside post-quantum, is 
>>>>> expressible today without any JSON.
>>>>>
>>>>>
>>>>>
>>>>> Best,
>>>>> Mauro
>>>>>
>>>>>
>>>>>> On 16 Sep 2026, at 16:05, Timo Gerke <[email protected]> wrote:
>>>>>>
>>>>>> Ciao Mauro,
>>>>>> Hi all,
>>>>>>
>>>>>> It seems there was some misunderstanding. I am not proposing an
>>>>>> array of positional tuples, nor an array of objects with deep
>>>>>> nested structures.
>>>>>>
>>>>>> I am proposing a flattened JSON array containing flat,
>>>>>> single-level JSON objects representing distinct crypto contexts:
>>>>>>
>>>>>> [
>>>>>> {"tag1": "value1", "tag2": "value2"},
>>>>>> {"tag3": "value3", "tag4": "value4"}
>>>>>> ]
>>>>>>
>>>>>> The less room for interpretation the spec has, the fewer faulty
>>>>>> implementations will exist.
>>>>>>
>>>>>> With a flattened array of flat objects, the expected structural
>>>>>> nesting depth is strictly capped at level 2. A high-throughput
>>>>>> gateway under a real productive load can reject non-conforming
>>>>>> deeper structures at wire speed immediately upon inspecting the
>>>>>> token stream, preventing any deep allocation vectors and
>>>>>> eliminating undefined multi-parser anomalies (RFC 8259) by
>>>>>> design.
>>>>>>
>>>>>> Best regards,
>>>>>> Timo
>>>>>>
>>>>>> It looks like Mauro De Gennaro aimed to say:
>>>>>>> Hi Timo,
>>>>>>>
>>>>>>> Both of your arguments hold only if implementers write a custom 
>>>>>>> streaming parser against your schema. Neither holds for a standard JSON 
>>>>>>> library, and I think that is the issue.
>>>>>>>
>>>>>>> Regarding hash map allocation, an array of objects is still an array of 
>>>>>>> objects. serde_json, Jackson, encoding/json and Python's json will 
>>>>>>> allocate a map or dict per element, because each element has named 
>>>>>>> fields. Under any off the shelf parser your design performs more hash 
>>>>>>> map insertion than the schema you are proposing to replace, which 
>>>>>>> inverts the argument. Zero hash map allocation would require an array 
>>>>>>> of positional arrays rather than objects, and at that point the 
>>>>>>> self-describing property of JSON is gone.
>>>>>>>
>>>>>>> Also, I did some research, and the hash flooding vector is largely 
>>>>>>> historical for maintained libraries. Randomized hash seeding is 
>>>>>>> available in Python, Ruby, Rust and the JVM ecosystem following the 
>>>>>>> 2011/2012 disclosures, and Jackson ships input constraints by default. 
>>>>>>> A gateway running a parser with deterministic unseeded hashing has a 
>>>>>>> dependency problem, not a schema problem.
>>>>>>>
>>>>>>> Regarding nesting, strictly limits nesting to level 1 describes what 
>>>>>>> conforming senders emit. It says nothing about what arrives. As I 
>>>>>>> mentioned in my previous email, a standard parser handed 10,000 nested 
>>>>>>> braces will recurse into them regardless of what the schema permits, 
>>>>>>> because the attacker is not reading the schema. The immediate drop you 
>>>>>>> want comes from a depth limit configured at the parser, and that limit 
>>>>>>> works identically against a nested schema.
>>>>>>>
>>>>>>> If implementers use standard libraries, your array allocates more hash 
>>>>>>> maps and handles recursion no differently, so it is worse on your own 
>>>>>>> criterion. If implementers write custom streaming parsers for wire 
>>>>>>> speed drops, they can enforce a depth cap against the current schema 
>>>>>>> just as easily, so the array gains nothing. Schema shape does not 
>>>>>>> determine parser architecture, and the defence has to sit at the parser 
>>>>>>> either way.
>>>>>>>
>>>>>>> Separately, have you benchmarked any of this, or tested these vectors 
>>>>>>> against actual JSON libraries? Taking Rust as the example, neither 
>>>>>>> point survives contact with serde_json. Deserializing into a typed 
>>>>>>> struct allocates no hash map whatever the shape of the document, 
>>>>>>> because serde resolves field names through code generated at compile 
>>>>>>> time rather than through a runtime map, so hash flooding has nothing to 
>>>>>>> attack. And the recursion limit is not an optional hardening step, it 
>>>>>>> is the default, capped at 128 levels unless an implementer explicitly 
>>>>>>> disables it. A hostile document is rejected during the parse, at wire 
>>>>>>> speed, without any change to the schema. I would be glad to look at 
>>>>>>> numbers if you have them, but the claims as stated do not describe how 
>>>>>>> the mainstream parsers actually behave.
>>>>>>>
>>>>>>>
>>>>>>> Best,
>>>>>>> Mauro
>>>>>>>
>>>>>>>
>>>>>>>> On 16 Sep 2026, at 14:41, Timo Gerke <[email protected]> wrote:
>>>>>>>>
>>>>>>>> Ciao Mauro,
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> As I already wrote, flat JSON arrays provide a massive advantage
>>>>>>>> to CRITIS environments: predictable parsing time.
>>>>>>>>
>>>>>>>> 1. Nesting: Deeply nested objects force standard parsers into
>>>>>>>> recursive allocation. This is crucial with a real load in
>>>>>>>> productive, possibly CRITIS environments, provoking
>>>>>>>> unpredictable errors under a DDoS attack. A flattened
>>>>>>>> array strictly limits nesting to level 1 at the structural
>>>>>>>> layer, allowing immediate wire-speed drops.
>>>>>>>>
>>>>>>>> 2. Hash Flooding: Standard parsers allocate internal hash maps to
>>>>>>>> resolve name/value pairs, making them vulnerable to engineered
>>>>>>>> collision attacks. A flattened JSON array requires zero hash
>>>>>>>> map allocation. It is processed as a pure linear stream.
>>>>>>>> Algorithmic key-flooding becomes structure.
>>>>>>>>
>>>>>>>> Best regards,
>>>>>>>> Timo
>>>>>>>>
>>>>>>>>
>>>>>>>> It looks like Mauro De Gennaro aimed to say:
>>>>>>>>> Hi Timo,
>>>>>>>>>
>>>>>>>>>> A flattened JSON array forces strict sequential determinism.
>>>>>>>>>> It ensures that duplicate context tags cannot overwrite each
>>>>>>>>>> other or create ambiguous parsing paths.
>>>>>>>>>>
>>>>>>>>>> Regarding predictable parsing time: Sterile lab setups do not
>>>>>>>>>> simulate a CRITIS gateway under a DDoS attack. Deeply nested JSON
>>>>>>>>>> opens the door to algorithmic complexity exploits. An array
>>>>>>>>>> guarantees linear O(n) parsing time at wire speed.
>>>>>>>>>>
>>>>>>>>>> My idea of a flat array reduces the attack surface to the
>>>>>>>>>> smallest possible level. It provides security by design, rather
>>>>>>>>>> than security by policy.
>>>>>>>>>
>>>>>>>>> On flattening as a DoS mitigation: changing the schema does not 
>>>>>>>>> change what arrives on the wire. An attacker sending a hostile value 
>>>>>>>>> is not emitting schema-conformant JSON. They will send 10,000 levels 
>>>>>>>>> of nesting whether the spec describes nested objects or a flat array. 
>>>>>>>>> A verifier therefore has to bound depth and input length at the 
>>>>>>>>> parser under either design, and since the mitigation is identical 
>>>>>>>>> either way, flattening buys no additional resistance.
>>>>>>>>>
>>>>>>>>> Regarding linear time, a conforming JSON parser makes a single pass 
>>>>>>>>> and consumes each token exactly once, regardless of shape. Nesting 
>>>>>>>>> depth determines how much parser stack is live at a given moment, not 
>>>>>>>>> how many times any byte is examined. Nested JSON is already O(n) in 
>>>>>>>>> input length, so the guarantee you want from the array is one the 
>>>>>>>>> current design has. JSON also cannot express the expansion attacks 
>>>>>>>>> that motivate this worry in other formats, because it has no entity 
>>>>>>>>> or anchor references; output size is bounded by input size.
>>>>>>>>> Also, about algorithmic complexity attacks specifically, in JSON 
>>>>>>>>> these are normally hash flooding, many colliding keys within a single 
>>>>>>>>> object degrading insertion. That depends on key count per object, not 
>>>>>>>>> on depth, so flattening does not mitigate it.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Best,
>>>>>>>>> Mauro
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>
>> --
>>
>> Timo Gerke
>> Hamburg, Germany
>>
>> "Errare humanum est, sed in errore perservare diabolicum est."
>>  -- Seneca Rhetor
>> <OpenPGP_0x9F03DF9F597BF31E.asc>
>> _______________________________________________
>> Ietf-dkim mailing list -- [email protected]
>> To unsubscribe send an email to [email protected]
> _______________________________________________
> Ietf-dkim mailing list -- [email protected]
> To unsubscribe send an email to [email protected]


Timo Gerke
Hamburg, Germany

"If you think technology can solve your security
 problems then you don't understand the problems
 and you don't understand the technology."
   -- Bruce Schneier

Attachment: OpenPGP_0x9F03DF9F597BF31E.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

_______________________________________________
Ietf-dkim mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to