Hi!
On 1/23/26 17:29, Bron Gondwana wrote:
I agree! I've had a play at converting my generator and parser for
Message-Instance headers (see the interop repo here dkim2wg/interop:
DKIM2 interoperability testing <https://github.com/dkim2wg/interop/tree/
master/brong> - I worked from the code I wrote at the last hackathon in
Montreal)
Another nice thing about JSON is that it removes the "wart" of 'z' and
the 'b' and 'c' prefixes. You can just do this:
*[number-number]* - a range of items
*"string"* - a single line or header field value
*null *- an expression that this can't be recreated
So you could have the following fields in a Message-Instance:
{ "rb" : [ [1, 50], [57, 60] ],
"rh" : {
"SecretValue": null,
"From": "Bron Gondwana <[email protected]
<mailto:[email protected]>>",
"List-Id": []
}
}
This doesn't yet look so well-defined.
If we do this, I'd still strongly suggest a uniform change recipe
format, which is directly below "rb" or below an array below a
"rh" header key:
{
"rb": null
}
or
{
"rb": [instruction...]
}
and for headers:
{
"rh": {
"foo": null,
"bar": [instruction...]
}
}
In both cases, you need to be able to encode multiple insertions.
So the rhs (directly below "rb" or below a specific header key)
needs to be either null ("z") or a JSON array.
(I'd additionally suggest the additional option of specifying
"rh": null
with null applied "globally" to the complete header. The semantic
difference is: The revisor can't even tell which header field keys
have been added/removed/modified, in contrast to the above syntax
where the revisor only can't/won't tell what exactly happened to
one specific field key but might be able to disclose changes for
other header field keys.)
Of course you could then define that each array element
("instruction") is either a string (insert this body
line/header field value) or a nested JSON array of 2 elements
(number from, number to).
(Optionally, for optimization of single line copies, allow a number
directly as instruction.)
An issue is: JSON is specified to be UTF-8 only. Strings are not
octet strings but Unicode strings (logically equivalent to UTF-16,
given that the \u escapes need to use surrogates for code points
>= U+10000). This is good enough for header recipes, as headers
are either us-ascii or utf-8 (SMTPUTF8 extension). However it's
not good for body recipes as bodies could use some legacy 8bit
charset (like iso-8859-1) with content-transfer-encoding: 8bit.
Change recipes for these can't be generated in compliant JSON.
[...]
Here's some actual examples written by my code. Note that I include a
'h' key naming the list of headers which were included in the |h1| hash
calculation. This is just an aid to debugging, and is not used by the
validator. The actual header selection logic is this function in my
library:
sub should_skip {
my $hname = lc(shift);
# Stuff we handle ourselves
return 1 if $hname eq 'message-instance';
return 1 if $hname eq 'dkim2-signature';
# Trace Headers
return 1 if $hname eq 'received';
return 1 if $hname eq 'return-path';
# X headers
return 1 if $hname =~ m/^x-/;
# stuff we don't sign
return 1 if $hname eq 'dkim-signature';
return 1 if $hname eq 'arc-authentication-results';
return 1 if $hname eq 'arc-message-signature';
return 1 if $hname eq 'arc-seal';
According to the latest draft the last 3 lines should be
return 1 if $hname =~ m/^arc-/;
instead.
}
Message-Instance: v=4; j=eyJhMSI6InNoYTI1NiIsImIxIjoiNG9sVWtNVWkyYkNDZlZ
[... rest of example snipped ...]
I don't see any particular reason why the value needs all that syntax
even, it could just be:
Message-Instance: 1; yJhMSI6InNoYTI1NiIsImIxIjoiWEkyMjhWLzcyMFhOZWx
tNzZERktRZjkzNGlPRVFRQ3Q2d1ozdUtDSXI5UT0iLCJoIjpbImNvbnRlbnQtdHl
wZSIsImRhdGUiLCJmcm9tIiwibWVzc2FnZS1pZCIsIm1pbWUtdmVyc2lvbiIsInN
1YmplY3QiLCJ0byJdLCJoMSI6InRCOHV3UFFiY0NITzZ6dlUwRW56RUZXVUtLQnR
3eXptcnhlYXZ5NEpuMWc9In0=
The revision could be in the JSON too.
{
"v": 1,
"rh": ...
...
}
I do like that whiespace is entirely non-significant in these fields, so
you can wrap them however you like.
ALSO DO NOTE: I still base-64 encode the |b1| and |h1| fields in this
example. That's really necessary because otherwise they would be
binary, and JSON isn't binary-safe.
Shouldn't it be rather idiomatic JSON instead of magic "1" and "2" in
JSON object names?
{
"v": 2,
"rh": ...,
"hashes": [
{"a":"sha256","h":"headerHashBase64","b":"bodyHashBase64"},
{"a":"somesha3",...}
],
...
}
If we want to limit the hashes to two at most, this could be a semantic
constraint.
Message-Instance would be only base64 with no further syntax,
except the allowance to insert SP/TAB/FWS at will.
[...]
Bron.
Kind regards,
Hannah.
--
Hannah Stern
Software Developer
Mail Transfer Development
1&1 Mail & Media Development & Technology GmbH | | |
Phone: +49 721 91374-4519
E-Mail: [email protected] | Web: www.mail-and-media.com www.gmx.net
www.web.de www.mail.com www.united-internet-media.de
Hauptsitz Montabaur, Amtsgericht Montabaur, HRB 5452
Geschäftsführer: Alexander Charles, Dr. Michael Hagenau, Thomas Ludwig,
Dr. Verena Patzelt
Member of United Internet
Diese E-Mail kann vertrauliche und/oder gesetzlich geschützte
Informationen enthalten. Wenn Sie nicht der bestimmungsgemäße Adressat
sind oder diese E-Mail irrtümlich erhalten haben, unterrichten Sie bitte
den Absender und vernichten Sie diese E-Mail. Anderen als dem
bestimmungsgemäßen Adressaten ist untersagt, diese E-Mail zu speichern,
weiterzuleiten oder ihren Inhalt auf welche Weise auch immer zu verwenden.
This e-mail may contain confidential and/or privileged information. If
you are not the intended recipient of this e-mail, you are hereby
notified that saving, distribution or use of the content of this e-mail
in any way is prohibited. If you have received this e-mail in error,
please notify the sender and delete the e-mail.
_______________________________________________
Ietf-dkim mailing list -- [email protected]
To unsubscribe send an email to [email protected]