commit 3926051105b66e90b8202c3f86516d2795e6d639
parent 7700e03cba8277ef975e07deb5da81a4431e3397
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 3 Nov 2025 11:15:47 +0100
01 to master
Diffstat:
| M | draft-donau.xml | | | 466 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
1 file changed, 254 insertions(+), 212 deletions(-)
diff --git a/draft-donau.xml b/draft-donau.xml
@@ -1,29 +1,11 @@
-<?xml version="1.0" encoding="US-ASCII"?>
-<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
-<!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
-<!ENTITY RFC3986 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3986.xml">
-<!ENTITY RFC8174 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8174.xml">
-<!ENTITY RFC5234 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5234.xml">
-<!ENTITY RFC6234 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6234.xml">
-<!ENTITY RFC8032 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8032.xml">
-<!ENTITY RFC4648 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.4648.xml">
-<!ENTITY RFC9498 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.9498.xml">
-<!ENTITY RFC8905 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8905.xml">
-]>
-<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
+<?xml version="1.0" encoding="UTF-8"?>
+<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
+ category="info" docName="draft-grothoff-donau-XX"
+ ipr="trust200902" submissionType="independent" version="3">
<!-- SEE ALSO: https://docs.taler.net/core/taler-uri.html -->
-<?rfc strict="yes" ?>
-<?rfc toc="yes" ?>
-<?rfc symrefs="yes"?>
-<?rfc sortrefs="yes" ?>
-<?rfc compact="yes" ?>
-<?rfc subcompact="no" ?>
-
-<rfc category="info"
- docName="draft-grothoff-donau-01"
- ipr="trust200902">
+
<!-- FIXME ipr is copied from lsd0001, need to be updated -->
- <front>
+ <front xmlns="">
<title abbrev="The 'donau' URI scheme">
The 'donau' URI scheme for validation of Donau donation statements.
</title>
@@ -32,11 +14,10 @@
<organization>Bern University of Applied Sciences</organization>
<address>
<postal>
- <street>Höheweg 80</street>
- <street></street>
+ <street>Höheweg 80</street>
<city>Biel/Bienne</city>
- <code>CH-2501</code>
- <country>CH</country>
+ <code>2501</code>
+ <country>CHE</country>
</postal>
<email>christian.grothoff@bfh.ch</email>
</address>
@@ -46,11 +27,10 @@
<organization>Bern University of Applied Sciences</organization>
<address>
<postal>
- <street>Höheweg 80</street>
- <street></street>
+ <street>Höheweg 80</street>
<city>Biel/Bienne</city>
- <code>CH-2501</code>
- <country>CH</country>
+ <code>2501</code>
+ <country>CHE</country>
</postal>
<email>emmanuel.benoist@bfh.ch</email>
</address>
@@ -61,11 +41,10 @@
<organization>Bern University of Applied Sciences</organization>
<address>
<postal>
- <street>Höheweg 80</street>
- <street></street>
+ <street>Höheweg 80</street>
<city>Biel/Bienne</city>
- <code>CH-2501</code>
- <country>CH</country>
+ <code>2501</code>
+ <country>CHE</country>
</postal>
<email>bohdan.potuzhnyi@bfh.ch</email>
</address>
@@ -77,17 +56,16 @@
<address>
<postal>
<street>7, rue de Mondorf</street>
- <street></street>
<city>Erpeldange</city>
- <code>L-5421</code>
- <country>Luxembourg</country>
+ <code>5421</code>
+ <country>LUX</country>
</postal>
<email>dold@taler.net</email>
</address>
</author>
- <date day="21" month="October" year="2025" />
+ <date day="22" month="October" year="2025" />
<!-- Meta-data Declarations -->
<area>General</area>
@@ -145,16 +123,18 @@
</front>
-<middle>
+<middle xmlns="">
-<section anchor="introduction" title="Introduction">
+<section anchor="introduction">
+ <name>Introduction</name>
<t>
This document defines the 'donau' Uniform Resource Identifier (URI)
<xref target="RFC3986" /> scheme for triggering interactions with
Donau validators.
</t>
-<section title="Objective">
+<section>
+ <name>Objective</name>
<t>
A 'donau' URI always instructs a Donau validator to perform the
validation of a Donau donation statement.
@@ -172,7 +152,8 @@
</section>
-<section title="Requirements Language">
+<section>
+ <name>Requirements Language</name>
<t>
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
@@ -184,8 +165,8 @@
</section>
-<section anchor="syntax"
- title="Syntax of a 'donau' URI">
+<section anchor="syntax">
+ <name>Syntax of a 'donau' URI</name>
<t>
This document uses the Augmented Backus-Naur Form (ABNF) of <xref target="RFC5234"/>.
</t>
@@ -193,8 +174,9 @@
<artwork type="abnf"><![CDATA[
; Scheme and high-level structure
scheme = "donau" / "DONAU" / "donau+http" / "DONAU+HTTP"
- donau-URI = scheme "://" base "?" year-param "&" taxid-param "&" salt-param
- ("&" total-param "&" sig-param)?
+ donau-URI = scheme "://" base "?" year-param "&"
+ taxid-param "&" salt-param
+ ("&" total-param "&" sig-param)?
; The base is the HTTP(S) origin plus optional path segments that
; identify the Donau REST API deployment. Everything before the last
@@ -236,7 +218,8 @@
</figure>
</section>
-<section anchor="semantics" title="Semantics">
+<section anchor="semantics">
+ <name>Semantics</name>
<t>
Even if RFC3986 <xref target="RFC3986"/> explicitly writes that scheme names
are case-insensitive, lower and upper case variations are presented here to
@@ -324,23 +307,43 @@
</t>
</section>
-<section anchor="examples" title="Examples">
+<section anchor="examples">
+ <name>Examples</name>
<figure>
<artwork><![CDATA[
; Minimal example with a simple base and simple taxid
- donau://example.com/?year=2025&id=7560001010000&salt=1234&total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
+ donau://example.com/
+ ?year=2025&id=7560001010000&
+ salt=1234&
+ total=EUR:15&
+ sig=ED25519:
+ H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1
+ QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
; Example with percent-encoded taxid containing '/'
- donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&salt=1234&total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
+ donau://donau.test.taler.net/
+ ?year=2025&id=123%2F456%2F789&
+ salt=1234&
+ total=TESTKUDOS:1&
+ sig=ED25519:
+ B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG2
+ 1W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
; Example with a base URL that includes path components
- donau://admin.ch/taxes/donau/?year=2025&id=7560001010000&salt=1234&total=EUR:15&sig=ED25519:H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
+ donau://admin.ch/taxes/donau/
+ ?year=2025&id=7560001010000&
+ salt=1234&
+ total=EUR:15&
+ sig=ED25519:
+ H9PM3BW3P8MEKB34GZ0G1F7JSNVX7B8AHXRFFMS37QZM7TXZ5MWPXTEDZZGN1
+ QRB1AFPKNCFXJB39NJHP3BAFGCZSCXHEYPHA1YJY28
]]>
</artwork>
</figure>
</section>
-<section anchor="verification" title="Verification of a Donau URI">
+<section anchor="verification">
+ <name>Verification of a Donau URI</name>
<t>
The verification requires the Donau verification application to test
if a given taxpayer is entitled to a tax reduction.
@@ -362,7 +365,8 @@
</t>
</section>
-<section anchor="get-server-keys" title="Obtaining Donau Server Public Keys">
+<section anchor="get-server-keys">
+ <name>Obtaining Donau Server Public Keys</name>
<t>
The verification app <bcp14>MUST</bcp14> obtain the signing public key
corresponding to the base for the given year.
@@ -376,31 +380,32 @@
The verification app <bcp14>SHOULD</bcp14> cache downloaded signing
public keys for the current year.
</t>
- <t>
-
- <list style="symbols">
- <t>Endpoint: /keys</t>
- <t>Method: GET</t>
- <t>Syntax: base/keys</t>
- <t>Syntax response: defined hereunder</t>
- <t>References: [this.I-D]</t>
- </list>
+ <ul>
+ <li>Endpoint: /keys</li>
+ <li>Method: GET</li>
+ <li>Syntax: base/keys</li>
+ <li>Syntax response: defined hereunder</li>
+ <li>References: [this.I-D]</li>
+ </ul>
+ <t>
Each of the "<tt>signkeys</tt>" is valid between "<tt>stamp_start</tt>" and
"<tt>stamp_expire</tt>" and the public "<tt>key</tt>" returned is encoded using Base 32
U Crockford encoding <xref target="base32-U-crockford"/>.
+ </t>
- <sourcecode>
+ <sourcecode>
<![CDATA[
-; Core JSON tokens (simplified; assumes standard JSON for strings, numbers, booleans, null, arrays, objects)
-JSONString = DQUOTE *(%x20-21 / %x23-5B / %x5D-10FFFF / "\" EscapedChar) DQUOTE
+; Core JSON tokens (simplified; assumes standard JSON dialect)
+JSONString = DQUOTE *(%x20-21 / %x23-5B /
+ %x5D-10FFFF / "\" EscapedChar) DQUOTE
UCrockford = *( ALPHA32 / "-" )
ALPHA32 = DIGIT / LETTER
DIGIT = %x30-39 ; 0-9
LETTER = %x41-48 / %x4A-4E / %x50-5A / %x61-68 / %x6A-6E / %x70-7A
JSONUCrockfordString = DQUOTE UCrockford DQUOTE
-EscapedChar = %x22 / %x5C / %x2F / %x62 / %x66 / %x6E / %x72 / %x74 /
- "u" 4HEXDIG
+EscapedChar = %x22 / %x5C / %x2F / %x62 / %x66 /
+ %x6E / %x72 / %x74 / "u" 4HEXDIG
JSONNumber = [ "-" ] 1DIGIT *( DIGIT ) [ "." 1DIGIT *( DIGIT ) ]
[ ( "e" / "E" ) [ "+" / "-" ] 1DIGIT *( DIGIT ) ]
JSONBool = "true" / "false"
@@ -408,42 +413,53 @@ JSONNull = "null"
JSONArray = "[" [ JSONException *( "," JSONException ) ] "]"
JSONObject = "{" [ JSONMember *( "," JSONMember ) ] "}"
JSONMember = JSONString ":" JSONException
-JSONException = JSONString / JSONNumber / JSONObject / JSONArray / JSONBool / JSONNull
+JSONException = JSONString / JSONNumber / JSONObject /
+ JSONArray / JSONBool / JSONNull
; Specific DonauKeysResponse structure
DonauKeysResponse = "{"
JSONMemberSep
"}"
-JSONMemberSep = version , domain , base_url , currency , currency_fraction_digits ,
- donation_units , signkeys
+JSONMemberSep = version , domain , base_url , currency ,
+ currency_fraction_digits , donation_units , signkeys
version = DQUOTE "version" DQUOTE ":" JSONString
domain = DQUOTE "domain" DQUOTE ":" JSONString
base_url = DQUOTE "base_url" DQUOTE ":" JSONString
currency = DQUOTE "currency" DQUOTE ":" JSONString
-currency_fraction_digits = DQUOTE "currency_fraction_digits" DQUOTE ":" JSONNumber
+currency_fraction_digits = DQUOTE "currency_fraction_digits"
+ DQUOTE ":" JSONNumber
EDDSAPubKey = JSONUCrockfordString
SignKey = DQUOTE "key" DQUOTE ":" EDDSAPubKey
-donation_units = DQUOTE "donation_units" DQUOTE ":" "[" DonationUnitKeyGroup *( "," DonationUnitKeyGroup ) "]"
-signkeys = DQUOTE "signkeys" DQUOTE ":" "[" SignKey *( "," SignKey ) "]"
-
-DonationUnitKeyGroup = "{" cipher_field "," value_field "," donation_units_array "}"
-cipher_field = DQUOTE "cipher" DQUOTE ":" ( DQUOTE "RSA" DQUOTE / DQUOTE "CS" DQUOTE )
+donation_units = DQUOTE "donation_units" DQUOTE ":" "["
+ DonationUnitKeyGroup *(
+ "," DonationUnitKeyGroup ) "]"
+signkeys = DQUOTE "signkeys" DQUOTE ":" "[" SignKey
+ *( "," SignKey ) "]"
+
+DonationUnitKeyGroup = "{" cipher_field "," value_field ","
+ donation_units_array "}"
+cipher_field = DQUOTE "cipher" DQUOTE ":" (
+ DQUOTE "RSA" DQUOTE / DQUOTE "CS" DQUOTE )
value_field = DQUOTE "value" DQUOTE ":" JSONNumber
-donation_units_array = DQUOTE "donation_units" DQUOTE ":" "[" DUNK_UNIT_KEY *( "," DUNK_UNIT_KEY ) "]"
+donation_units_array = DQUOTE "donation_units" DQUOTE ":" "["
+ DUNK_UNIT_KEY *(
+ "," DUNK_UNIT_KEY ) "]"
; donation unit entries differ depending on cipher
DUNK_UNIT_KEY = "{" base_fields "," key_specific "}"
-base_fields = DQUOTE "year" DQUOTE ":" JSONNumber [ "," DQUOTE "lost" DQUOTE ":" JSONBool ]
+base_fields = DQUOTE "year" DQUOTE ":" JSONNumber
+ [ "," DQUOTE "lost" DQUOTE ":" JSONBool ]
key_specific = ( DQUOTE "rsa_pub" DQUOTE ":" JSONObject ) /
( DQUOTE "cs_pub" DQUOTE ":" JSONString )
-SignKey = "{" DQUOTE "key" DQUOTE ":" JSONObject "," DQUOTE "year" DQUOTE ":" JSONNumber "}"
+SignKey = "{" DQUOTE "key" DQUOTE ":" JSONObject ","
+ DQUOTE "year" DQUOTE ":" JSONNumber "}"
]]>
</sourcecode>
-Example, a response to a GET request to the <tt>/keys</tt> endpoint.
- <sourcecode>
+ <t>Example, a response to a GET request to the <tt>/keys</tt> endpoint.</t>
+ <sourcecode>
<![CDATA[
{ "signkeys":
[
@@ -456,13 +472,11 @@ Example, a response to a GET request to the <tt>/keys</tt> endpoint.
}
]]>
</sourcecode>
-
-
- </t>
</section>
-<section anchor="get-donation-statement"
- title="Donation Statement Retrieval">
+
+<section anchor="get-donation-statement">
+ <name>Donation Statement Retrieval</name>
<t>
If the Donau URI does not contain the total or the signature, the
verification app <bcp14>MUST</bcp14> download them from the <tt>/donation-statement</tt>
@@ -480,23 +494,26 @@ Example, a response to a GET request to the <tt>/keys</tt> endpoint.
The hash of the donor taxpayer ID <tt>hash-donor-id</tt> <bcp14>MUST</bcp14> be encoded
using Base 32 U Crockford
encoding <xref target="base32-U-crockford"/>.
+ </t>
- <list style="symbols">
- <t>Endpoint: /donation-statement</t>
- <t>Method: GET</t>
- <t>Syntax: base/donation-statement/{year}/{hash-donor-id}</t>
- <t>References: [this.I-D]</t>
- </list>
+ <ul>
+ <li>Endpoint: /donation-statement</li>
+ <li>Method: GET</li>
+ <li>Syntax: base/donation-statement/{year}/{hash-donor-id}</li>
+ <li>References: [this.I-D]</li>
+ </ul>
-Servers implementing the donation-statement endpoint
-<bcp14>MUST</bcp14> respect the
-following syntax; all three fields (<tt>total-field</tt>, <tt>sig-field</tt>, <tt>pub-field</tt>) <bcp14>MUST</bcp14> be included.
+ <t>
+ Servers implementing the donation-statement endpoint
+ <bcp14>MUST</bcp14> respect the
+ following syntax; all three fields (<tt>total-field</tt>, <tt>sig-field</tt>, <tt>pub-field</tt>) <bcp14>MUST</bcp14> be included.
-The total amount is a string formed first of the currency (in capital
-letters) then ":" and then the value (can be an integer or a decimal
-number).
+ The total amount is a string formed first of the currency (in capital
+ letters) then ":" and then the value (can be an integer or a decimal
+ number).
+ </t>
- <sourcecode>
+ <sourcecode>
<![CDATA[
json-object = "{" ws field-list ws "}"
@@ -504,9 +521,12 @@ field-list = field *(ws "," ws field)
field = total-field / sig-field / pub-field
; Allow any order of the three fields
-total-field = DQUOTE "total" DQUOTE ws ":" ws DQUOTE currency ":" value DQUOTE
-sig-field = DQUOTE "donation_statement_sig" DQUOTE ws ":" ws DQUOTE signature DQUOTE
-pub-field = DQUOTE "donau_pub" DQUOTE ws ":" ws DQUOTE signature DQUOTE ; same format as signature
+total-field = DQUOTE "total" DQUOTE ws ":" ws
+ DQUOTE currency ":" value DQUOTE
+sig-field = DQUOTE "donation_statement_sig" DQUOTE ws ":"
+ ws DQUOTE signature DQUOTE
+pub-field = DQUOTE "donau_pub" DQUOTE ws ":" ws
+ DQUOTE signature DQUOTE ; same format as signature
currency = 1*(%x41-5A) ; A-Z uppercase letters
value = int / decimal
@@ -524,10 +544,8 @@ ALPHA = %x41-5A / %x61-7A
]]>
</sourcecode>
-
-
-Example of an element of USD 100.00 :
- <sourcecode>
+ <t>Example of an element of USD 100.00 :</t>
+ <sourcecode>
<![CDATA[
{
"total": "USD:100",
@@ -536,14 +554,11 @@ Example of an element of USD 100.00 :
}
]]>
</sourcecode>
-
-
- </t>
</section>
-<section anchor="signature-total-available"
- title="Verification if Signature and Total are Available">
+<section anchor="signature-total-available">
+ <name>Verification if Signature and Total are Available</name>
<t>
The verification app <bcp14>MUST</bcp14> verify that the signature corresponds to
the claimed values.
@@ -560,22 +575,22 @@ Example of an element of USD 100.00 :
The verification <bcp14>MAY</bcp14> be done with the following instructions.
The signed data is the concatenation of the following fields
in network byte order (big-endian):
-
- <ul>
- <li>size (4 bytes): 32-bit unsigned integer with the total length of the signed data in bytes.</li>
- <li>purpose (4 bytes): 32-bit unsigned integer with the constant value <tt>1500</tt>.</li>
- <li>total value (8 bytes): integer part as an unsigned 64-bit integer.</li>
- <li>total fraction (4 bytes): fractional part as an unsigned 32-bit integer in units of 1/100000000.</li>
- <li>currency (12 bytes): ASCII string, left-aligned with zero-padding on the right to 12 bytes.</li>
- <li>hash of donor taxpayer ID (64 bytes): <tt>hash-donor-id = SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>.</li>
- <li>year (4 bytes): 32-bit unsigned integer (the donation year).</li>
- </ul>
</t>
+
+ <ul>
+ <li>size (4 bytes): 32-bit unsigned integer with the total length of the signed data in bytes.</li>
+ <li>purpose (4 bytes): 32-bit unsigned integer with the constant value <tt>1500</tt>.</li>
+ <li>total value (8 bytes): integer part as an unsigned 64-bit integer.</li>
+ <li>total fraction (4 bytes): fractional part as an unsigned 32-bit integer in units of 1/100000000.</li>
+ <li>currency (12 bytes): ASCII string, left-aligned with zero-padding on the right to 12 bytes.</li>
+ <li>hash of donor taxpayer ID (64 bytes): <tt>hash-donor-id = SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>.</li>
+ <li>year (4 bytes): 32-bit unsigned integer (the donation year).</li>
+ </ul>
</section>
-<section anchor="signature"
- title="Creating Donation Statement Signatures">
+<section anchor="signature">
+ <name>Creating Donation Statement Signatures</name>
<t>
The server signing the donation statement <bcp14>MUST</bcp14> use the Sign(d,message) procedure implemented as defined in <xref target="RFC8032" />.
</t>
@@ -644,8 +659,8 @@ Example of an element of USD 100.00 :
</dl>
</section>
-<section anchor="signature-verification"
- title="Validating Donation Statement Signatures">
+<section anchor="signature-verification">
+ <name>Validating Donation Statement Signatures</name>
<t>
The signature verification step is taking the data presented in the
figure <xref target="figure_donausigwithpseudo" /> as input.
@@ -664,8 +679,8 @@ Example of an element of USD 100.00 :
</section>
-<section anchor="base32-U-crockford"
- title="Base 32 Representation of Binary Data">
+<section anchor="base32-U-crockford">
+ <name>Base 32 Representation of Binary Data</name>
<t>
All binary data <bcp14>MUST</bcp14> be encoded to be transmitted. For encoding, one
<bcp14>MUST</bcp14> use the Base32 U Crockford encoding. This is a variation of the
@@ -677,7 +692,8 @@ Example of an element of USD 100.00 :
Alphabet. The new alphabet is given in the Table <xref target="figure_base32_encoding" />, below.
</t>
- <figure anchor="figure_base32_encoding" title="The Base 32 Encoding Alphabet.">
+ <figure anchor="figure_base32_encoding">
+ <name>The Base 32 Encoding Alphabet.</name>
<artwork name="" type="" align="left" alt="table where value between 0 and 9 are encoded with the character corresponding to the number. Then between 10 and 31, we have all the letters expect I, L, O, U that could be misleading (OCR may not recognize them properly). Padding is the char ="><![CDATA[
Value Encoding Value Encoding Value Encoding Value Encoding
0 0 9 9 18 J 27 V
@@ -701,7 +717,8 @@ Value Encoding Value Encoding Value Encoding Value Encoding
System reading a <tt>U</tt> <bcp14>MUST</bcp14> evaluate it as a <tt>V</tt>.
</t>
- <figure anchor="figure_base32_decoding" title="The Base 32 Decoding Alphabet.">
+ <figure anchor="figure_base32_decoding">
+ <name>The Base 32 Decoding Alphabet.</name>
<artwork name="" type="" align="left" alt=""><![CDATA[
Value Encoding Value Encoding Value Encoding Value Encoding
0 0 9 9 18 J|j 27 V|v|u|U
@@ -719,7 +736,8 @@ Value Encoding Value Encoding Value Encoding Value Encoding
</section>
-<section anchor="security" title="Security Considerations">
+<section anchor="security">
+ <name>Security Considerations</name>
<t>
Donau validators <bcp14>SHOULD</bcp14> support
"<tt>donau+http://</tt>"-URIs only when run in developer or debug mode
@@ -733,18 +751,18 @@ Value Encoding Value Encoding Value Encoding Value Encoding
for instance on <tt>localhost</tt>.
</t>
<t>
- Validator applications <bcp>MUST</bcp> include protections
+ Validator applications <bcp14>MUST</bcp14> include protections
against repeated validations of the same donation statement
with the same salt and year. Specifically, when summing up
multiple donation statements for the same taxpayer and
- tax year, the <bcp>MUST</bcp> keep enough state to add
+ tax year, the <bcp14>MUST</bcp14> keep enough state to add
up the maximum total amounts per salt if multiple donation
statements are submitted with the same salt.
</t>
</section>
-<section anchor="iana" title="IANA Considerations">
+<section anchor="iana">
<name slugifiedName="name-iana-considerations">IANA Considerations</name>
<t>
IANA maintains the "Uniform Resource Identifier (URI) Schemes"
@@ -752,7 +770,7 @@ Value Encoding Value Encoding Value Encoding Value Encoding
requested to update that entry to reference this document when
published as an RFC.
</t>
- <dl indent="3" newline="false" spacing="normal" pn="section-9-2">
+ <dl indent="3" newline="false" spacing="normal">
<dt>Scheme name:</dt>
<dd> donau</dd>
<dt>Status:</dt>
@@ -779,10 +797,63 @@ Value Encoding Value Encoding Value Encoding Value Encoding
</middle>
-<back>
+<back xmlns="">
+
+
+
+
+ <references anchor="refs">
+ <name>Normative References</name>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5234.xml"/>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6234.xml"/>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8032.xml"/>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9498.xml"/>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8905.xml"/>
+
+
+ </references>
+
+ <references>
+ <name>Informational References</name>
+
+ <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml"/>
+
+
+ <reference anchor="GANA" target="https://gana.gnunet.org/">
+ <front>
+ <title>GNUnet Assigned Numbers Authority (GANA)</title>
+ <author><organization>GNUnet e.V.</organization>
+ </author>
+ <date month="April" year="2020" />
+ </front>
+ </reference>
+
+ <reference anchor="BaThesis" target="https://www.taler.net/papers/donau-thesis.pdf">
+ <front>
+ <title>Tax-deductable Privacy-Preserving Donations</title>
+ <author initials="J.C." surname="Casaburi" fullname="Johannes Casaburi">
+ <organization>Bern University of Applied Science, Bachelor Thesis</organization>
+ </author>
+ <author initials="L.M." surname="Matya" fullname="Lukas Matya">
+ <organization>Bern University of Applied Science, Bachelor Thesis</organization>
+ </author>
+ </front>
+ </reference>
+ </references>
-<section anchor="appendix-test-vectors" title="Appendix. Test Vector: Verify from URI">
+<section anchor="appendix-test-vectors">
+ <name>Appendix. Test Vector: Verify from URI</name>
<t>
This appendix shows how to verify a donation statement starting from a
received URI. Public key is fetched from the Donau base.
@@ -791,7 +862,12 @@ Value Encoding Value Encoding Value Encoding Value Encoding
<figure>
<artwork><![CDATA[
Example URI:
-donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
+donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&
+ salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&
+ total=TESTKUDOS:1&
+ sig=ED25519:
+ B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21
+ W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
Extracted fields:
- base: donau.test.taler.net
@@ -800,7 +876,8 @@ Extracted fields:
- taxid (decoded): 123/456/789
- salt: AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0
- total: TESTKUDOS:1
-- signature: ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
+- signature: ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4
+ GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30
Fetched public key for year 2025 from https://donau.test.taler.net/keys:
- pub: 2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG
@@ -808,103 +885,68 @@ Fetched public key for year 2025 from https://donau.test.taler.net/keys:
</figure>
<t>Verification steps:</t>
- <list style="numbers">
- <t>Input (URI):<br/>
-<tt>donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&total=TESTKUDOS:1&sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30</tt></t>
- <t>Parse fields:<br/>
+ <ol>
+ <li>Input (URI):<br/>
+<tt>donau://donau.test.taler.net/?year=2025&id=123%2F456%2F789&
+salt=AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0&
+total=TESTKUDOS:1&
+sig=ED25519:B14WGS43FFPEB8JMSR6W1H8M6KH9AV33JFH376R6PM2MNH4GR24FP1C93C4ZPDG21
+W5WY4SASZQ4CRS427F4WJZJFZMQ5Y4HZNXGY30</tt></li>
+ <li>Parse fields:<br/>
- base: <tt>donau.test.taler.net</tt><br/>
- year: <tt>2025</tt> (4 digits)<br/>
- taxid-enc: <tt>123%2F456%2F789</tt><br/>
- taxid (UTF-8, percent-decoded, no trimming): <tt>123/456/789</tt><br/>
- salt (ASCII): <tt>AWNFDRFT0WX45W4Y32A9DJA03S1EF66GFQZ9EV5EF9JTHWZ37WR0</tt><br/>
- total (amount string): <tt>TESTKUDOS:1</tt><br/>
- - sig (Crockford Base32, algorithm ED25519): <tt>B14WGS...XGY30</tt></t>
- <t>Public signing key (Crockford Base32) (from <tt>/keys</tt>):<br/>
-<tt>2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG</tt></t>
- <t>Hash of the donor taxpayer ID <tt>hash-donor-id</tt> = <tt>SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>:<br/>
+ - sig (Crockford Base32, algorithm ED25519): <tt>B14WGS...XGY30</tt></li>
+ <li>Public signing key (Crockford Base32) (from <tt>/keys</tt>):<br/>
+<tt>2FRN2CAK9DMDWE157W6HY97RAVSP0ZCCC08X9N6JD2MK7413XXZG</tt></li>
+ <li>Hash of the donor taxpayer ID <tt>hash-donor-id</tt> = <tt>SHA-512( UTF-8(taxid) || 0x00 || UTF-8(salt) || 0x00 )</tt>:<br/>
- length: 64 bytes<br/>
- hex:<br/>
-<tt>4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b</tt><br/>
+<tt>4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a 1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b</tt><br/>
- Crockford Base32 (for HTTP endpoints):<br/>
-<tt>9AN1W5QWBFJ4GGNRCERZ2ZD3JABCMYSN56KJ1R8TQAE8QNS9YYGY5ERBK8WW0B973PJXT5DEMSPEJPZ7HF5F706Y36GBVF6RMY9RY6R</tt></t>
- <t>Total amount encoding (<tt>TALER_AmountNBO</tt>):<br/>
+<tt>9AN1W5QWBFJ4GGNRCERZ2ZD3JABCMYSN56KJ1R8TQAE8QNS9YYGY5ERBK 8WW0B973PJXT5DEMSPEJPZ7HF5F706Y36GBVF6RMY9RY6R</tt></li>
+ <li>Total amount encoding (<tt>TALER_AmountNBO</tt>):<br/>
- currency (12 bytes): <tt>"TESTKUDOS"</tt> then <tt>0x00</tt> x 3<br/>
- value (uint64 BE): <tt>1</tt> -> <tt>0x0000000000000001</tt><br/>
- - fraction (uint32 BE): <tt>0</tt> -> <tt>0x00000000</tt></t>
- <t>Signed message <tt>M</tt> layout (network byte order, total 100 bytes):<br/>
+ - fraction (uint32 BE): <tt>0</tt> -> <tt>0x00000000</tt></li>
+ <li>Signed message <tt>M</tt> layout (network byte order, total 100 bytes):<br/>
- [0000..0003] 4 bytes <tt>size</tt>: <tt>0x00000064</tt><br/>
- [0004..0007] 4 bytes <tt>purpose</tt>: <tt>0x000005DC</tt> (1500)<br/>
- [0008..0015] 8 bytes <tt>amount.value</tt>: <tt>0x0000000000000001</tt><br/>
- [0016..0019] 4 bytes <tt>amount.fraction</tt>: <tt>0x00000000</tt><br/>
- [0020..0031] 12 bytes <tt>amount.currency</tt>: <tt>54 45 53 54 4b 55 44 4f 53 00 00 00</tt> ("TESTKUDOS\x00\x00\x00")<br/>
- [0032..0095] 64 bytes <tt>i.hash</tt>: hash of donor taxpayer ID <tt>hash-donor-id</tt><br/>
- - [0096..0099] 4 bytes <tt>year</tt>: <tt>0x000007E9</tt> (2025)</t>
- <t>Message <tt>M</tt> (hex, 100 bytes):<br/>
-<tt>00000064 000005dc 0000000000000001 00000000 544553544b55444f53000000 4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b 000007e9</tt></t>
- <t>Signature (ED25519, Crockford Base32 -> bytes):<br/>
+ - [0096..0099] 4 bytes <tt>year</tt>: <tt>0x000007E9</tt> (2025)</li>
+ <li>Message <tt>M</tt> (hex, 100 bytes):<br/>
+<tt>00000064 000005dc 0000000000000001 00000000 544553544b55444f53000000 4aaa1e16fc5be44842b863b1f17da39296ca7b3529a720e11aba9c8bd729f7a1e2bb0b 9a39c02d271da5dd15aea66ce95be78bcaf380de19a0bdbcd8a7938f1b 000007e9</tt></li>
+ <li>Signature (ED25519, Crockford Base32 -> bytes):<br/>
- length: 64 bytes<br/>
- R (first 32 bytes, hex):<br/>
<tt>5849c864837bece5a254ce0dc0c51434e2956c6393e2339b06b5054ac490c088</tt><br/>
- S (last 32 bytes, hex):<br/>
-<tt>fb05891b09fb36020f0bcf132acfee46632411de4e4bf27fe972f891fd7b0f0c</tt></t>
- <t>Public key (Ed25519, Crockford Base32 -> bytes):<br/>
+<tt>fb05891b09fb36020f0bcf132acfee46632411de4e4bf27fe972f891fd7b0f0c</tt></li>
+ <li>Public key (Ed25519, Crockford Base32 -> bytes):<br/>
- length: 32 bytes<br/>
- hex:<br/>
-<tt>13f15131534b68de38253f0d1f24f856f3607d8c6011d4d4d268a9339023ef7f</tt></t>
- <t>Verification (expected): call <tt>crypto_sign_verify_detached(sig, M, 100, pubkey)</tt>. The result <bcp14>MUST</bcp14> indicate a valid signature for this vector.</t>
- <t>Negative check (optional): flip one bit of <tt>M</tt> or <tt>sig</tt> and repeat; verification <bcp14>MUST</bcp14> fail.</t>
- </list>
+<tt>13f15131534b68de38253f0d1f24f856f3607d8c6011d4d4d268a9339023ef7f</tt></li>
+ <li>Verification (expected): call <tt>crypto_sign_verify_detached(sig, M, 100, pubkey)</tt>. The result <bcp14>MUST</bcp14> indicate a valid signature for this vector.</li>
+ <li>Negative check (optional): flip one bit of <tt>M</tt> or <tt>sig</tt> and repeat; verification <bcp14>MUST</bcp14> fail.</li>
+ </ol>
</section>
-
-
- <references anchor="refs" title="Normative References">
-
- &RFC2119;
-
- &RFC3986;
-
- &RFC8174;
-
- &RFC5234;
-
- &RFC6234;
-
- &RFC8032;
-
- &RFC9498;
-
- &RFC8905;
-
-
- </references>
-
- <references title="Informational References">
-
- &RFC4648;
-
-
- <reference anchor="GANA" target="https://gana.gnunet.org/">
- <front>
- <title>GNUnet Assigned Numbers Authority (GANA)</title>
- <author><organization>GNUnet e.V.</organization>
- </author>
- <date month="April" year="2020" />
- </front>
- </reference>
-
- <reference anchor="BaThesis" target="https://www.taler.net/papers/donau-thesis.pdf">
- <front>
- <title>Tax-deductable Privacy-Preserving Donations</title>
- <author initials="J.C." surname="Casaburi" fullname="Johannes Casaburi">
- <organization>Bern University of Applied Science, Bachelor Thesis</organization>
- </author>
- <author initials="L.M." surname="Matya" fullname="Lukas Matya">
- <organization>Bern University of Applied Science, Bachelor Thesis</organization>
- </author>
- </front>
- </reference>
- </references>
+<section numbered="false">
+ <name>Acknowledgements</name>
+ <t>
+ The authors thank Ted Hardie for his comments on an earlier version of the draft.
+ This work was funded in part by the European Commission through the
+ Horizon Europe program under project number 101135475 (TALER). It also
+ has received funding from the Swiss State Secretariat for Education,
+ Research and Innovation (SERI).
+ </t>
+</section>
<!-- Change Log
v00 2025-10-17 CG Initial version